diff --git a/libraries/base/dp/tb/vhdl/tb_dp_fifo_xonoff.vhd b/libraries/base/dp/tb/vhdl/tb_dp_fifo_xonoff.vhd new file mode 100644 index 0000000000000000000000000000000000000000..fb93beff2e1e52c3fcbde9d4e0d5dec28f725289 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_dp_fifo_xonoff.vhd @@ -0,0 +1,262 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2023 +-- 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: Eric Kooistra +-- Date: 26 Apr 2023 +-- Purpose: +-- . Test bench for dp_fifos to verify xon flow control when FIFO runs full +-- Description: +-- Verify that the dp_mux will not cause input FIFO overflow when the input +-- load is too large for the output capacity. +-- +-- BG -> xonoff -> fifo_sc -> mux -> xonoff -> fifo <-- out_siso +-- arr arr arr fill +-- sc +-- +-- Usage: +-- . as 12 +-- . run -all +-- Self test result is OK when there is no FAILURE due to FIFO overflow. + +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.common_str_pkg.ALL; +USE common_lib.common_lfsr_sequences_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; +USE work.dp_stream_pkg.ALL; +USE work.tb_dp_pkg.ALL; + +ENTITY tb_dp_fifo_xonoff IS + GENERIC ( + g_nof_inputs : NATURAL := 5; + g_nof_blocks : NATURAL := 300; + g_block_size : NATURAL := 10; + g_gap_size : NATURAL := 0 + ); +END tb_dp_fifo_xonoff; + + +ARCHITECTURE tb OF tb_dp_fifo_xonoff IS + + CONSTANT c_clk_period : TIME := 5 ns; + + CONSTANT c_tb_nof_clk_cycles : NATURAL := g_nof_blocks * g_block_size; + + -- c_fifo_af_ready >= 4, nof words below max (full) at which fifo is considered almost full for snk_out.ready + -- c_fifo_af_xon >= 0, nof words below max (full) at which fifo is considered almost full for snk_out.xon + CONSTANT c_fifo_af_ready : NATURAL := 4; + CONSTANT c_fifo_af_xon : NATURAL := g_block_size + 5; + + CONSTANT c_in_fifo_size : NATURAL := g_block_size * 20; + + CONSTANT c_out_fifo_size : NATURAL := g_block_size * 20; + CONSTANT c_out_fifo_fill : NATURAL := g_block_size; + CONSTANT c_out_fifo_af_xon : NATURAL := g_block_size + 5; + + CONSTANT c_ready_latency : NATURAL := 1; + CONSTANT c_data_w : NATURAL := 16; + CONSTANT c_symbol_w : NATURAL := c_data_w; + CONSTANT c_symbol_init : NATURAL := 0; + CONSTANT c_nof_symbols : NATURAL := g_block_size; + CONSTANT c_bsn : NATURAL := 0; + CONSTANT c_sync : STD_LOGIC := '0'; + + CONSTANT c_nof_input_w : NATURAL := ceil_log2(g_nof_inputs); + + SIGNAL clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '1'; + SIGNAL in_en : STD_LOGIC := '0'; + SIGNAL tb_end : STD_LOGIC := '0'; + + SIGNAL bg_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL bg_sosi_arr : t_dp_sosi_arr(0 TO g_nof_inputs-1); + SIGNAL fifo_in_siso_arr : t_dp_siso_arr(0 TO g_nof_inputs-1); + SIGNAL fifo_in_sosi_arr : t_dp_sosi_arr(0 TO g_nof_inputs-1); + SIGNAL mux_in_siso_arr : t_dp_siso_arr(0 TO g_nof_inputs-1); + SIGNAL mux_in_sosi_arr : t_dp_sosi_arr(0 TO g_nof_inputs-1); + + SIGNAL mux_out_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL mux_out_sosi : t_dp_sosi; + SIGNAL fifo_fill_in_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL fifo_fill_in_sosi : t_dp_sosi; + SIGNAL out_siso : t_dp_siso := c_dp_siso_rdy; + SIGNAL out_sosi : t_dp_sosi; + + -- Monitor FIFO filling + TYPE t_in_fifo_usedw_slv_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(ceil_log2(c_out_fifo_size)-1 DOWNTO 0); + + SIGNAL in_fifo_wr_ful_arr : STD_LOGIC_VECTOR(0 TO g_nof_inputs-1); + SIGNAL in_fifo_usedw_arr : t_in_fifo_usedw_slv_arr(0 TO g_nof_inputs-1); + SIGNAL in_fifo_rd_emp_arr : STD_LOGIC_VECTOR(0 TO g_nof_inputs-1); + SIGNAL out_fifo_wr_ful : STD_LOGIC; + SIGNAL out_fifo_usedw : STD_LOGIC_VECTOR(ceil_log2(c_out_fifo_size)-1 DOWNTO 0); + SIGNAL out_fifo_rd_emp : STD_LOGIC; + +BEGIN + + ------------------------------------------------------------------------------ + -- Clock & reset + ------------------------------------------------------------------------------ + clk <= (NOT clk) OR tb_end AFTER c_clk_period/2; + rst <= '1', '0' AFTER c_clk_period*7; + + ------------------------------------------------------------------------------ + -- Stimuli: + ------------------------------------------------------------------------------ + gen_bg_arr : FOR I IN 0 TO g_nof_inputs-1 GENERATE + p_bg_arr : PROCESS + BEGIN + WHILE TRUE LOOP + proc_dp_gen_frame(c_ready_latency, + c_data_w, + c_symbol_w, + c_symbol_init, + c_nof_symbols, + c_bsn + I, -- use bsn to identify the inputs + c_sync, + clk, + in_en, + bg_siso, + bg_sosi_arr(I)); + WAIT FOR g_gap_size * c_clk_period; + END LOOP; + -- Use WHILE LOOP and WAIT to avoid warning (vcom-1090) Possible infinite loop: + -- Process contains no WAIT statement. + WAIT; + END PROCESS; + + u_dp_xonoff : ENTITY work.dp_xonoff + PORT MAP ( + rst => rst, + clk => clk, + -- Frame in + in_siso => OPEN, + in_sosi => bg_sosi_arr(I), + -- Frame out + out_siso => fifo_in_siso_arr(I), + out_sosi => fifo_in_sosi_arr(I) + ); + + u_in_fifo : ENTITY work.dp_fifo_sc + GENERIC MAP ( + g_data_w => c_data_w, + g_bsn_w => c_nof_input_w, + g_use_bsn => TRUE, -- use bsn to identify the inputs + g_use_ctrl => TRUE, -- sop & eop + g_fifo_size => c_in_fifo_size, + g_fifo_af_margin => c_fifo_af_ready, + g_fifo_af_xon => c_fifo_af_xon, + g_fifo_rl => c_ready_latency + ) + PORT MAP ( + rst => rst, + clk => clk, + -- Monitor FIFO filling + wr_ful => in_fifo_wr_ful_arr(I), + usedw => in_fifo_usedw_arr(I), + rd_emp => in_fifo_rd_emp_arr(I), + -- ST sink + snk_out => fifo_in_siso_arr(I), -- flush control via out_siso.xon + snk_in => fifo_in_sosi_arr(I), + -- ST source + src_in => mux_in_siso_arr(I), + src_out => mux_in_sosi_arr(I) + ); + END GENERATE; + + -- Eanble input after reset and disable it before tb_end, to read FIFOs empty + in_en <= '0', '1' AFTER c_clk_period*17, + '0' AFTER 4 * c_tb_nof_clk_cycles * c_clk_period; + + -- Also verify toggling external siso.xon flow control + out_siso.xon <= '1', + '0' AFTER 2 * c_tb_nof_clk_cycles * c_clk_period, + '1' AFTER 3 * c_tb_nof_clk_cycles * c_clk_period; + + -- End test + tb_end <= '0', '1' AFTER 5 * c_tb_nof_clk_cycles * c_clk_period; + + ------------------------------------------------------------------------------ + -- Multiplexer + ------------------------------------------------------------------------------ + u_dp_mux : ENTITY work.dp_mux + GENERIC MAP ( + g_nof_input => g_nof_inputs, + g_fifo_size => array_init(1024, g_nof_inputs), -- must match g_nof_input, even when g_use_fifo=FALSE + g_fifo_fill => array_init( 0, g_nof_inputs) -- must match g_nof_input, even when g_use_fifo=FALSE + ) + PORT MAP ( + rst => rst, + clk => clk, + -- ST sinks + snk_out_arr => mux_in_siso_arr, + snk_in_arr => mux_in_sosi_arr, + -- ST source + src_in => mux_out_siso, + src_out => mux_out_sosi + ); + + ------------------------------------------------------------------------------ + -- Output + ------------------------------------------------------------------------------ + +-- u_dp_xonoff : ENTITY work.dp_xonoff +-- PORT MAP ( +-- rst => rst, +-- clk => clk, +-- -- Frame in +-- in_siso => mux_out_siso, +-- in_sosi => mux_out_sosi, +-- -- Frame out +-- out_siso => fifo_fill_in_siso, +-- out_sosi => fifo_fill_in_sosi +-- ); + + u_out_fifo : ENTITY work.dp_fifo_fill_sc + GENERIC MAP ( + g_data_w => c_data_w, + g_bsn_w => c_nof_input_w, + g_use_bsn => TRUE, -- use bsn to identify the inputs + g_fifo_fill => c_out_fifo_fill, + g_fifo_size => c_out_fifo_size, + g_fifo_af_margin => c_fifo_af_ready, + g_fifo_af_xon => c_fifo_af_xon, + g_fifo_rl => c_ready_latency + ) + PORT MAP ( + rst => rst, + clk => clk, + -- Monitor FIFO filling + wr_ful => out_fifo_wr_ful, + usedw => out_fifo_usedw, + rd_emp => out_fifo_rd_emp, + -- ST sink + snk_out => mux_out_siso, + snk_in => mux_out_sosi, +-- snk_out => fifo_fill_in_siso, +-- snk_in => fifo_fill_in_sosi, + -- ST source + src_in => out_siso, + src_out => out_sosi + ); + +END tb;