Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
tb_ddrctrl_pack.vhd 5.47 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_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
    g_sim_length              : NATURAL                                     := 52                                 -- determens the lengt of the duration of the test

 );
END tb_ddrctrl_pack;

ARCHITECTURE tb OF tb_ddrctrl_pack IS

  -- 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

  -- 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
    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;

  -- 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

  -- generating clock
  clk               <= NOT clk OR tb_end AFTER c_clk_period/2;

  -- excecuting the test
  p_test : PROCESS
  BEGIN

    -- starting the test
    tb_end            <= '0';
    WAIT UNTIL rising_edge(clk);
    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 g_sim_length-1 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;  

    -- stopping the testbench
    WAIT FOR c_clk_period*4;
    tb_end <= '1';
    ASSERT FALSE                                                                                               REPORT "Test: OK"                                     SEVERITY FAILURE;
  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;

  -- DUT
  u_ddrctrl_pack : ENTITY work.ddrctrl_pack
  GENERIC MAP (
    g_nof_streams     => g_nof_streams,
    g_data_w          => g_data_w
  )
  PORT MAP (
    in_sosi_arr       => in_sosi_arr,

    out_data          => out_data
  );

END tb;