------------------------------------------------------------------------------- -- -- Copyright (C) 2011 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see <http://www.gnu.org/licenses/>. -- ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib; USE IEEE.STD_LOGIC_1164.ALL; USE common_lib.common_pkg.ALL; USE IEEE.NUMERIC_STD.ALL; PACKAGE ddr3_pkg IS -- DDR3 (definitions similar as in ug_altmemphy.pdf) TYPE t_c_ddr3_phy IS RECORD a_w : NATURAL; -- = 16; a_row_w : NATURAL; -- = 16; -- = a_w, row address width, via a_w lines a_col_w : NATURAL; -- = 10; -- <= a_w, col address width, via a_w lines ba_w : NATURAL; -- = 3; dq_w : NATURAL; -- = 64; dqs_w : NATURAL; -- = 8; -- = dq_w / nof_dq_per_dqs; dm_w : NATURAL; -- = 8; cs_w : NATURAL; -- = 2; clk_w : NATURAL; -- = 2; END RECORD; CONSTANT c_ddr3_phy : t_c_ddr3_phy := (16, 16, 10, 3, 64, 8, 8, 2, 2); CONSTANT c_ddr3_phy_4g : t_c_ddr3_phy := (15, 15, 10, 3, 64, 8, 8, 2, 2); TYPE t_ddr3_phy_in IS RECORD evt : STD_LOGIC; oct_rup : STD_LOGIC; oct_rdn : STD_LOGIC; nc : STD_LOGIC; -- not connected, needed to be able to initialize constant record which has to have more than one field in VHDL END RECORD; TYPE t_ddr3_phy_io IS RECORD -- Do not use this type in Quartus! Use the _sel version instead. dq : STD_LOGIC_VECTOR(c_ddr3_phy.dq_w-1 DOWNTO 0); -- data bus dqs : STD_LOGIC_VECTOR(c_ddr3_phy.dqs_w-1 DOWNTO 0); -- data strobe bus dqs_n : STD_LOGIC_VECTOR(c_ddr3_phy.dqs_w-1 DOWNTO 0); clk : STD_LOGIC_VECTOR(c_ddr3_phy.clk_w-1 DOWNTO 0); -- clock, positive edge clock clk_n : STD_LOGIC_VECTOR(c_ddr3_phy.clk_w-1 DOWNTO 0); -- clock, negative edge clock scl : STD_LOGIC; -- I2C sda : STD_LOGIC; END RECORD; TYPE t_ddr3_phy_ou IS RECORD a : STD_LOGIC_VECTOR(c_ddr3_phy.a_w-1 DOWNTO 0); -- row and column address ba : STD_LOGIC_VECTOR(c_ddr3_phy.ba_w-1 DOWNTO 0); -- bank address dm : STD_LOGIC_VECTOR(c_ddr3_phy.dm_w-1 DOWNTO 0); -- data mask bus cas_n : STD_LOGIC; --_VECTOR(0 DOWNTO 0); -- column address strobe ras_n : STD_LOGIC; --_VECTOR(0 DOWNTO 0); -- row address strobe we_n : STD_LOGIC; --_VECTOR(0 DOWNTO 0); -- write enable signal reset_n : STD_LOGIC; -- reset signal odt : STD_LOGIC_VECTOR(c_ddr3_phy.cs_w-1 DOWNTO 0); -- on-die termination control signal cke : STD_LOGIC_VECTOR(c_ddr3_phy.cs_w-1 DOWNTO 0); -- clock enable cs_n : STD_LOGIC_VECTOR(c_ddr3_phy.cs_w-1 DOWNTO 0); -- chip select END RECORD; CONSTANT c_ddr3_phy_in_rst : t_ddr3_phy_in := ('0', 'X', 'X', 'X'); CONSTANT c_ddr3_phy_io_rst : t_ddr3_phy_io := ((OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), '0', '0'); CONSTANT c_ddr3_phy_ou_rst : t_ddr3_phy_ou := ((OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), '0', '0', '0', '0', (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0')); TYPE t_ddr3_phy_in_arr IS ARRAY(NATURAL RANGE <>) OF t_ddr3_phy_in; TYPE t_ddr3_phy_io_arr IS ARRAY(NATURAL RANGE <>) OF t_ddr3_phy_io; TYPE t_ddr3_phy_ou_arr IS ARRAY(NATURAL RANGE <>) OF t_ddr3_phy_ou; TYPE t_ddr3_addr IS RECORD chip : STD_LOGIC_VECTOR(ceil_log2(c_ddr3_phy.cs_w) -1 DOWNTO 0); -- Note: The controller interprets the chip address as logical address (NOT individual chip sel lines), hence ceil_log2 bank : STD_LOGIC_VECTOR( c_ddr3_phy.ba_w -1 DOWNTO 0); row : STD_LOGIC_VECTOR( c_ddr3_phy.a_row_w-1 DOWNTO 0); column : STD_LOGIC_VECTOR( c_ddr3_phy.a_col_w-1 DOWNTO 0); END RECORD; TYPE t_ddr3_addr_arr IS ARRAY(NATURAL RANGE <>) OF t_ddr3_addr; CONSTANT c_ddr3_ctlr_data_w : NATURAL := 256; -- = 64 (PHY dq width) * 2 (use both PHY clock edges) * 2 (PHY transfer at double rate) CONSTANT c_ddr3_ctlr_rsl : NATURAL := c_ddr3_ctlr_data_w / c_ddr3_phy.dq_w; -- =4 CONSTANT c_ddr3_ctlr_rsl_w : NATURAL := ceil_log2(c_ddr3_ctlr_rsl); CONSTANT c_ddr3_ctlr_maxburstsize : NATURAL := 64; CONSTANT c_ddr3_ctlr_maxburstsize_w : NATURAL := ceil_log2(c_ddr3_ctlr_maxburstsize+1); CONSTANT c_ddr3_ctrl_nof_latent_reads : NATURAL := 100; -- The downside to having a command cue: even after de-asserting read requests, the ALTMEMPHY keeps processing your cued read requests. -- This makes sure 100 words are still available in the read FIFO after it de-asserted its siso.ready signal towards the ddr3 read side. CONSTANT c_ddr3_phy_oct_w : NATURAL := 14; CONSTANT c_ddr3_phy_oct_rs : STD_LOGIC_VECTOR := TO_UVEC(0, c_ddr3_phy_oct_w); CONSTANT c_ddr3_phy_oct_rt : STD_LOGIC_VECTOR := TO_UVEC(0, c_ddr3_phy_oct_w); CONSTANT c_ddr3_addr_lo : t_ddr3_addr := ((OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0'), (OTHERS=>'0')); CONSTANT c_ddr3_address_lo : NATURAL := 0; CONSTANT c_ddr3_addr_hi_4gb : t_ddr3_addr := ((OTHERS=>'1'), (OTHERS=>'1'), (OTHERS=>'1'), TO_UVEC(2**c_ddr3_phy_4g.a_col_w - c_ddr3_ctlr_rsl, c_ddr3_phy_4g.a_col_w)); -- 4 rows * 1024 cols * 64 bits / 128bits per associative mem array element = 2048 = default ALTMEMPHY mem_model array depth. CONSTANT c_ddr3_addr_hi_sim : t_ddr3_addr := ((OTHERS=>'0'), (OTHERS=>'0'), TO_UVEC(3, c_ddr3_phy.a_row_w), TO_UVEC(2**c_ddr3_phy_4g.a_col_w - c_ddr3_ctlr_rsl, c_ddr3_phy_4g.a_col_w)); CONSTANT c_ddr3_address_hi_sim : NATURAL := 4092; --TB uses generated mem model with 2ki addresses of 128k - so the array holds 4096 64-bit words. End address is 4092 (resolution=4: last write=4092,4093,4094,4095.) TYPE t_ddr3_seq IS RECORD wr_chunksize : POSITIVE; -- := 64; wr_nof_chunks : POSITIVE; -- := 1; rd_chunksize : POSITIVE; -- := 16; rd_nof_chunks : POSITIVE; -- := 4; gapsize : NATURAL; -- := 0; nof_blocks : POSITIVE; -- := 5; END RECORD; CONSTANT c_ddr3_seq : t_ddr3_seq := (64, 1, 16, 4, 0, 5); -- Manually derived VHDL entity from Verilog module $RADIOHDL/libraries/technology/ip_stratixiv/ddr3_uphy_4g_800_master/generated/ip_stratixiv_ddr3_uphy_4g_800_master.v COMPONENT ip_stratixiv_ddr3_uphy_4g_800_master IS PORT ( pll_ref_clk : IN STD_LOGIC; -- pll_ref_clk.clk global_reset_n : IN STD_LOGIC; -- global_reset.reset_n soft_reset_n : IN STD_LOGIC; -- soft_reset.reset_n afi_clk : OUT STD_LOGIC; -- afi_clk.clk afi_half_clk : OUT STD_LOGIC; -- afi_half_clk.clk afi_reset_n : OUT STD_LOGIC; -- afi_reset.reset_n mem_a : OUT STD_LOGIC_VECTOR(14 DOWNTO 0); -- memory.mem_a mem_ba : OUT STD_LOGIC_VECTOR(2 DOWNTO 0); -- .mem_ba mem_ck : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_ck mem_ck_n : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_ck_n mem_cke : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_cke mem_cs_n : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_cs_n mem_dm : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- .mem_dm mem_ras_n : OUT STD_LOGIC; -- .mem_ras_n mem_cas_n : OUT STD_LOGIC; -- .mem_cas_n mem_we_n : OUT STD_LOGIC; -- .mem_we_n mem_reset_n : OUT STD_LOGIC; -- .mem_reset_n mem_dq : INOUT STD_LOGIC_VECTOR(63 DOWNTO 0); -- .mem_dq mem_dqs : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- .mem_dqs mem_dqs_n : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- .mem_dqs_n mem_odt : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_odt avl_ready : OUT STD_LOGIC; -- avl.waitrequest_n avl_burstbegin : IN STD_LOGIC; -- .beginbursttransfer avl_addr : IN STD_LOGIC_VECTOR(26 DOWNTO 0); -- .address avl_rdata_valid : OUT STD_LOGIC; -- .readdatavalid avl_rdata : OUT STD_LOGIC_VECTOR(255 DOWNTO 0); -- .readdata avl_wdata : IN STD_LOGIC_VECTOR(255 DOWNTO 0); -- .writedata avl_be : IN STD_LOGIC_VECTOR(31 DOWNTO 0); -- .byteenable avl_read_req : IN STD_LOGIC; -- .read avl_write_req : IN STD_LOGIC; -- .write avl_size : IN STD_LOGIC_VECTOR(6 DOWNTO 0); -- .burstcount local_init_done : OUT STD_LOGIC; -- status.local_init_done local_cal_success : OUT STD_LOGIC; -- .local_cal_success local_cal_fail : OUT STD_LOGIC; -- .local_cal_fail oct_rdn : IN STD_LOGIC; -- oct.rdn oct_rup : IN STD_LOGIC; -- .rup seriesterminationcontrol : OUT STD_LOGIC_VECTOR(13 DOWNTO 0); -- oct_sharing.seriesterminationcontrol parallelterminationcontrol : OUT STD_LOGIC_VECTOR(13 DOWNTO 0); -- .parallelterminationcontrol pll_mem_clk : OUT STD_LOGIC; -- pll_sharing.pll_mem_clk pll_write_clk : OUT STD_LOGIC; -- .pll_write_clk pll_write_clk_pre_phy_clk : OUT STD_LOGIC; -- .pll_write_clk_pre_phy_clk pll_addr_cmd_clk : OUT STD_LOGIC; -- .pll_addr_cmd_clk pll_locked : OUT STD_LOGIC; -- .pll_locked pll_avl_clk : OUT STD_LOGIC; -- .pll_avl_clk pll_config_clk : OUT STD_LOGIC; -- .pll_config_clk dll_delayctrl : OUT STD_LOGIC_VECTOR(5 DOWNTO 0) -- dll_sharing.dll_delayctrl ); END COMPONENT; -- Manually derived VHDL entity from Verilog module $RADIOHDL/libraries/technology/ip_stratixiv/ddr3_uphy_4g_800_slave/generated/ip_stratixiv_ddr3_uphy_4g_800_slave.v -- . diff with master is that only master has oct_* inputs and that the *terminationcontrol are inputs for the slave COMPONENT ip_stratixiv_ddr3_uphy_4g_800_slave IS PORT ( pll_ref_clk : IN STD_LOGIC; -- pll_ref_clk.clk global_reset_n : IN STD_LOGIC; -- global_reset.reset_n soft_reset_n : IN STD_LOGIC; -- soft_reset.reset_n afi_clk : OUT STD_LOGIC; -- afi_clk.clk afi_half_clk : OUT STD_LOGIC; -- afi_half_clk.clk afi_reset_n : OUT STD_LOGIC; -- afi_reset.reset_n mem_a : OUT STD_LOGIC_VECTOR(14 DOWNTO 0); -- memory.mem_a mem_ba : OUT STD_LOGIC_VECTOR(2 DOWNTO 0); -- .mem_ba mem_ck : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_ck mem_ck_n : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_ck_n mem_cke : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_cke mem_cs_n : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_cs_n mem_dm : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- .mem_dm mem_ras_n : OUT STD_LOGIC; -- .mem_ras_n mem_cas_n : OUT STD_LOGIC; -- .mem_cas_n mem_we_n : OUT STD_LOGIC; -- .mem_we_n mem_reset_n : OUT STD_LOGIC; -- .mem_reset_n mem_dq : INOUT STD_LOGIC_VECTOR(63 DOWNTO 0); -- .mem_dq mem_dqs : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- .mem_dqs mem_dqs_n : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- .mem_dqs_n mem_odt : OUT STD_LOGIC_VECTOR(1 DOWNTO 0); -- .mem_odt avl_ready : OUT STD_LOGIC; -- avl.waitrequest_n avl_burstbegin : IN STD_LOGIC; -- .beginbursttransfer avl_addr : IN STD_LOGIC_VECTOR(26 DOWNTO 0); -- .address avl_rdata_valid : OUT STD_LOGIC; -- .readdatavalid avl_rdata : OUT STD_LOGIC_VECTOR(255 DOWNTO 0); -- .readdata avl_wdata : IN STD_LOGIC_VECTOR(255 DOWNTO 0); -- .writedata avl_be : IN STD_LOGIC_VECTOR(31 DOWNTO 0); -- .byteenable avl_read_req : IN STD_LOGIC; -- .read avl_write_req : IN STD_LOGIC; -- .write avl_size : IN STD_LOGIC_VECTOR(6 DOWNTO 0); -- .burstcount local_init_done : OUT STD_LOGIC; -- status.local_init_done local_cal_success : OUT STD_LOGIC; -- .local_cal_success local_cal_fail : OUT STD_LOGIC; -- .local_cal_fail seriesterminationcontrol : IN STD_LOGIC_VECTOR(13 DOWNTO 0); -- oct_sharing.seriesterminationcontrol parallelterminationcontrol : IN STD_LOGIC_VECTOR(13 DOWNTO 0); -- .parallelterminationcontrol pll_mem_clk : OUT STD_LOGIC; -- pll_sharing.pll_mem_clk pll_write_clk : OUT STD_LOGIC; -- .pll_write_clk pll_write_clk_pre_phy_clk : OUT STD_LOGIC; -- .pll_write_clk_pre_phy_clk pll_addr_cmd_clk : OUT STD_LOGIC; -- .pll_addr_cmd_clk pll_locked : OUT STD_LOGIC; -- .pll_locked pll_avl_clk : OUT STD_LOGIC; -- .pll_avl_clk pll_config_clk : OUT STD_LOGIC; -- .pll_config_clk dll_delayctrl : OUT STD_LOGIC_VECTOR(5 DOWNTO 0) -- dll_sharing.dll_delayctrl ); END COMPONENT; COMPONENT alt_mem_if_ddr3_mem_model_top_ddr3_mem_if_dm_pins_en_mem_if_dqsn_en IS GENERIC ( MEM_IF_ADDR_WIDTH : INTEGER := 0; MEM_IF_ROW_ADDR_WIDTH : INTEGER := 0; MEM_IF_COL_ADDR_WIDTH : INTEGER := 0; MEM_IF_CS_PER_RANK : INTEGER := 0; MEM_IF_CONTROL_WIDTH : INTEGER := 0; MEM_IF_DQS_WIDTH : INTEGER := 0; MEM_IF_CS_WIDTH : INTEGER := 0; MEM_IF_BANKADDR_WIDTH : INTEGER := 0; MEM_IF_DQ_WIDTH : INTEGER := 0; MEM_IF_CK_WIDTH : INTEGER := 0; MEM_IF_CLK_EN_WIDTH : INTEGER := 0; DEVICE_WIDTH : INTEGER := 1; MEM_TRCD : INTEGER := 0; MEM_TRTP : INTEGER := 0; MEM_DQS_TO_CLK_CAPTURE_DELAY : INTEGER := 0; MEM_CLK_TO_DQS_CAPTURE_DELAY : INTEGER := 0; MEM_IF_ODT_WIDTH : INTEGER := 0; MEM_MIRROR_ADDRESSING_DEC : INTEGER := 0; MEM_REGDIMM_ENABLED : BOOLEAN := FALSE; DEVICE_DEPTH : INTEGER := 1; MEM_GUARANTEED_WRITE_INIT : BOOLEAN := FALSE; MEM_VERBOSE : BOOLEAN := TRUE; MEM_INIT_EN : BOOLEAN := FALSE; MEM_INIT_FILE : STRING := ""; DAT_DATA_WIDTH : INTEGER := 32 ); PORT ( mem_a : IN STD_LOGIC_VECTOR(14 DOWNTO 0) := (OTHERS => 'X'); -- mem_a mem_ba : IN STD_LOGIC_VECTOR(2 DOWNTO 0) := (OTHERS => 'X'); -- mem_ba mem_ck : IN STD_LOGIC_VECTOR(1 DOWNTO 0) := (OTHERS => 'X'); -- mem_ck mem_ck_n : IN STD_LOGIC_VECTOR(1 DOWNTO 0) := (OTHERS => 'X'); -- mem_ck_n mem_cke : IN STD_LOGIC_VECTOR(1 DOWNTO 0) := (OTHERS => 'X'); -- mem_cke mem_cs_n : IN STD_LOGIC_VECTOR(1 DOWNTO 0) := (OTHERS => 'X'); -- mem_cs_n mem_dm : IN STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => 'X'); -- mem_dm mem_ras_n : IN STD_LOGIC_VECTOR(0 DOWNTO 0) := (OTHERS => 'X'); -- mem_ras_n mem_cas_n : IN STD_LOGIC_VECTOR(0 DOWNTO 0) := (OTHERS => 'X'); -- mem_cas_n mem_we_n : IN STD_LOGIC_VECTOR(0 DOWNTO 0) := (OTHERS => 'X'); -- mem_we_n mem_reset_n : IN STD_LOGIC := 'X'; -- mem_reset_n mem_dq : INOUT STD_LOGIC_VECTOR(63 DOWNTO 0) := (OTHERS => 'X'); -- mem_dq mem_dqs : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => 'X'); -- mem_dqs mem_dqs_n : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => 'X'); -- mem_dqs_n mem_odt : IN STD_LOGIC_VECTOR(1 DOWNTO 0) := (OTHERS => 'X') -- mem_odt ); END COMPONENT alt_mem_if_ddr3_mem_model_top_ddr3_mem_if_dm_pins_en_mem_if_dqsn_en; END ddr3_pkg; PACKAGE BODY ddr3_pkg IS END ddr3_pkg;