------------------------------------------------------------------------------- -- -- Copyright 2022 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License. -- You may obtain a copy of the License at -- -- http://www.apache.org/licenses/LICENSE-2.0 -- -- Unless required by applicable law or agreed to in writing, software -- distributed under the License is distributed on an "AS IS" BASIS, -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- See the License for the specific language governing permissions and -- limitations under the License. -- ------------------------------------------------------------------------------- -- Author: Job van Wee -- Purpose: Self checking and self-stopping tb for ddrctrl_input.vhd -- Usage: -- > run -a LIBRARY IEEE, common_lib, technology_lib, tech_ddr_lib, dp_lib; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; USE IEEE.MATH_REAL.ALL; USE technology_lib.technology_pkg.ALL; USE tech_ddr_lib.tech_ddr_pkg.ALL; USE dp_lib.dp_stream_pkg.ALL; USE common_lib.common_mem_pkg.ALL; USE common_lib.common_pkg.ALL; ENTITY tb_ddrctrl_input IS GENERIC ( g_tech_ddr : t_c_tech_ddr := c_tech_ddr4_8g_1600m; -- type of memory 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 ); END tb_ddrctrl_input; ARCHITECTURE tb OF tb_ddrctrl_input IS -- constants for testbench CONSTANT c_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation 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 -- 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 := 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 FUNCTION c_total_vector_init RETURN STD_LOGIC_VECTOR IS VARIABLE v_total_vector : STD_LOGIC_VECTOR(c_in_data_w*g_sim_length-1 DOWNTO 0); BEGIN FOR I IN 0 TO g_sim_length*g_nof_streams-1 LOOP v_total_vector(g_data_w*(I+1)-1 DOWNTO g_data_w*I) := TO_UVEC(I, g_data_w); END LOOP; RETURN v_total_vector; 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 -- input signals for ddrctrl_input.vhd SIGNAL clk : STD_LOGIC := '1'; SIGNAL rst : STD_LOGIC := '0'; SIGNAL q_rst : STD_LOGIC := '0'; SIGNAL q_q_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_input.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 signal from ddrctrl_pack.vhd SIGNAL out_adr : NATURAL := 0; -- testbench signal SIGNAL tb_end : STD_LOGIC := '0'; -- signal to turn the testbench off -- 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 q_in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd with a delay of 1 clockcycle SIGNAL q_q_in_data_cnt : NATURAL := 0; -- signal which contains the amount of times there has been input data for ddrctrl_repack.vhd with a delay of 2 clockcycles SIGNAL test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started SIGNAL q_test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started with a delay of 1 clockcycle SIGNAL q_q_test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started with a delay of 2 clockcycles SIGNAL lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest SIGNAL q_lag_due_reset : NATURAL := 0; -- signal to hold the address lag after a rest with a delay of 1 clockcycle BEGIN -- generating clock clk <= NOT clk OR tb_end AFTER c_clk_period/2; -- excecuting test p_test : PROCESS BEGIN -- start the test tb_end <= '0'; WAIT UNTIL rising_edge(clk); -- align to rising edge WAIT FOR c_clk_period*4; rst <= '1'; WAIT FOR c_clk_period*1; rst <= '0'; test_running <= '1'; -- filling the input data vectors with the corresponding numbers make_data : FOR J IN 0 TO g_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); END LOOP; WAIT FOR c_clk_period*1; END LOOP; 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; -- stopping the testbench WAIT FOR c_clk_period*4; tb_end <= '1'; ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE; END PROCESS; -- generating compare data for out_sosi p_out_sosi : PROCESS BEGIN WAIT UNTIL rising_edge(clk); if rising_edge(clk) THEN q_q_rst <= q_rst; q_lag_due_reset <= lag_due_reset; q_rst <= rst; END IF; IF q_rst = '1' THEN 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+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 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 (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; 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 p_verify : PROCESS VARIABLE ctr_of : NATURAL := 0; VARIABLE out_data_cnt : NATURAL := 0; BEGIN WAIT UNTIL rising_edge(clk); IF q_q_test_running = '1' AND out_sosi.valid = '1' THEN out_data_cnt := out_data_cnt+1; IF out_data_cnt mod 2 = 0 THEN ctr_of := c_in_data_w*(q_q_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) & ", out_of = " & NATURAL'image(out_of) SEVERITY ERROR; END IF; ASSERT out_sosi.data(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; END PROCESS; -- DUT u_ddrctrl_input : ENTITY work.ddrctrl_input GENERIC MAP ( g_tech_ddr => g_tech_ddr, g_sim_model => c_sim_model, g_nof_streams => g_nof_streams, g_data_w => g_data_w ) PORT MAP ( clk => clk, rst => rst, in_sosi_arr => in_sosi_arr, out_of => out_of, out_sosi => out_sosi, out_adr => out_adr ); END tb;