From be80aefb1f64daf85e4592ffefa2ad1aa30d8d56 Mon Sep 17 00:00:00 2001 From: JobvanWee <wee@astron.nl> Date: Thu, 31 Mar 2022 08:29:25 +0200 Subject: [PATCH] Ready for Review. --- .../libraries/ddrctrl/src/vhdl/ddrctrl.vhd | 50 +++++++++++++------ .../src/vhdl/ddrctrl_address_counter.vhd | 4 +- .../libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd | 40 +++++++-------- .../tb/vhdl/tb_ddrctrl_address_counter.vhd | 25 +++++++--- .../ddrctrl/tb/vhdl/tb_ddrctrl_input.vhd | 41 +++++++++------ 5 files changed, 99 insertions(+), 61 deletions(-) diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd index 0a2afbc86e..070e230f95 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd @@ -50,10 +50,8 @@ ENTITY ddrctrl IS 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_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 - ); + g_data_w : NATURAL := 14 -- data with of input data vectors + ); PORT ( clk : IN STD_LOGIC := '0'; rst : IN STD_LOGIC; @@ -67,12 +65,12 @@ ENTITY ddrctrl IS 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; @@ -84,11 +82,17 @@ 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 width for ddrctrl_repack 168 - CONSTANT c_io_ddr_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); + 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 ); + CONSTANT c_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 + CONSTANT c_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 + CONSTANT c_burstsize : NATURAL := 64; -- max burstsize for max troughput + CONSTANT c_bitshift_adr : NATURAL := ceil_log2(c_burstsize); + CONSTANT c_adr_w : NATURAL := 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 : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address + CONSTANT c_zeros : STD_LOGIC_VECTOR(c_bitshift_adr-1 DOWNTO 0) := (OTHERS => '0'); -- signals for connecting the components - SIGNAL sosi : t_dp_sosi := c_dp_sosi_init; SIGNAL adr : NATURAL := 0; SIGNAL a_of : NATURAL := 0; SIGNAL ctrl_clk : STD_LOGIC; @@ -97,13 +101,29 @@ ARCHITECTURE str OF ddrctrl IS SIGNAL wr_siso : t_dp_siso; SIGNAL rd_siso : t_dp_siso; SIGNAL dvr_mosi : t_mem_ctlr_mosi; + SIGNAL dvr_miso : t_mem_ctlr_miso; + BEGIN - dvr_mosi.address <= TO_UVEC(adr, dvr_mosi.address'length); - dvr_mosi.burstbegin <= wr_sosi.valid; + p_burst : PROCESS(adr) + BEGIN + IF TO_UVEC(adr, c_adr_w)(c_bitshift_adr-1 DOWNTO 0) = c_zeros THEN + dvr_mosi.burstbegin <= '1'; + IF adr = 0 THEN + dvr_mosi.address <= TO_UVEC(c_max_adr-c_burstsize, dvr_mosi.address'length); + ELSE + dvr_mosi.address <= TO_UVEC(adr-c_burstsize, dvr_mosi.address'length); + END IF; + ELSE + dvr_mosi.burstbegin <= '0'; + END IF; + END PROCESS; + + dvr_mosi.burstsize <= TO_UVEC(c_burstsize, dvr_mosi.burstsize'length); dvr_mosi.wr <= wr_not_rd; dvr_mosi.rd <= NOT wr_not_rd; + -- input to io_ddr u_ddrctrl_input : ENTITY work.ddrctrl_input GENERIC MAP( @@ -118,7 +138,7 @@ BEGIN in_sosi_arr => in_sosi_arr, out_of => out_of, out_sosi => wr_sosi, - out_adr => out_adr + out_adr => adr ); -- functions as a fifo buffer for input data into the sdram stick. also manages input to sdram stick. @@ -129,8 +149,8 @@ BEGIN 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_wr_fifo_depth => c_wr_fifo_depth, + g_rd_fifo_depth => c_rd_fifo_depth, g_rd_data_w => c_io_ddr_data_w, g_wr_flush_mode => "VAL", g_wr_flush_use_channel => FALSE, @@ -162,7 +182,7 @@ BEGIN dvr_clk => clk, dvr_rst => rst, - dvr_miso => open, + dvr_miso => dvr_miso, dvr_mosi => dvr_mosi, -- Write FIFO clock domain 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 8c2fad8bce..8a7b08f424 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd @@ -60,7 +60,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_adr_w : NATURAL := 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 : NATURAL := 2**(c_adr_w)-1; -- the maximal address that is possible within the vector length of the address -- type for statemachine @@ -103,7 +103,7 @@ BEGIN CASE q_reg.state IS WHEN RESET => - v.s_adr := 0; + v.s_adr := c_max_adr-1; WHEN COUNTING => v.s_adr := q_reg.s_adr+1; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd index 9bd01e39ea..63f3df23fa 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd @@ -40,7 +40,7 @@ ENTITY tb_ddrctrl IS g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation g_nof_streams : POSITIVE := 12; -- number of input streams g_data_w : NATURAL := 14; -- data with of input data vectors - g_sim_length : NATURAL := 1052; + g_sim_length : NATURAL := 16500; g_technology : NATURAL := c_tech_select_default; g_tech_ddr3 : t_c_tech_ddr := c_tech_ddr3_4g_800m_master; g_tech_ddr4 : t_c_tech_ddr := c_tech_ddr4_4g_1600m @@ -54,6 +54,7 @@ ARCHITECTURE tb OF tb_ddrctrl IS CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock priod, 5 ns CONSTANT c_mm_clk_freq : NATURAL := 100; CONSTANT c_mm_clk_period : TIME := (10**6 / c_mm_clk_freq) * 1 ps; + CONSTANT c_sim_length : NATURAL := (g_sim_length*576)/168; -- Select DDR3 or DDR4 dependent on the technology and sim model CONSTANT c_mem_ddr : t_c_tech_ddr := func_tech_sel_ddr(g_technology, g_tech_ddr3, g_tech_ddr4); @@ -71,16 +72,16 @@ ARCHITECTURE tb OF tb_ddrctrl IS -- function for making total data vector FUNCTION c_total_vector_init RETURN STD_LOGIC_VECTOR IS - VARIABLE temp : STD_LOGIC_VECTOR(c_in_data_w*g_sim_length-1 DOWNTO 0); + VARIABLE temp : STD_LOGIC_VECTOR(c_in_data_w*c_sim_length-1 DOWNTO 0); BEGIN - FOR I IN 0 TO g_sim_length*g_nof_streams-1 LOOP + FOR I IN 0 TO c_sim_length*g_nof_streams-1 LOOP temp(g_data_w*(I+1)-1 DOWNTO g_data_w*I) := TO_UVEC(I, g_data_w); END LOOP; RETURN temp; END FUNCTION c_total_vector_init; -- constant for running the test - CONSTANT c_total_vector : STD_LOGIC_VECTOR(c_in_data_w*g_sim_length-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector + CONSTANT c_total_vector : STD_LOGIC_VECTOR(c_in_data_w*c_sim_length-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector -- input signals for ddrctrl.vhd @@ -137,9 +138,18 @@ BEGIN mm_rst <= '0'; test_running <= '1'; wr_not_rd <= '1'; + WAIT FOR c_clk_period*1; + + make_data_0 : FOR J IN 1 TO 40-1 LOOP + in_data_cnt <= in_data_cnt+1; + fill_in_sosi_arr_rest_0 : FOR I IN 0 TO g_nof_streams-1 LOOP + in_sosi_arr(I).data(g_data_w-1 DOWNTO 0) <= c_total_vector(g_data_w*(I+1)+J*c_in_data_w-1 DOWNTO g_data_w*I+J*c_in_data_w); + END LOOP; + WAIT FOR c_clk_period*1; + END LOOP; -- filling the input data vectors with the corresponding numbers - make_data : FOR J IN 0 TO g_sim_length-1 LOOP + make_data : FOR J IN 40 TO c_sim_length-1 LOOP in_data_cnt <= in_data_cnt+1; fill_in_sosi_arr_rest : FOR I IN 0 TO g_nof_streams-1 LOOP in_sosi_arr(I).data(g_data_w-1 DOWNTO 0) <= c_total_vector(g_data_w*(I+1)+J*c_in_data_w-1 DOWNTO g_data_w*I+J*c_in_data_w); @@ -150,7 +160,7 @@ BEGIN wr_not_rd <= '0'; -- testing reset --- FOR I IN 0 TO g_sim_length-1 LOOP +-- FOR I IN 0 TO c_sim_length-1 LOOP -- rst <= '1'; -- WAIT FOR c_clk_period*1; -- rst <= '0'; @@ -174,9 +184,7 @@ BEGIN g_sim_model => g_sim_model, g_technology => g_technology, g_nof_streams => g_nof_streams, - g_data_w => g_data_w, - g_wr_fifo_depth => c_wr_fifo_depth, - g_rd_fifo_depth => c_rd_fifo_depth + g_data_w => g_data_w ) PORT MAP ( clk => clk, @@ -195,18 +203,4 @@ BEGIN phy4_ou => phy4_ou ); - u_tech_ddr_memory_model : ENTITY tech_ddr_lib.tech_ddr_memory_model - GENERIC MAP ( - g_tech_ddr => c_tech_ddr - ) - PORT MAP ( - -- DDR3 PHY interface - mem3_in => phy3_ou, - mem3_io => phy3_io, - - -- DDR4 PHY interface - mem4_in => phy4_ou, - mem4_io => phy4_io - ); - 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 14f4d34b19..61726138ae 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 @@ -48,10 +48,9 @@ ARCHITECTURE tb OF tb_ddrctrl_address_counter IS -- constants for running the test CONSTANT c_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- in and output data vector with, 576 - CONSTANT c_adr_w : NATURAL := 4; -- address with in simulation + CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( g_tech_ddr ); -- address with in simulation CONSTANT c_adr_size : NATURAL := 2**c_adr_w; -- address size in simulation - -- input signals for ddrctrl_address_counter.vhd SIGNAL clk : STD_LOGIC := '1'; SIGNAL rst : STD_LOGIC := '0'; @@ -96,6 +95,10 @@ BEGIN in_data <= (OTHERS => '0'); in_data_enable <= '0'; WAIT UNTIL rising_edge(clk); + WAIT FOR c_clk_period*4; + rst <= '1'; + WAIT FOR c_clk_period*1; + rst <= '0'; -- changing inputs to start the address counting FOR I IN 0 TO g_sim_length-1 LOOP @@ -160,17 +163,27 @@ BEGIN -- verifying if the address is correct by keeping track of the address p_verify_address : PROCESS + + VARIABLE v_adr : NATURAL range 0 to c_adr_size-1 := c_adr_size-1; + BEGIN - FOR I IN 0 TO c_adr_size-1 LOOP - IF I >= q_lag_due_reset THEN - 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; + WAIT UNTIL rst = '1'; + WAIT UNTIL rst = '0'; + FOR I IN 0 TO g_sim_length-1 LOOP + IF v_adr >= q_lag_due_reset THEN + ASSERT v_adr-q_lag_due_reset = out_adr REPORT "Wrong address, 1, v_adr = " & NATURAL'image(v_adr-q_lag_due_reset) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR; ELSE - 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; + ASSERT (v_adr-q_lag_due_reset)+c_adr_size = out_adr REPORT "Wrong address, 2, v_adr = " & NATURAL'image((v_adr-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR; END IF; WAIT UNTIL out_sosi.valid = '1'; IF q_q_rst = '1' THEN WAIT UNTIL out_sosi.valid = '1'; END IF; + IF v_adr = c_adr_size-1 THEN + v_adr := 0; + ELSE + v_adr := v_adr+1; + END IF; END LOOP; END PROCESS; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_input.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_input.vhd index 5d6da7aa7c..86316cbb50 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_input.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_input.vhd @@ -53,7 +53,7 @@ ARCHITECTURE tb OF tb_ddrctrl_input IS -- constants for readability CONSTANT c_in_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168 CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576 - CONSTANT c_adr_w : NATURAL := 4; -- address with in simulation + CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( g_tech_ddr ) ; -- address with in simulation CONSTANT c_adr_size : NATURAL := 2**c_adr_w; -- address size in simulation -- function for making total data vector @@ -124,12 +124,12 @@ BEGIN test_running <= '0'; -- testing reset - FOR I IN 0 TO g_sim_length-1 LOOP - rst <= '1'; - WAIT FOR c_clk_period*1; - rst <= '0'; - WAIT FOR c_clk_period*((((c_out_data_w/c_in_data_w)+1)*c_adr_size)+4); - END LOOP; + --FOR I IN 0 TO g_sim_length-1 LOOP + --rst <= '1'; + --WAIT FOR c_clk_period*1; + --rst <= '0'; + --WAIT FOR c_clk_period*((((c_out_data_w/c_in_data_w)+1)*c_adr_size)+4); + --END LOOP; -- stopping the testbench @@ -148,28 +148,39 @@ BEGIN q_rst <= rst; END IF; IF q_rst = '1' THEN - IF lag_due_reset + out_adr >= c_adr_size THEN - lag_due_reset <= lag_due_reset+out_adr-c_adr_size; + IF lag_due_reset+out_adr+2 >= c_adr_size THEN + lag_due_reset <= lag_due_reset+out_adr+2-c_adr_size; ELSE - lag_due_reset <= lag_due_reset+out_adr; + lag_due_reset <= lag_due_reset+out_adr+2; END IF; END IF; END PROCESS; -- verifying if the address is correct by keeping track of the address p_verify_address : PROCESS + + VARIABLE v_adr : NATURAL range 0 to c_adr_size-1 := c_adr_size-2; + BEGIN - FOR I IN 0 TO c_adr_size-1 LOOP - IF I >= q_lag_due_reset THEN - 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; + WAIT UNTIL rst = '1'; + WAIT UNTIL rst = '0'; + FOR I IN 0 TO g_sim_length-1 LOOP + IF v_adr >= q_lag_due_reset THEN + ASSERT v_adr-q_lag_due_reset = out_adr REPORT "Wrong address, 1, v_adr = " & NATURAL'image(v_adr-q_lag_due_reset) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR; ELSE - 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; + ASSERT (v_adr-q_lag_due_reset)+c_adr_size = out_adr REPORT "Wrong address, 2, v_adr = " & NATURAL'image((v_adr-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(out_adr) SEVERITY ERROR; END IF; - WAIT UNTIL out_sosi.valid = '1'; + WAIT UNTIL out_sosi.valid = '1'; IF q_q_rst = '1' THEN WAIT UNTIL out_sosi.valid = '1'; END IF; + IF v_adr = c_adr_size-1 THEN + v_adr := 0; + ELSE + v_adr := v_adr+1; + END IF; END LOOP; + WAIT; END PROCESS; -- verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected -- GitLab