------------------------------------------------------------------------------- -- -- 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_pack.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_pack IS GENERIC ( g_nof_streams : POSITIVE := 12; -- number of input streams g_data_w : NATURAL := 14 -- data with of input data vectors ); 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 CONSTANT c_out_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168 FUNCTION c_testv_init RETURN STD_LOGIC_VECTOR IS VARIABLE temp : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); BEGIN FOR I IN 0 TO 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_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 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 SIGNAL out_data : STD_LOGIC_VECTOR(c_out_data_w-1 DOWNTO 0); -- output signal from ddrctrl_pack.vhd BEGIN clk <= NOT clk OR tb_end AFTER c_clk_period/2; -- generating clock signal p_mm : PROCESS BEGIN -- Start the testbench. tb_end <= '0'; WAIT UNTIL rising_edge(clk); -- align to rising edge WAIT FOR c_clk_period*2; -- The input data vectors get filled with the corresponding number. fill_in_sosi_arr : FOR I IN 0 TO g_nof_streams-1 LOOP in_sosi_arr(I).data(g_data_w - 1 DOWNTO 0) <= c_testv(g_data_w * (I + 1) - 1 DOWNTO g_data_w * I); END LOOP; -- The numbers get cycled trough the input vectors. change_in_sosi_arr : FOR J IN 0 TO 4 LOOP WAIT FOR c_clk_period*1; in_sosi_arr(0).data(g_data_w - 1 DOWNTO 0) <= in_sosi_arr(g_nof_streams-1).data(g_data_w - 1 DOWNTO 0); loop_switch_data : FOR I IN 1 TO g_nof_streams-1 LOOP in_sosi_arr(I).data(g_data_w - 1 DOWNTO 0) <= in_sosi_arr(I-1).data(g_data_w - 1 DOWNTO 0); END LOOP; END LOOP; -- Stop the testbench. WAIT FOR c_clk_period*4; tb_end <= '1'; WAIT; END PROCESS; -- Verification by checking if the input vectors equel the corresponding index of the output vector. p_verify : PROCESS BEGIN WAIT UNTIL rising_edge(clk); IF rising_edge(clk) THEN check_data : FOR I IN 0 TO g_nof_streams - 1 LOOP ASSERT out_data(g_data_w * (I + 1) - 1 DOWNTO g_data_w * I) = in_sosi_arr(I).data(g_data_w-1 DOWNTO 0) REPORT "Data does not match, I = " & NATURAL'image(I) SEVERITY ERROR; END LOOP; END IF; END PROCESS; u_ddrctrl_pack : ENTITY work.ddrctrl_pack GENERIC MAP ( g_nof_streams => g_nof_streams, g_data_w => g_data_w ) PORT MAP ( clk => clk, in_sosi_arr => in_sosi_arr, out_data => out_data ); END tb;