diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 2fde174ca6ad410d78783e108d27dffaecb690a2..7559aa613151c7ad258011fd873b9c00f06def6a 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -295,6 +295,7 @@ test_bench_files = tb/vhdl/tb_tb_tb_dp_backpressure.vhd tb/vhdl/tb_dp_offload_tx_v3.vhd tb/vhdl/tb_dp_offload_rx_filter.vhd + tb/vhdl/tb_dp_selector_arr.vhd regression_test_vhdl = tb/vhdl/tb_dp_fifo_to_mm.vhd diff --git a/libraries/base/dp/tb/vhdl/tb_dp_selector_arr.vhd b/libraries/base/dp/tb/vhdl/tb_dp_selector_arr.vhd new file mode 100644 index 0000000000000000000000000000000000000000..e2aa2378a39b58a5f575316c8ffa5c9538b0e970 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_dp_selector_arr.vhd @@ -0,0 +1,195 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- 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: R. van der Walle +-- Purpose: +-- . Test bench for dp_selector_arr +-- Description: +-- . A data stream is offered to g_nof_streams=4 inputs of the DUT. +-- A process asserts mm accesses in time to switch the streams. +-- +-- Usage: +-- > as 10 +-- > run -all +-- +-- Remarks: + +LIBRARY IEEE, common_lib, mm_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_lfsr_sequences_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE common_lib.common_mem_pkg.ALL; +USE common_lib.tb_common_mem_pkg.ALL; +USE work.dp_stream_pkg.ALL; +USE work.tb_dp_pkg.ALL; + +ENTITY tb_dp_selector_arr IS + GENERIC ( + -- specific + g_in_dat_w : NATURAL := 32; + g_in_nof_words : NATURAL := 1; + g_nof_repeat : NATURAL := 20; + g_pkt_len : NATURAL := 16; -- must be a multiple of g_in_nof_words + g_pkt_gap : NATURAL := 4 + ); +END tb_dp_selector_arr; + +ARCHITECTURE tb OF tb_dp_selector_arr IS + + CONSTANT c_nof_streams : NATURAL := 4; + + CONSTANT c_sync_period : NATURAL := 10; + CONSTANT c_sync_offset : NATURAL := 7; + + CONSTANT c_data_max : UNSIGNED(g_in_dat_w-1 DOWNTO 0) := (OTHERS=>'1'); + CONSTANT c_data_init : INTEGER := -1; + CONSTANT c_bsn_init : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := X"0000000000000000"; -- X"0877665544332211" + CONSTANT c_err_init : NATURAL := 247; + CONSTANT c_channel_init : INTEGER := 5; -- fixed + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '1'; + + SIGNAL stimuli_en : STD_LOGIC := '1'; + SIGNAL stimuli_src_in : t_dp_siso; + SIGNAL stimuli_src_out : t_dp_sosi; + + SIGNAL in_sosi_arr : t_dp_sosi_arr(c_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL pipe_sosi_arr : t_dp_sosi_arr(c_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst); + SIGNAL out_sosi_arr : t_dp_sosi_arr(c_nof_streams-1 DOWNTO 0); + + SIGNAL mm_mosi : t_mem_mosi; + SIGNAL mm_miso : t_mem_miso; + +BEGIN + + + clk <= (NOT clk) OR tb_end AFTER clk_period/2; + rst <= '1', '0' AFTER clk_period*7; + + + ------------------------------------------------------------------------------ + -- STREAM CONTROL + ------------------------------------------------------------------------------ + stimuli_en <= '1'; + + ------------------------------------------------------------------------------ + -- DATA GENERATION + ------------------------------------------------------------------------------ + + -- Generate data path input data + p_stimuli_st : PROCESS + VARIABLE v_sosi : t_dp_sosi := c_dp_sosi_rst; + BEGIN + -- Adjust initial sosi field values by -1 to compensate for auto increment + v_sosi.bsn := INCR_UVEC(c_bsn_init, -1); + v_sosi.channel := INCR_UVEC(TO_DP_CHANNEL(c_channel_init), -1); + v_sosi.data := INCR_UVEC(TO_DP_DATA(c_data_init), -1); + v_sosi.err := INCR_UVEC(TO_DP_ERROR(c_err_init), -1); + + stimuli_src_out <= c_dp_sosi_rst; + proc_common_wait_until_low(clk, rst); + proc_common_wait_some_cycles(clk, 5); + + -- Generate c_nof_repeat packets + FOR I IN 0 TO g_nof_repeat-1 LOOP + -- Auto increment v_sosi field values for this packet + v_sosi.bsn := INCR_UVEC(v_sosi.bsn, 1); + v_sosi.sync := sel_a_b((UNSIGNED(v_sosi.bsn) MOD c_sync_period) = c_sync_offset, '1', '0'); -- insert sync starting at BSN=c_sync_offset and with period c_sync_period + v_sosi.channel := INCR_UVEC(v_sosi.channel, 1); + v_sosi.data := INCR_UVEC(v_sosi.data, g_pkt_len); + v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_in_dat_w-1 DOWNTO 0)); -- wrap when >= 2**g_in_dat_w + v_sosi.err := INCR_UVEC(v_sosi.err, 1); + + -- Send packet + proc_dp_gen_block_data(g_in_dat_w, TO_UINT(v_sosi.data), g_pkt_len, TO_UINT(v_sosi.channel), TO_UINT(v_sosi.err), v_sosi.sync, v_sosi.bsn, clk, stimuli_en, stimuli_src_in, stimuli_src_out); + + -- Insert optional gap between the packets + proc_common_wait_some_cycles(clk, g_pkt_gap); + END LOOP; + + -- Signal end of stimuli + proc_common_wait_some_cycles(clk, 50); + tb_end <= '1'; + WAIT; + END PROCESS; + + gen_connect : FOR I IN 0 TO c_nof_streams-1 generate + in_sosi_arr(i) <= stimuli_src_out; + END GENERATE; + + stimuli_src_in <= c_dp_siso_rdy; + + -- Add 1000 to pipe_sosi_arr data to differentiate it from ref_sosi_arr + p_pipe_sosi: PROCESS(in_sosi_arr) + BEGIN + pipe_sosi_arr <= in_sosi_arr; + FOR I IN 0 TO c_nof_streams-1 LOOP + pipe_sosi_arr(I).data <= RESIZE_DP_DATA(INCR_UVEC(in_sosi_arr(I).data, 1000)(g_in_dat_w-1 DOWNTO 0)); + END LOOP; + END PROCESS; + + u_dut : ENTITY work.dp_selector_arr + GENERIC MAP( + g_nof_arr => c_nof_streams, + g_pipeline => 1 + ) + PORT MAP( + -- Memory-mapped clock domain + mm_rst => rst, + mm_clk => clk, + + reg_selector_mosi => mm_mosi, + reg_selector_miso => mm_miso, + + -- Streaming clock domain + dp_rst => rst, + dp_clk => clk, + + -- ST sinks + pipe_sosi_arr => pipe_sosi_arr, + ref_sosi_arr => in_sosi_arr, + -- ST source + out_sosi_arr => out_sosi_arr + ); + + p_stim: PROCESS + BEGIN + WAIT UNTIL rst='0'; + proc_mem_mm_bus_wr(0, x"0", clk, mm_mosi); + + WAIT FOR 500 ns; + + proc_mem_mm_bus_wr(0, x"1", clk, mm_mosi); + + WAIT FOR 1200 ns; + + proc_mem_mm_bus_wr(0, x"0", clk, mm_mosi); + + WAIT; + END PROCESS; + +END tb; +