Skip to content
Snippets Groups Projects
Select Git revision
  • de83af40f39642a11d9e12df2d9566bd7df81b55
  • master default protected
  • RTSD-375
  • L2SDP-1134
  • L2SDP-1137
  • L2SDP-LIFT
  • L2SDP-1113
  • HPR-158
8 results

ddrctrl_input_repack.vhd

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    tb_ddrctrl.vhd 11.05 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;
    
    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;                                    -- 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_length              : NATURAL                                               := 52
    
      );
    END tb_ddrctrl;
    
    ARCHITECTURE tb OF tb_ddrctrl IS
    
      -- 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
    
      -- 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;                                       -- 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 temp             : 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
          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 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.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.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
    
      -- 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_mosi
      p_out_mosi : 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 + 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;
        END IF;
      END PROCESS;
    
      -- verifying if the address is correct by keeping track of the address
      p_verify_address : PROCESS
      BEGIN
        FOR I IN 0 TO c_adr_size-1 LOOP
          IF I >= q_lag_due_reset THEN
            ASSERT I-q_lag_due_reset   = TO_UINT(out_mosi.address)                                                                            REPORT "Wrong address, 1, I = " & NATURAL'image(I-q_lag_due_reset) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address))                SEVERITY ERROR;
          ELSE
            ASSERT (I-q_lag_due_reset)+c_adr_size = TO_UINT(out_mosi.address)                                                                 REPORT "Wrong address, 2, I = " & NATURAL'image((I-q_lag_due_reset)+c_adr_size) & ", address = " & NATURAL'image(TO_UINT(out_mosi.address))   SEVERITY ERROR;
          END IF;
          WAIT UNTIL out_mosi.wr = '1';
          IF q_q_rst = '1' THEN
            WAIT UNTIL out_mosi.wr = '1';
          END IF;
        END LOOP;
      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_mosi.wr = '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_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;
      END PROCESS;
    
    
      -- DUT
      u_ddrctrl : ENTITY work.ddrctrl
      GENERIC MAP (
        g_tech_ddr        => g_tech_ddr,
        g_sim_model       => g_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_mosi          => out_mosi
      );
    
    END tb;