From 6ff51f1de7de357c5845304fcee9913c4728f9cd Mon Sep 17 00:00:00 2001 From: JobvanWee <wee@astron.nl> Date: Thu, 3 Mar 2022 15:21:48 +0100 Subject: [PATCH] ASSERT --- .../libraries/ddrctrl/src/vhdl/ddrctrl.vhd | 52 ++++---- .../src/vhdl/ddrctrl_address_counter.vhd | 38 +++--- .../ddrctrl/src/vhdl/ddrctrl_pack.vhd | 6 +- .../ddrctrl/src/vhdl/ddrctrl_repack.vhd | 25 ++-- .../libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd | 123 +++++++++--------- .../tb/vhdl/tb_ddrctrl_address_counter.vhd | 118 +++++++++-------- .../ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd | 40 +++--- .../ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd | 48 +++---- 8 files changed, 239 insertions(+), 211 deletions(-) diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd index 74fbb3c2d3..8a75aece94 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl.vhd @@ -18,11 +18,14 @@ -- ------------------------------------------------------------------------------- -- Author: Job van Wee --- Purpose: Create address by counting input valids +-- Purpose: Folding a stream of data into a mm data configuration so it can be +-- stored in a DDR RAM-stick. -- -- Description: --- The counter starts on the first valid = '1' clockcylce, the counter stops --- when valid = '0'. +-- First the data from the sosi array gets collected into one data vector. +-- After that this data vector gets resized to the right size data vector in +-- order to make it storable in a DDR RAM-stick. +-- After that a address gets assigned to the data so the data can be found back. -- -- Remark: -- Use VHDL coding template from: @@ -41,58 +44,63 @@ USE dp_lib.dp_stream_pkg.ALL; ENTITY ddrctrl IS GENERIC ( - g_tech_ddr : t_c_tech_ddr; - g_sim_model : BOOLEAN := TRUE; - g_nof_streams : NATURAL := 12; - g_data_w : NATURAL := 14 + g_tech_ddr : t_c_tech_ddr; -- type of memory + g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation + g_nof_streams : NATURAL := 12; -- number of input streams + g_data_w : NATURAL := 14 -- data with of input data vectors ); PORT ( clk : IN STD_LOGIC := '0'; rst : IN STD_LOGIC; - in_sosi_arr : IN t_dp_sosi_arr; - out_of : OUT NATURAL; - out_mosi : OUT t_mem_ctlr_mosi + in_sosi_arr : IN t_dp_sosi_arr; -- input data + out_of : OUT NATURAL; -- amount of overflow this output + out_mosi : OUT t_mem_ctlr_mosi -- output data ); END ddrctrl; -ARCHITECTURE rtl OF ddrctrl IS +ARCHITECTURE str OF ddrctrl IS + -- constant for readability CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; - SIGNAL total_data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); - SIGNAL out_sosi : t_dp_sosi; + -- signals for connecting the components + SIGNAL data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); + SIGNAL sosi : t_dp_sosi; BEGIN + -- makes one data vector out of all the data from the t_dp_sosi_arr u_pack : ENTITY work.ddrctrl_pack GENERIC MAP( - g_nof_streams => g_nof_streams, -- number of input streams - g_data_w => g_data_w -- data with of input data vectors + g_nof_streams => g_nof_streams, -- number of input streams + g_data_w => g_data_w -- data with of input data vectors ) PORT MAP( clk => clk, in_sosi_arr => in_sosi_arr, - out_data => total_data + out_data => data ); + -- resizes the input data vector so that the output data vector can be stored into the ddr memory u_repack : ENTITY work.ddrctrl_repack GENERIC MAP( - g_tech_ddr => g_tech_ddr, -- type of memory - g_in_data_w => c_out_data_w -- the input data with + g_tech_ddr => g_tech_ddr, -- type of memory + g_in_data_w => c_out_data_w -- the input data with ) PORT MAP( clk => clk, - in_data => total_data, + in_data => data, out_of => out_of, - out_sosi => out_sosi + out_sosi => sosi ); + -- creates address by counting input valids u_address_counter : ENTITY work.ddrctrl_address_counter GENERIC MAP( g_tech_ddr => g_tech_ddr, @@ -101,8 +109,8 @@ BEGIN PORT MAP( clk => clk, rst => rst, - in_sosi => out_sosi, + in_sosi => sosi, out_mosi => out_mosi ); -END rtl; +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 f0cf079b5a..2a46b873dc 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_address_counter.vhd @@ -18,7 +18,7 @@ -- ------------------------------------------------------------------------------- -- Author: Job van Wee --- Purpose: Create address by counting input valids +-- Purpose: Creates address by counting input valids -- -- Description: -- The counter starts on the first valid = '1' clockcylce, the counter stops @@ -41,43 +41,45 @@ USE dp_lib.dp_stream_pkg.ALL; ENTITY ddrctrl_address_counter IS GENERIC ( - g_tech_ddr : t_c_tech_ddr; - g_sim_model : BOOLEAN := TRUE + g_tech_ddr : t_c_tech_ddr; -- type of memory + g_sim_model : BOOLEAN := TRUE -- determens if this is a simulation ); PORT ( clk : IN STD_LOGIC; rst : IN STD_LOGIC; - in_sosi : IN t_dp_sosi; - out_mosi : OUT t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst + in_sosi : IN t_dp_sosi; -- input data + out_mosi : OUT t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst -- output data ); END ddrctrl_address_counter; ARCHITECTURE rtl OF ddrctrl_address_counter IS - CONSTANT c_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); --576 - CONSTANT c_adr_w : NATURAL := sel_a_b(g_sim_model, 4, func_tech_ddr_ctlr_address_w( g_tech_ddr )); --27; - CONSTANT c_max_adr : NATURAL := 2**(c_adr_w) - 1; + -- 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 : NATURAL := 2**(c_adr_w) - 1; -- the maximal address that is possible within the vector length of the address - SIGNAL s_adr : NATURAL range 0 to 2**(c_adr_w)-1 := 0; + -- signal for storing address + SIGNAL s_adr : NATURAL range 0 to 2**(c_adr_w)-1 := 0; -- a signal that contains the address BEGIN + -- The data is directly put through. out_mosi.wrdata(c_data_w - 1 DOWNTO 0) <= in_sosi.data(c_data_w - 1 DOWNTO 0); out_mosi.wr <= in_sosi.valid; out_mosi.address(c_adr_w -1 DOWNTO 0) <= TO_UVEC(s_adr, c_adr_w); - p_clk : PROCESS(clk) + -- Increments the address each time in_sosi.valid = '1', if address = c_max_adr the address is reset to 0. + p_adr : PROCESS(rst, in_sosi.valid) BEGIN - IF rising_edge(clk) THEN - IF rst = '1' THEN + IF rst = '1' THEN + s_adr <= 0; + ELSIF rising_edge(in_sosi.valid) THEN + IF (s_adr = c_max_adr) THEN s_adr <= 0; - ELSIF in_sosi.valid = '1' THEN - IF (s_adr = c_max_adr) THEN - s_adr <= 0; - ELSE - s_adr <= s_adr + 1; - END IF; + ELSE + s_adr <= s_adr + 1; END IF; END IF; END PROCESS; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd index 1a547881d6..2a897961ef 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_pack.vhd @@ -40,9 +40,9 @@ ENTITY ddrctrl_pack IS ); PORT ( - clk : IN STD_LOGIC; -- clock signal - in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); -- input signal - out_data : OUT STD_LOGIC_VECTOR((g_nof_streams*g_data_w)-1 DOWNTO 0) -- output signal + clk : IN STD_LOGIC; + in_sosi_arr : IN t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0); -- input data + out_data : OUT STD_LOGIC_VECTOR((g_nof_streams*g_data_w)-1 DOWNTO 0) -- output data ); END ddrctrl_pack; diff --git a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd index 3c515a881c..7157e0b207 100644 --- a/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd +++ b/applications/lofar2/libraries/ddrctrl/src/vhdl/ddrctrl_repack.vhd @@ -50,23 +50,22 @@ END ddrctrl_repack; ARCHITECTURE rtl OF ddrctrl_repack IS + -- constant for readability CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- the output data with, 576 CONSTANT k_c_v_w : NATURAL := c_out_data_w*2; -- the c_v data with, 2*576=1152 - SIGNAL c_v_count : NATURAL := 0; -- the amount of times the c_v vector received data from the input since the last time it was filled completely - SIGNAL out_data_count : NATURAL := 0; -- the amount of times the output data vector has been filled since the last time c_v was filled completely - BEGIN + -- put the input data into c_v and fill the output vector from c_v p_clk : PROCESS(clk) VARIABLE a_of : NATURAL := 0; -- amount of overflow VARIABLE c_v : STD_LOGIC_VECTOR (k_c_v_w-1 DOWNTO 0) := (OTHERS => '0'); -- the vector that stores the input data until the data is put into the output data vector + VARIABLE c_v_count : NATURAL := 0; -- the amount of times the c_v vector received data from the input since the last time it was filled completely + VARIABLE out_data_count : NATURAL := 0; -- the amount of times the output data vector has been filled since the last time c_v was filled completely BEGIN - IF rising_edge(clk) THEN - IF ((g_in_data_w*(c_v_count+1))+a_of >= c_out_data_w*(out_data_count+1)) THEN -- if the input data exceeds the output data vector width IF (out_data_count = 1) THEN -- if the input data exceeds c_v widt @@ -76,28 +75,22 @@ BEGIN c_v(a_of - 1 DOWNTO 0) := in_data(g_in_data_w - 1 DOWNTO g_in_data_w - a_of); -- fill the start of c_v untill the a_of out_sosi.data(c_out_data_w - 1 DOWNTO 0) <= c_v(k_c_v_w - 1 DOWNTO c_out_data_w); -- fill out_sosi.data with 2nd part of c_v out_sosi.valid <= '1'; -- out_sosi.valid 1 - c_v_count <= 0; -- reset counter - out_data_count <= 0; -- reset counter + c_v_count := 0; -- reset counter + out_data_count := 0; -- reset counter Else -- if the input data exceeds output data vector width but not the c_v vector widt c_v(g_in_data_w * (c_v_count + 1) + a_of - 1 DOWNTO g_in_data_w * c_v_count + a_of) := in_data(g_in_data_w - 1 DOWNTO 0); -- fill c_v - c_v_count <= c_v_count + 1; -- increase the counter of c_v with 1 + c_v_count := c_v_count + 1; -- increase the counter of c_v with 1 out_sosi.data(c_out_data_w - 1 DOWNTO 0) <= c_v(c_out_data_w - 1 DOWNTO 0); -- fill out_sosi.data with 1st part of c_v out_sosi.valid <= '1'; -- out_sosi.valid 1 - out_data_count <= out_data_count + 1; -- increase the counter of out_sosi.data with 1 + out_data_count := out_data_count + 1; -- increase the counter of out_sosi.data with 1 END IF; ELSE -- if the input data doesn't exceeds the output data vector width c_v(g_in_data_w * (c_v_count + 1) + a_of - 1 DOWNTO g_in_data_w * c_v_count + a_of) := in_data(g_in_data_w - 1 DOWNTO 0); -- fill c_v - c_v_count <= c_v_count + 1; -- increase the counter of c_v with 1 + c_v_count := c_v_count + 1; -- increase the counter of c_v with 1 out_sosi.valid <= '0'; -- out_sosi.valid 0 - END IF; - END IF; - END PROCESS; - 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 61b1c01df6..897bc9fd57 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl.vhd @@ -35,72 +35,81 @@ USE common_lib.common_pkg.ALL; ENTITY tb_ddrctrl IS GENERIC ( - g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory - g_sim_model : BOOLEAN := TRUE; - g_nof_streams : POSITIVE := 12; -- number of input streams - g_data_w : NATURAL := 14; -- data with of input data vectors - g_sim_lengt : NATURAL := 52 + g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory + 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_lengt : NATURAL := 52 ); END tb_ddrctrl; ARCHITECTURE tb OF tb_ddrctrl IS - CONSTANT c_clk_freq : NATURAL := 200; -- MHz - CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock priod, 5 ns + -- constants for testbench + CONSTANT c_clk_freq : NATURAL := 200; -- clock frequency in MHz + CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock priod, 5 ns - CONSTANT c_in_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168 + -- 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; - CONSTANT c_max_adr : NATURAL := 2**c_adr_w-1; + CONSTANT c_adr_w : NATURAL := 4; -- address with in simulation + CONSTANT c_max_adr : NATURAL := 2**c_adr_w-1; -- max address in simulation + -- 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_lengt-1 DOWNTO 0); BEGIN - --temp(c_out_data_w-1 DOWNTO 0) := (OTHERS => '0'); FOR I IN 0 TO g_sim_lengt*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 c_total_vector : STD_LOGIC_VECTOR(c_in_data_w*g_sim_lengt-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector + -- constant for running the test + CONSTANT c_total_vector : STD_LOGIC_VECTOR(c_in_data_w*g_sim_lengt-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector - SIGNAL in_data_cnt : NATURAL := 0; - - SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell when the testing has started - SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off - SIGNAL lag_due_reset : NATURAL := 0; + -- input signals for ddrctrl.vhd + SIGNAL clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '0'; + SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- input data signal for ddrctrl_pack.vhd + -- output singals from ddrctrl.vhd + SIGNAL out_of : NATURAL := 0; -- output signal from ddrctrl_repack to determen how high the overflow is + SIGNAL out_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; -- output signal from ddrctrl_pack.vhd - SIGNAL clk : STD_LOGIC := '1'; -- clock signal - SIGNAL rst : STD_LOGIC := '0'; - SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- input signal for ddrctrl_pack.vhd + -- testbench signal + SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off - SIGNAL out_of : NATURAL := 0; -- output signal from ddrctrl_repack to determen how high the overflow is - SIGNAL out_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; -- output signal from ddrctrl_pack.vhd + -- signals for running test + SIGNAL in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd + SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started + SIGNAL lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest BEGIN - clk <= NOT clk OR tb_end AFTER c_clk_period/2; -- generating clock signal + -- generating clock + clk <= NOT clk OR tb_end AFTER c_clk_period/2; + -- excecuting test p_test : PROCESS BEGIN + -- initialize input data for ddrctrl.vhd fill_in_sosi_arr_1 : 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)-1 DOWNTO g_data_w*I); END LOOP; - -- Start the testbench. + -- start the test tb_end <= '0'; - WAIT UNTIL rising_edge(clk); -- align to rising edge - WAIT UNTIL out_of /= 0; -- wait for out_of /= 0 to align to ddrctrl_repack properly - WAIT UNTIL out_of = 0; -- align to ddrctrl_repack - test_running <= '1'; -- start of test + WAIT UNTIL rising_edge(clk); + WAIT UNTIL out_of /= 0; + WAIT UNTIL out_of = 0; + test_running <= '1'; - -- The input data vectors get filled with the corresponding numbers. + -- filling the input data vectors with the corresponding numbers WAIT FOR c_clk_period*1; make_data : FOR J IN 1 TO g_sim_lengt-1 LOOP fill_in_sosi_arr : FOR I IN 0 TO g_nof_streams-1 LOOP @@ -111,43 +120,39 @@ BEGIN END LOOP; test_running <= '0'; - -- Stop the testbench. + -- stopping the testbench WAIT FOR c_clk_period*4; tb_end <= '1'; - - WAIT; + ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; END PROCESS; - + -- excecuting the reset test p_test_reset : PROCESS BEGIN - - WAIT FOR c_clk_period*32; - rst <= '1'; - lag_due_reset <= TO_UINT(out_mosi.address)+1; - WAIT FOR c_clk_period*1; - rst <= '0'; - WAIT; + rst <= '0'; + WAIT FOR c_clk_period*g_sim_lengt*3/4; + rst <= '1'; + IF lag_due_reset + TO_UINT(out_mosi.address) >= c_max_adr THEN + lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address)-c_max_adr; + ELSE + lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address); + END IF; + WAIT FOR c_clk_period*1; END PROCESS; - - - -- Verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected. + -- verifying if the input vectors are correctly put into the output vector and the amount of overflow is as expected p_verify_of_data : PROCESS VARIABLE ctr_of : NATURAL := 0; VARIABLE out_data_cnt : NATURAL := 0; BEGIN - WAIT UNTIL rising_edge(out_mosi.wr); - - IF test_running = '1' THEN IF out_data_cnt > 0 THEN IF out_data_cnt mod 2 = 0 THEN ctr_of := c_in_data_w*in_data_cnt-c_out_data_w*out_data_cnt; - ASSERT ctr_of = out_of REPORT "The amount of overflow does not match, ctr_of = " & NATURAL'image(ctr_of) SEVERITY ERROR; + ASSERT ctr_of = out_of REPORT "The amount of overflow does not match, ctr_of = " & NATURAL'image(ctr_of) SEVERITY ERROR; END IF; ASSERT out_mosi.wrdata(c_out_data_w -1 DOWNTO 0) = c_total_vector(c_out_data_w*(out_data_cnt)-1 DOWNTO c_out_data_w*(out_data_cnt-1)) REPORT "Data does not match, out_data_cnt = " & NATURAL'image(out_data_cnt) SEVERITY ERROR; END IF; @@ -155,22 +160,22 @@ BEGIN END IF; END PROCESS; - + -- verifying if the address is correct by keeping trach of the address p_verify_address : PROCESS BEGIN - FOR I IN 0 TO c_max_adr LOOP - WAIT UNTIL rising_edge(out_mosi.wr); - IF I >= lag_due_reset THEN - ASSERT I-lag_due_reset = TO_UINT(out_mosi.address) REPORT "Wrong address, 1, I = " & NATURAL'image(I-lag_due_reset) SEVERITY ERROR; - ELSE - ASSERT I+c_max_adr-lag_due_reset+1 = TO_UINT(out_mosi.address) REPORT "Wrong address, 2, I = " & NATURAL'image(I+c_max_adr-lag_due_reset+1) SEVERITY ERROR; - END IF; - END LOOP; + FOR I IN 0 TO c_max_adr LOOP + WAIT UNTIL rising_edge(out_mosi.wr); + IF rst = '0' THEN -- testing on reset is a bad idea + IF I >= lag_due_reset THEN + ASSERT I-lag_due_reset = TO_UINT(out_mosi.address) REPORT "Wrong address, 1, I = " & NATURAL'image(I-lag_due_reset) SEVERITY ERROR; + ELSE + ASSERT I+c_max_adr-lag_due_reset+1 = TO_UINT(out_mosi.address) REPORT "Wrong address, 2, I = " & NATURAL'image(I+c_max_adr-lag_due_reset+1) SEVERITY ERROR; + END IF; + END IF; + END LOOP; END PROCESS; - - - + -- DUT u_ddrctrl_pack : ENTITY work.ddrctrl GENERIC MAP ( g_tech_ddr => g_tech_ddr, 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 3a00080067..60a7cffc69 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 @@ -33,75 +33,60 @@ USE common_lib.common_pkg.ALL; ENTITY tb_ddrctrl_address_counter IS GENERIC ( - g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; - g_sim_model : BOOLEAN := TRUE + g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory + g_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation + g_sim_lengt : NATURAL := 52 -- determens the lengt of the duration of the test ); END tb_ddrctrl_address_counter; ARCHITECTURE tb OF tb_ddrctrl_address_counter IS - CONSTANT c_clk_freq : NATURAL := 200; -- MHz - CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; + -- constants for running the testbench + CONSTANT c_clk_freq : NATURAL := 200; -- clock frequency in MHz + CONSTANT c_clk_period : TIME := (10**6/c_clk_freq)*1 ps; -- clock period, 5 ns - CONSTANT c_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- 576 - CONSTANT c_adr_w : NATURAL := 4; - CONSTANT c_max_adr : NATURAL := 2**c_adr_w; + -- 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_size : NATURAL := 2**c_adr_w; -- address size in simulation - SIGNAL tb_end : STD_LOGIC := '0'; + -- input signals for ddrctrl_address_counter.vhd SIGNAL clk : STD_LOGIC := '1'; SIGNAL rst : STD_LOGIC; + SIGNAL in_sosi : t_dp_sosi := c_dp_sosi_init; -- signal which is the input for ddrctrl_address_counter.vhd - SIGNAL in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); - SIGNAL in_data_enable : STD_LOGIC; - SIGNAL in_sosi : t_dp_sosi := c_dp_sosi_init; + -- 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_mosi : t_mem_ctlr_mosi := c_mem_ctlr_mosi_rst; + -- testbench signals + SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + SIGNAL in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); -- signal which contains the data that is set as input + SIGNAL in_data_enable : STD_LOGIC; -- signal to determen if in_data is ready for reading + SIGNAL lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest BEGIN - -- if these ASSERT's get uncommented u can see that modelsim does take a few itteration before the warning gets asserted. These asserts are also present in p_verify - - --ASSERT in_sosi.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; -- gives error if in_sosi and out_mosi do not match - --ASSERT in_sosi.valid = out_mosi.wr REPORT "in_sosi.valid does not match out_mosi.wr" SEVERITY ERROR; - --ASSERT in_sosi.data(c_data_w - 1 DOWNTO 0) /= out_mosi.wrdata(c_data_w - 1 DOWNTO 0) REPORT "in_sosi.data does match out_mosi.wrdata" SEVERITY WARNING; -- gives warning if in_sosi and out_mosi do match - --ASSERT in_sosi.valid /= out_mosi.wr REPORT "in_sosi.valid does match out_mosi.wr" SEVERITY WARNING; - - in_sosi.data(c_data_w - 1 DOWNTO 0) <= in_data(c_data_w - 1 DOWNTO 0); + -- Wiring the input signals to the inputs of the testbench. + in_sosi.data(c_data_w-1 DOWNTO 0) <= in_data(c_data_w-1 DOWNTO 0); in_sosi.valid <= in_data_enable; + -- Generating clock. clk <= NOT clk OR tb_end AFTER c_clk_period/2; - p_mm : PROCESS + -- Excecuting the test. + p_test : PROCESS BEGIN - rst <= '1', '0' AFTER c_clk_period/10; - + -- Initialize inputs. tb_end <= '0'; in_data <= (OTHERS => '0'); in_data_enable <= '0'; + WAIT UNTIL rising_edge(clk); - WAIT UNTIL rising_edge(clk); -- align to rising edge - WAIT FOR c_clk_period*10; - - FOR I IN 0 TO 6 LOOP - in_data_enable <= '1'; - in_data <= NOT in_data; - ASSERT I = TO_UINT(out_mosi.address) REPORT "Wrong address, I = " & NATURAL'image(I) SEVERITY ERROR; - WAIT FOR c_clk_period*1; - in_data_enable <= '0'; - WAIT FOR c_clk_period*2; - END LOOP; - - WAIT FOR c_clk_period*1; - rst <= '1'; -- reset - WAIT FOR c_clk_period*1; - rst <= '0'; - WAIT FOR c_clk_period*1; - - FOR I IN 0 TO 20 LOOP - ASSERT I = TO_UINT(out_mosi.address) OR I - c_max_adr = TO_UINT(out_mosi.address) REPORT "Wrong address, I = " & NATURAL'image(I) SEVERITY ERROR; + -- Changing inputs to start the address counting. + FOR I IN 0 TO g_sim_lengt-1 LOOP in_data_enable <= '1'; in_data <= NOT in_data; WAIT FOR c_clk_period*1; @@ -109,24 +94,52 @@ BEGIN WAIT FOR c_clk_period*2; END LOOP; - WAIT FOR c_clk_period*20; - + -- Stopping the test. + WAIT FOR c_clk_period*4; tb_end <= '1'; - WAIT; - + ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; END PROCESS; - p_verify : PROCESS + -- Verifying if the data is correct and if valid is correct. + p_verify_data_valid : PROCESS BEGIN WAIT UNTIL rising_edge(clk); IF rising_edge(clk) THEN - ASSERT in_sosi.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; -- gives error if in_sosi and out_mosi do not match - ASSERT in_sosi.valid = out_mosi.wr REPORT "in_sosi.valid does not match out_mosi.wr" SEVERITY ERROR; - --ASSERT in_sosi.data(c_data_w - 1 DOWNTO 0) /= out_mosi.wrdata(c_data_w - 1 DOWNTO 0) REPORT "in_sosi.data does match out_mosi.wrdata" SEVERITY WARNING; -- gives warning if in_sosi and out_mosi do match - --ASSERT in_sosi.valid /= out_mosi.wr REPORT "in_sosi.valid does match out_mosi.wr" SEVERITY WARNING; + ASSERT in_sosi.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 in_sosi.valid = out_mosi.wr REPORT "in_sosi.valid does not match out_mosi.wr" SEVERITY ERROR; + END IF; + END PROCESS; + + -- Excecuting the reset test. + p_test_reset : PROCESS + BEGIN + rst <= '0'; + WAIT FOR c_clk_period*g_sim_lengt*3/4; + rst <= '1'; + 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; + ELSE + lag_due_reset <= lag_due_reset+TO_UINT(out_mosi.address); END IF; + WAIT FOR c_clk_period*1; END PROCESS; + -- verifying if the address is correct by keeping trach of the address + p_verify_address : PROCESS + BEGIN + FOR I IN 0 TO c_adr_size-1 LOOP + WAIT UNTIL rising_edge(out_mosi.wr); + IF rst = '0' THEN -- testing on reset is a bad idea + IF I >= lag_due_reset THEN + ASSERT I-lag_due_reset = TO_UINT(out_mosi.address) REPORT "Wrong address, 1, I = " & NATURAL'image(I-lag_due_reset) SEVERITY ERROR; + ELSE + ASSERT (I-lag_due_reset)+c_adr_size = TO_UINT(out_mosi.address) REPORT "Wrong address, 2, I = " & NATURAL'image((I-lag_due_reset)+c_adr_size) SEVERITY ERROR; + END IF; + END IF; + END LOOP; + END PROCESS; + + -- DUT. u_ddrctrl_address_counter : ENTITY work.ddrctrl_address_counter GENERIC MAP ( g_tech_ddr => g_tech_ddr, @@ -138,7 +151,6 @@ BEGIN in_sosi => in_sosi, out_mosi => out_mosi - ); END tb; diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd index 5478ec55c5..292219045b 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_pack.vhd @@ -43,12 +43,14 @@ END tb_ddrctrl_pack; ARCHITECTURE tb OF tb_ddrctrl_pack IS - CONSTANT c_clk_freq : NATURAL := 200; -- MHz - CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock priod, 5 ns + -- constants for running the testbench + CONSTANT c_clk_freq : NATURAL := 200; -- clock frequency in MHz + CONSTANT c_clk_period : TIME := (10**6/c_clk_freq)*1 ps; -- clock priod, 5 ns + -- constant for readability + CONSTANT c_out_data_w : NATURAL := g_nof_streams*g_data_w; -- output data with, 168 - CONSTANT c_out_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168 - + -- function for making test vector FUNCTION c_testv_init RETURN STD_LOGIC_VECTOR IS VARIABLE temp : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); BEGIN @@ -57,28 +59,33 @@ ARCHITECTURE tb OF tb_ddrctrl_pack IS END LOOP; RETURN temp; END FUNCTION c_testv_init; - CONSTANT c_testv : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0) := c_testv_init; -- testvector which contains a number for each stream, so the data of stream 6 will look like ...00110 - - - SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + -- constants for running the test + CONSTANT c_testv : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0) := c_testv_init; -- testvector which contains a number for each stream, so the data of stream 6 will look like ...00110 + -- input signals for ddrctrl_pack.vhd SIGNAL clk : STD_LOGIC := '1'; -- clock signal SIGNAL in_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init); -- input signal for ddrctrl_pack.vhd + -- output singal from ddrctrl_pack.vhd SIGNAL out_data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); -- output signal from ddrctrl_pack.vhd + -- testbench signal + SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + BEGIN - clk <= NOT clk OR tb_end AFTER c_clk_period/2; -- generating clock signal + -- Generating clock. + clk <= NOT clk OR tb_end AFTER c_clk_period/2; - p_mm : PROCESS + -- Excecuting the test. + p_test : PROCESS BEGIN - -- Start the testbench. + -- Start the test. tb_end <= '0'; - WAIT UNTIL rising_edge(clk); -- align to rising edge + WAIT UNTIL rising_edge(clk); WAIT FOR c_clk_period*2; @@ -97,12 +104,10 @@ BEGIN END LOOP; END LOOP; - -- Stop the testbench. + -- Stopping the testbench. WAIT FOR c_clk_period*4; tb_end <= '1'; - - - WAIT; + ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; END PROCESS; -- Verification by checking if the input vectors equel the corresponding index of the output vector. @@ -116,8 +121,7 @@ BEGIN END IF; END PROCESS; - - + -- DUT. u_ddrctrl_pack : ENTITY work.ddrctrl_pack GENERIC MAP ( g_nof_streams => g_nof_streams, diff --git a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd index 3467ce703a..c9542f7ed5 100644 --- a/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd +++ b/applications/lofar2/libraries/ddrctrl/tb/vhdl/tb_ddrctrl_repack.vhd @@ -44,11 +44,14 @@ END tb_ddrctrl_repack; ARCHITECTURE tb OF tb_ddrctrl_repack IS + -- constants for running testbench CONSTANT c_clk_freq : NATURAL := 200; -- clock freqency in MHz CONSTANT c_clk_period : TIME := (10**6 / c_clk_freq) * 1 ps; -- clock period, 5 ns - CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576 + -- constant for readability + CONSTANT c_out_data_w : NATURAL := func_tech_ddr_ctlr_data_w( g_tech_ddr ); -- output data vector with, 576 + -- function for making total data vector FUNCTION c_total_vector_init RETURN STD_LOGIC_VECTOR IS VARIABLE temp : STD_LOGIC_VECTOR(g_in_data_w*g_sim_lengt-1 DOWNTO 0); BEGIN @@ -57,66 +60,67 @@ ARCHITECTURE tb OF tb_ddrctrl_repack IS END LOOP; RETURN temp; END FUNCTION c_total_vector_init; - CONSTANT c_total_vector : STD_LOGIC_VECTOR(g_in_data_w*g_sim_lengt-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector - - SIGNAL ctr_of : NATURAL := 0; -- signal which contains the amount of overflow for checking - SIGNAL in_data_cnt : NATURAL := 0; + -- constant for running the test + CONSTANT c_total_vector : STD_LOGIC_VECTOR(g_in_data_w*g_sim_lengt-1 DOWNTO 0) := c_total_vector_init; -- vector which contains all input data vectors to make it easy to fill ctr_vector - SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell when the testing has started - SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + -- input signals for ddrctrl_repack.vhd SIGNAL clk : STD_LOGIC := '1'; -- clock signal SIGNAL in_data : STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0) := (OTHERS => '0'); -- input data signal for ddrctrl_repack + -- output signals from ddrctrl_repack.vhd SIGNAL out_of : NATURAL := 0; -- output signal from ddrctrl_repack to determen how high the overflow is SIGNAL out_sosi : t_dp_sosi := c_dp_sosi_init; -- output data signal form ddrctrl_repack + -- testbench signal + SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off + + -- singals for running the test + SIGNAL ctr_of : NATURAL := 0; -- signal which contains the amount of overflow for checking + SIGNAL in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd + SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started + BEGIN - clk <= NOT clk OR tb_end AFTER c_clk_period/2; -- genereting clock signal + -- Generating clock + clk <= NOT clk OR tb_end AFTER c_clk_period/2; - p_mm : PROCESS + -- Excecuting the test + p_test : PROCESS BEGIN - - -- Start the testbench. + -- start the test tb_end <= '0'; WAIT UNTIL rising_edge(clk); -- align to rising edge WAIT UNTIL out_of /= 0; -- wait for out_of /= 0 to align to ddrctrl_repack properly WAIT UNTIL out_of = 0; -- align to ddrctrl_repack test_running <= '1'; -- start of test - -- Filling the input vector g_sim_lengt amount of times. + -- filling the input vector g_sim_lengt amount of times make_in_data : FOR I IN 0 TO g_sim_lengt-1 LOOP - --ASSERT FALSE REPORT "I = " & NATURAL'image(I) SEVERITY NOTE; in_data(g_in_data_w-1 DOWNTO 0) <= TO_UVEC(I, g_in_data_w); WAIT FOR c_clk_period*1; in_data_cnt <= in_data_cnt + 1; END LOOP; test_running <= '0'; - -- Stop the testbench. + -- stopping the testbench WAIT FOR c_clk_period*5; tb_end <= '1'; - - WAIT; + ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; END PROCESS; - -- Verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected. + -- verification by checking if the input vectors are correctly put into the output vector and the amount of overflow is as expected p_verify : PROCESS VARIABLE ctr_of : NATURAL := 0; VARIABLE out_data_cnt : NATURAL := 0; BEGIN - WAIT UNTIL rising_edge(out_sosi.valid); - --WAIT FOR c_clk_period*1; - IF test_running = '1' THEN - ASSERT FALSE REPORT "ik werk" SEVERITY NOTE; IF out_data_cnt mod 2 = 1 THEN ctr_of := g_in_data_w*in_data_cnt-c_out_data_w*(out_data_cnt+1); ASSERT ctr_of = out_of REPORT "The amount of overflow does not match, ctr_of = " & NATURAL'image(ctr_of) SEVERITY ERROR; @@ -126,7 +130,7 @@ BEGIN END IF; END PROCESS; - + -- DUT u_ddrctrl_repack : ENTITY work.ddrctrl_repack GENERIC MAP ( g_tech_ddr => g_tech_ddr, -- GitLab