-
Job van Wee authoredJob van Wee authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tb_ddrctrl.vhd 11.62 KiB
-------------------------------------------------------------------------------
--
-- 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.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;
USE technology_lib.technology_select_pkg.ALL;
ENTITY tb_ddrctrl 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 := 16500; -- close to the amount of word that gets put into the memory
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;
g_stop_percentage : NATURAL := 80 -- percentage there needs to be already written in the ddr memory when a stop gets triggered
);
END tb_ddrctrl;
ARCHITECTURE tb OF tb_ddrctrl IS
CONSTANT c_sim_model : BOOLEAN := TRUE; -- determens if this is a simulation
-- 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);
CONSTANT c_sim_ddr : t_c_tech_ddr := func_tech_sel_ddr(g_technology, c_tech_ddr3_sim_16k, c_tech_ddr4_sim_16k);
CONSTANT c_tech_ddr : t_c_tech_ddr := func_tech_sel_ddr(c_sim_model, c_sim_ddr, c_mem_ddr);
-- constants for readability
CONSTANT c_ctrl_data_w : NATURAL := func_tech_ddr_ctlr_data_w( c_tech_ddr ); -- 576
CONSTANT c_in_data_w : NATURAL := g_nof_streams * g_data_w; -- output data with, 168
-- 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_mm_clk_freq : NATURAL := 100; -- mm clock frequency in MHz
CONSTANT c_mm_clk_period : TIME := (10**6/c_mm_clk_freq)*1 ps; -- mm clock period, 10 ns
CONSTANT c_sim_length : NATURAL := (g_sim_length*c_ctrl_data_w)/c_in_data_w; -- amount of input words that get put into the DUT
-- constant for checking output data
CONSTANT c_adr_w : NATURAL := func_tech_ddr_ctlr_address_w( c_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_output_stop_adr : NATURAL := (c_max_adr+1)-((((c_max_adr+1)/64)*g_stop_percentage/100)*64);
CONSTANT c_output_ds : NATURAL := 144;
-- 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*c_sim_length-1 DOWNTO 0);
VARIABLE conv : STD_LOGIC_VECTOR(32-1 DOWNTO 0); -- removes a warning
BEGIN
FOR I IN 0 TO c_sim_length-1 LOOP
conv := TO_UVEC(I, 32);
FOR J IN 0 TO g_nof_streams-1 LOOP
temp(g_data_w*((I*g_nof_streams)+J+1)-1 DOWNTO g_data_w*((I*g_nof_streams)+j)) := conv(g_data_w-1 DOWNTO 0);
END LOOP;
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*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
CONSTANT c_check : NATURAL := 32;
CONSTANT c_check_bottom : NATURAL := 5;
CONSTANT c_ones : STD_LOGIC_VECTOR(c_check-c_check_bottom-1 DOWNTO 0) := (OTHERS => '1');
-- input signals for ddrctrl.vhd
SIGNAL clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '0';
SIGNAL mm_clk : STD_LOGIC := '0';
SIGNAL mm_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
SIGNAL stop_in : STD_LOGIC := '0';
SIGNAL bsn : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_init);
-- 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 test_running : STD_LOGIC := '0'; -- signal to tell wheter the testing has started
-- signals for checking the output data
SIGNAL output_data_cnt : NATURAL := 0;
-- PHY
SIGNAL phy3_io : t_tech_ddr3_phy_io;
SIGNAL phy3_ou : t_tech_ddr3_phy_ou;
SIGNAL phy4_io : t_tech_ddr4_phy_io;
SIGNAL phy4_ou : t_tech_ddr4_phy_ou;
BEGIN
-- generating clock
clk <= NOT clk OR tb_end AFTER c_clk_period/2;
mm_clk <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2;
-- excecuting test
p_test : PROCESS
BEGIN
bsn(c_check-1 DOWNTO c_check_bottom) <= c_ones(c_check-c_check_bottom-1 DOWNTO 0);
-- start the test
tb_end <= '0';
WAIT UNTIL rising_edge(clk); -- align to rising edge
WAIT FOR c_clk_period*4;
rst <= '1';
mm_rst <= '1';
WAIT FOR c_clk_period*1;
rst <= '0';
mm_rst <= '0';
test_running <= '1';
WAIT FOR c_clk_period*1;
-- filling the input data vectors with the corresponding numbers
run_multiple_times : FOR K in 0 TO 4 LOOP
make_data : FOR J IN 0 TO c_sim_length-1 LOOP
in_data_cnt <= in_data_cnt+1;
fill_in_sosi_arr_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;
in_sosi_arr(0).bsn(c_dp_stream_bsn_w-1 DOWNTO 0) <= bsn(c_dp_stream_bsn_w-1 DOWNTO 0);
bsn <= INCR_UVEC(bsn, 1);
IF K = 1 AND J = 0 THEN
stop_in <= '1';
ELSE
stop_in <= '0';
END IF;
WAIT FOR c_clk_period*1;
END LOOP;
END LOOP;
test_running <= '0';
-- stopping the testbench
WAIT FOR c_clk_period*4;
tb_end <= '1';
ASSERT FALSE REPORT "Test: OK" SEVERITY FAILURE;
END PROCESS;
p_checking_output_data : PROCESS
BEGIN
WAIT UNTIL rising_edge(clk);
IF out_sosi_arr(0).valid = '1' THEN
--assert false report "checking" severity note;
FOR I IN 0 TO g_nof_streams-1 LOOP
IF c_output_stop_adr+output_data_cnt <= c_max_adr THEN
ASSERT out_sosi_arr(I).data(c_in_data_w-1 DOWNTO 0) = c_total_vector(g_data_w*(I+1)+(c_output_stop_adr+output_data_cnt)*c_ctrl_data_w-1 DOWNTO g_data_w*I+(c_output_stop_adr+output_data_cnt)*c_ctrl_data_w) REPORT "wrong output data at: " & NATURAL'image(c_output_stop_adr+output_data_cnt) SEVERITY ERROR;
ELSE
ASSERT out_sosi_arr(I).data(c_in_data_w-1 DOWNTO 0) = c_total_vector(g_data_w*(I+1)+(c_output_stop_adr+output_data_cnt-c_max_adr)*c_ctrl_data_w-1 DOWNTO g_data_w*I+(c_output_stop_adr+output_data_cnt-c_max_adr)*c_ctrl_data_w) REPORT "wrong output data at: " & NATURAL'image(c_output_stop_adr+output_data_cnt) SEVERITY ERROR;
END IF;
END LOOP;
output_data_cnt <= output_data_cnt+1;
END IF;
WAIT FOR c_clk_period*1;
END PROCESS;
-- DUT
u_ddrctrl : ENTITY work.ddrctrl
GENERIC MAP (
g_tech_ddr => c_tech_ddr,
g_sim_model => c_sim_model,
g_technology => g_technology,
g_nof_streams => g_nof_streams,
g_data_w => g_data_w,
g_stop_percentage => g_stop_percentage
)
PORT MAP (
clk => clk,
rst => rst,
mm_clk => mm_clk,
mm_rst => mm_rst,
in_sosi_arr => in_sosi_arr,
stop_in => stop_in,
out_sosi_arr => out_sosi_arr,
--PHY
phy3_io => phy3_io,
phy3_ou => phy3_ou,
phy4_io => phy4_io,
phy4_ou => phy4_ou
);
END tb;