diff --git a/applications/lofar2/libraries/ddrctrl/hdllib.cfg b/applications/lofar2/libraries/ddrctrl/hdllib.cfg index 8f92d2ddd3f4d347fdfc32811cdbcefd07fe0288..24ebbd5221d3368de0a737ed46622798f23d32ef 100644 --- a/applications/lofar2/libraries/ddrctrl/hdllib.cfg +++ b/applications/lofar2/libraries/ddrctrl/hdllib.cfg @@ -1,6 +1,6 @@ hdl_lib_name = lofar2_ddrctrl hdl_library_clause_name = lofar2_ddrctrl_lib -hdl_lib_uses_synth = technology common tech_ddr dp +hdl_lib_uses_synth = technology common tech_ddr dp io_ddr hdl_lib_uses_sim = hdl_lib_technology = @@ -8,12 +8,14 @@ synth_files = src/vhdl/ddrctrl_address_counter.vhd src/vhdl/ddrctrl_pack.vhd src/vhdl/ddrctrl_repack.vhd + src/vhdl/ddrctrl_input.vhd src/vhdl/ddrctrl.vhd test_bench_files = tb/vhdl/tb_ddrctrl_address_counter.vhd tb/vhdl/tb_ddrctrl_pack.vhd tb/vhdl/tb_ddrctrl_repack.vhd + tb/vhdl/tb_ddrctrl_input.vhd tb/vhdl/tb_ddrctrl.vhd regression_test_vhdl = diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd index 838e8f5c89576d1b3a336d91e8d2ab180e863269..9577a0ca48378e3eede404c1f93486941a0fa9e2 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd @@ -32,29 +32,46 @@ -- https://support.astron.nl/confluence/display/SBe/VHDL+design+patterns+for+RTL+coding -- The maximum value of the address is determend by g_tech_ddr. -LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib; +LIBRARY IEEE, technology_lib, tech_ddr_lib, common_lib, dp_lib, io_ddr_lib; USE IEEE.std_logic_1164.ALL; USE IEEE.numeric_std.ALL; USE technology_lib.technology_pkg.ALL; +USE technology_lib.technology_select_pkg.ALL; USE tech_ddr_lib.tech_ddr_pkg.ALL; USE common_lib.common_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; +USE io_ddr_lib.ALL; ENTITY ddrctrl IS GENERIC ( g_tech_ddr : t_c_tech_ddr; -- type of memory g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation + g_technology : NATURAL := c_tech_select_default; g_nof_streams : NATURAL := 12; -- number of input streams - g_data_w : NATURAL := 14 -- data with of input data vectors - ); + g_data_w : NATURAL := 14; -- data with of input data vectors + g_wr_fifo_depth : NATURAL := 256; -- defined at DDR side of the FIFO, >=16 and independent of wr burst size, default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K + g_rd_fifo_depth : NATURAL := 256 -- defined at DDR side of the FIFO, >=16 AND > max number of rd burst sizes (so > c_rd_fifo_af_margin), default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K + ); PORT ( clk : IN STD_LOGIC := '0'; rst : IN STD_LOGIC; in_sosi_arr : IN t_dp_sosi_arr; -- input data out_of : OUT NATURAL; -- amount of internal overflow this output - out_mosi : OUT t_mem_ctlr_mosi -- output data + + term_ctrl_out : OUT t_tech_ddr3_phy_terminationcontrol; + term_ctrl_in : IN t_tech_ddr3_phy_terminationcontrol := c_tech_ddr3_phy_terminationcontrol_rst; + + -- DDR3 PHY external interface + phy3_in : IN t_tech_ddr3_phy_in := c_tech_ddr3_phy_in_x; + phy3_io : INOUT t_tech_ddr3_phy_io; + phy3_ou : OUT t_tech_ddr3_phy_ou; + + -- DDR4 PHY external interface + phy4_in : IN t_tech_ddr4_phy_in := c_tech_ddr4_phy_in_x; + phy4_io : INOUT t_tech_ddr4_phy_io; + phy4_ou : OUT t_tech_ddr4_phy_ou ); END ddrctrl; @@ -62,16 +79,25 @@ END ddrctrl; ARCHITECTURE str OF ddrctrl IS -- constant for readability - CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; -- the input data with for ddrctrl_repack - + CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; -- the input data width for ddrctrl_repack 168 + CONSTANT c_io_ddr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- signals for connecting the components SIGNAL data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); SIGNAL sosi : t_dp_sosi := c_dp_sosi_init; - SIGNAL a_of : NATURAL := 0; + SIGNAL adr : NATURAL := 0; + SIGNAL a_of : NATURAL := 0; + SIGNAL ctrl_clk : STD_LOGIC := '0'; + SIGNAL ctrl_rst : STD_LOGIC := '0'; + SIGNAL wr_sosi : t_dp_sosi := c_dp_sosi_init; + SIGNAL wr_siso : t_dp_siso; + SIGNAL rd_siso : t_dp_siso; + SIGNAL dvr_mosi : t_mem_ctlr_mosi; BEGIN + dvr_mosi.address <= TO_UVEC(adr, dvr_mosi.address'length); + -- makes one data vector out of all the data from the t_dp_sosi_arr u_pack : ENTITY work.ddrctrl_pack GENERIC MAP( @@ -112,8 +138,83 @@ BEGIN rst => rst, in_sosi => sosi, -- input data in_of => a_of, - out_mosi => out_mosi, -- output data - out_of => out_of + out_sosi => wr_sosi, -- output data + out_of => out_of, + out_adr => adr + ); + + -- functions as a fifo buffer for input data into the sdram stick. also manages input to sdram stick. + u_io_ddr : ENTITY io_ddr_lib.io_ddr + GENERIC MAP( + g_sim_model => g_sim_model, + g_technology => g_technology, + g_tech_ddr => g_tech_ddr, + g_cross_domain_dvr_ctlr => FALSE, + g_wr_data_w => c_io_ddr_data_w, + g_wr_fifo_depth => g_wr_fifo_depth, + g_rd_fifo_depth => g_rd_fifo_depth, + g_rd_data_w => c_io_ddr_data_w, + g_wr_flush_mode => "VAL", + g_wr_flush_use_channel => FALSE, + g_wr_flush_start_channel => 0, + g_wr_flush_nof_channels => 1 + ) + PORT MAP( + + -- DDR reference clock + ctlr_ref_clk => clk, + ctlr_ref_rst => rst, + + -- DDR controller clock domain + ctlr_clk_out => ctrl_clk, + ctlr_rst_out => ctrl_rst, + + ctlr_clk_in => ctrl_clk, + ctlr_rst_in => ctrl_rst, + + -- MM clock + reset + mm_rst => rst, + mm_clk => clk, + + -- MM interface + reg_io_ddr_mosi => open, + reg_io_ddr_miso => open, + + -- Driver clock domain + dvr_clk => clk, + dvr_rst => rst, + + dvr_miso => open, + dvr_mosi => dvr_mosi, + + -- Write FIFO clock domain + wr_clk => clk, + wr_rst => rst, + + wr_fifo_usedw => open, + wr_sosi => wr_sosi, + wr_siso => wr_siso, + + -- Read FIFO clock domain + rd_clk => clk, + rd_rst => rst, + + rd_fifo_usedw => open, + rd_sosi => open, + rd_siso => rd_siso, + + term_ctrl_out => term_ctrl_out, + term_ctrl_in => term_ctrl_in, + + -- DDR3 PHY external interface + phy3_in => phy3_in, + phy3_io => phy3_io, + phy3_ou => phy3_ou, + + -- DDR4 PHY external interface + phy4_in => phy4_in, + phy4_io => phy4_io, + phy4_ou => phy4_ou ); END str; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd index 25d43e825ad5bd8bd5babdb72071004b391f9945..8c2fad8bce712d12678a5ed6b4a9bd816ce857f0 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd @@ -49,8 +49,9 @@ ENTITY ddrctrl_address_counter IS rst : IN STD_LOGIC; in_sosi : IN t_dp_sosi; -- input data in_of : IN NATURAL; - out_mosi : OUT t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; -- output data - out_of : OUT NATURAL + out_sosi : OUT t_dp_sosi := c_dp_sosi_init; -- output data + out_of : OUT NATURAL; + out_adr : OUT NATURAL ); END ddrctrl_address_counter; @@ -60,7 +61,7 @@ ARCHITECTURE rtl OF ddrctrl_address_counter IS -- constants for readability CONSTANT c_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- the with of the input data and output data, 576 CONSTANT c_adr_w : NATURAL := sel_a_b(g_sim_model, 4, func_tech_ddr_ctlr_address_w( g_tech_ddr )); -- the lengt of the address vector, for simulation this is smaller, otherwise the simulation would take to long, 27 - CONSTANT c_max_adr : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0) := STD_LOGIC_VECTOR(TO_UVEC(2**(c_adr_w)-1, c_adr_w)); -- the maximal address that is possible within the vector length of the address + CONSTANT c_max_adr : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address -- type for statemachine TYPE t_state IS (RESET, COUNTING, MAX, IDLE); @@ -68,13 +69,14 @@ ARCHITECTURE rtl OF ddrctrl_address_counter IS -- record for readability TYPE t_reg IS RECORD state : t_state; - out_mosi : t_mem_ctlr_mosi; + out_sosi : t_dp_sosi; out_of : NATURAL; s_in_sosi : t_dp_sosi; s_in_of : NATURAL; + s_adr : NATURAL; END RECORD; - CONSTANT c_t_reg_init : t_reg := (RESET, c_mem_ctlr_mosi_rst, 0, c_dp_sosi_init, 0); + CONSTANT c_t_reg_init : t_reg := (RESET, c_dp_sosi_init, 0, c_dp_sosi_init, 0, 0); -- signals for readability @@ -92,8 +94,8 @@ BEGIN BEGIN v := q_reg; - v.out_mosi.wrdata(c_data_w-1 DOWNTO 0) := q_reg.s_in_sosi.data(c_data_w - 1 DOWNTO 0); - v.out_mosi.wr := q_reg.s_in_sosi.valid; + v.out_sosi.data(c_data_w-1 DOWNTO 0) := q_reg.s_in_sosi.data(c_data_w - 1 DOWNTO 0); + v.out_sosi.valid := q_reg.s_in_sosi.valid; v.out_of := q_reg.s_in_of; v.s_in_sosi := in_sosi; v.s_in_of := in_of; @@ -101,13 +103,13 @@ BEGIN CASE q_reg.state IS WHEN RESET => - v.out_mosi.address(c_adr_w-1 DOWNTO 0) := (OTHERS => '0'); + v.s_adr := 0; WHEN COUNTING => - v.out_mosi.address(c_adr_w-1 DOWNTO 0) := STD_LOGIC_VECTOR(TO_UVEC(TO_UINT(q_reg.out_mosi.address)+1, c_adr_w)); + v.s_adr := q_reg.s_adr+1; WHEN MAX => - v.out_mosi.address(c_adr_w-1 DOWNTO 0) := (OTHERS => '0'); + v.s_adr := 0; WHEN IDLE => @@ -115,7 +117,7 @@ BEGIN IF rst = '1' THEN v.state := RESET; - ELSIF q_reg.out_mosi.address(c_adr_w-1 DOWNTO 0) = c_max_adr(c_adr_w-1 DOWNTO 0) AND in_sosi.valid = '1' THEN + ELSIF q_reg.s_adr = c_max_adr AND in_sosi.valid = '1' THEN v.state := MAX; ELSIF in_sosi.valid = '1' THEN v.state := COUNTING; @@ -127,7 +129,8 @@ BEGIN END PROCESS; -- fill outputs - out_mosi <= q_reg.out_mosi; + out_sosi <= q_reg.out_sosi; out_of <= q_reg.out_of; + out_adr <= q_reg.s_adr; END rtl; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd index 8b56c9ddcf22d7455e0099fbc19f4179ba6e526c..ff2f25739c6e171f8d4739cbab2604826d7f58a9 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd @@ -40,7 +40,9 @@ ENTITY tb_ddrctrl IS g_nof_streams : POSITIVE := 12; -- number of input streams g_data_w : NATURAL := 14; -- data with of input data vectors g_sim_length : NATURAL := 52 - + g_technology : NATURAL := c_tech_select_default; + g_wr_fifo_depth : NATURAL := 256; -- defined at DDR side of the FIFO, >=16 and independent of wr burst size, default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K + g_rd_fifo_depth : NATURAL := 256 -- defined at DDR side of the FIFO, >=16 AND > max number of rd burst sizes (so > c_rd_fifo_af_margin), default >= 256 because 32b*256 fits in 1 M9K so c_ctlr_data_w=256b will require 8 M9K ); END tb_ddrctrl; @@ -195,15 +197,17 @@ BEGIN GENERIC MAP ( g_tech_ddr => g_tech_ddr, g_sim_model => g_sim_model, + g_technology => g_technology, g_nof_streams => g_nof_streams, - g_data_w => g_data_w + g_data_w => g_data_w, + g_wr_fifo_depth => g_wr_fifo_depth, + g_rd_fifo_depth => g_rd_fifo_depth ) PORT MAP ( clk => clk, rst => rst, in_sosi_arr => in_sosi_arr, out_of => out_of, - out_mosi => out_mosi ); END tb; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd index a17f098b594c673887acdc59f982a8dd87d515f2..14f4d34b1982c2f65f0fe7055c58e0b7c4f50b1d 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_address_counter.vhd @@ -61,7 +61,8 @@ ARCHITECTURE tb OF tb_ddrctrl_address_counter IS SIGNAL in_of : NATURAL := 0; -- signal which contains the amount of overflow -- output signal from ddrctrl_address_counter.vhd - SIGNAL out_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; -- signal which is the output from ddrctrl_address_counter.vhd + SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init; -- signal which is the output from ddrctrl_address_counter.vhd + SIGNAL out_adr : NATURAL := 0; SIGNAL out_of : NATURAL := 0; -- signal which is the output from ddrctrl_address_counter.vhd -- testbench signals @@ -112,8 +113,8 @@ BEGIN ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; END PROCESS; - -- generating compare data for out_mosi - p_out_mosi : PROCESS + -- generating compare data for out_sosi + p_out_sosi : PROCESS BEGIN WAIT UNTIL rising_edge(clk); if rising_edge(clk) THEN @@ -128,10 +129,10 @@ BEGIN q_rst <= rst; END IF; IF q_rst = '1' THEN - IF lag_due_reset + TO_UINT(out_mosi.address) >= c_adr_size THEN - lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address)-c_adr_size; + IF lag_due_reset + out_adr >= c_adr_size THEN + lag_due_reset <= lag_due_reset+out_adr-c_adr_size; ELSE - lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address); + lag_due_reset <= lag_due_reset+out_adr; END IF; END IF; END PROCESS; @@ -142,8 +143,8 @@ BEGIN BEGIN WAIT UNTIL rising_edge(clk); IF rising_edge(clk) THEN - ASSERT q_q_in_data(c_data_w-1 DOWNTO 0) = out_mosi.wrdata(c_data_w-1 DOWNTO 0) REPORT "in_sosi.data does not match out_mosi.wrdata" SEVERITY ERROR; - ASSERT q_q_in_data_enable = out_mosi.wr REPORT "in_sosi.valid does not match out_mosi.wr" SEVERITY ERROR; + ASSERT q_q_in_data(c_data_w-1 DOWNTO 0) = out_sosi.data(c_data_w-1 DOWNTO 0) REPORT "in_sosi.data does not match out_sosi.wrdata" SEVERITY ERROR; + ASSERT q_q_in_data_enable = out_sosi.valid REPORT "in_sosi.valid does not match out_sosi.wr" SEVERITY ERROR; ASSERT q_q_in_of = out_of REPORT "in_of does not match out_of" SEVERITY ERROR; END IF; END PROCESS; @@ -162,13 +163,13 @@ BEGIN BEGIN FOR I IN 0 TO c_adr_size-1 LOOP IF I >= q_lag_due_reset THEN - ASSERT I-q_lag_due_reset = TO_UINT(out_mosi.address) REPORT "Wrong address, 1, I = " & NATURAL'image(I-q_lag_due_reset) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address)) SEVERITY ERROR; + ASSERT I-q_lag_due_reset = out_adr REPORT "Wrong address, 1, I = " & NATURAL'image(I-q_lag_due_reset) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR; ELSE - ASSERT (I-q_lag_due_reset)+c_adr_size = TO_UINT(out_mosi.address) REPORT "Wrong address, 2, I = " & NATURAL'image((I-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address)) SEVERITY ERROR; + ASSERT (I-q_lag_due_reset)+c_adr_size = out_adr REPORT "Wrong address, 2, I = " & NATURAL'image((I-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR; END IF; - WAIT UNTIL out_mosi.wr = '1'; + WAIT UNTIL out_sosi.valid = '1'; IF q_q_rst = '1' THEN - WAIT UNTIL out_mosi.wr = '1'; + WAIT UNTIL out_sosi.valid = '1'; END IF; END LOOP; END PROCESS; @@ -186,8 +187,9 @@ BEGIN in_sosi => in_sosi, in_of => in_of, - out_mosi => out_mosi, - out_of => out_of + out_sosi => out_sosi, + out_of => out_of, + out_adr => out_adr ); END tb;