From 7460dbf635b61e36d3d46624ba947cfc3d78ec0f Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Wed, 15 Feb 2023 13:49:36 +0100 Subject: [PATCH] Add two variants of component that can reverse serial data in a block. --- libraries/base/common/hdllib.cfg | 1 + .../common/src/vhdl/common_reverse_n_data.vhd | 251 ++++++++++++++ libraries/base/dp/hdllib.cfg | 8 + .../base/dp/src/vhdl/dp_reverse_n_data.vhd | 129 +++++++ .../base/dp/src/vhdl/dp_reverse_n_data_fc.vhd | 108 ++++++ .../base/dp/tb/vhdl/tb_dp_reverse_n_data.vhd | 320 ++++++++++++++++++ .../dp/tb/vhdl/tb_dp_reverse_n_data_fc.vhd | 276 +++++++++++++++ .../dp/tb/vhdl/tb_tb_dp_reverse_n_data.vhd | 59 ++++ .../dp/tb/vhdl/tb_tb_dp_reverse_n_data_fc.vhd | 73 ++++ 9 files changed, 1225 insertions(+) create mode 100644 libraries/base/common/src/vhdl/common_reverse_n_data.vhd create mode 100644 libraries/base/dp/src/vhdl/dp_reverse_n_data.vhd create mode 100644 libraries/base/dp/src/vhdl/dp_reverse_n_data_fc.vhd create mode 100644 libraries/base/dp/tb/vhdl/tb_dp_reverse_n_data.vhd create mode 100644 libraries/base/dp/tb/vhdl/tb_dp_reverse_n_data_fc.vhd create mode 100644 libraries/base/dp/tb/vhdl/tb_tb_dp_reverse_n_data.vhd create mode 100644 libraries/base/dp/tb/vhdl/tb_tb_dp_reverse_n_data_fc.vhd diff --git a/libraries/base/common/hdllib.cfg b/libraries/base/common/hdllib.cfg index a5aa29dd84..a9a72853c4 100644 --- a/libraries/base/common/hdllib.cfg +++ b/libraries/base/common/hdllib.cfg @@ -88,6 +88,7 @@ synth_files = src/vhdl/common_reorder_symbol.vhd src/vhdl/common_multiplexer.vhd src/vhdl/common_demultiplexer.vhd + src/vhdl/common_reverse_n_data.vhd src/vhdl/common_transpose_symbol.vhd src/vhdl/common_transpose.vhd src/vhdl/common_peak.vhd diff --git a/libraries/base/common/src/vhdl/common_reverse_n_data.vhd b/libraries/base/common/src/vhdl/common_reverse_n_data.vhd new file mode 100644 index 0000000000..61c3b21077 --- /dev/null +++ b/libraries/base/common/src/vhdl/common_reverse_n_data.vhd @@ -0,0 +1,251 @@ +-------------------------------------------------------------------------------- +-- +-- 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. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE work.common_pkg.ALL; + +-- Author: +-- . Eric Kooistra, 14 Feb 2023 +-- Purpose: +-- . Reverse the order of time multiplexed, serial data per set of every +-- g_reverse_len data values in time. +-- Description: +-- . The implementation does: +-- serial in_data --> +-- parallel demux_data_vec --> +-- reversed parallel reverse_data_vec --> +-- serial out_data +-- . The first in_val after rst release is treated as start of the time +-- multiplexed sets of data. +-- . For example with g_reverse_len = 3, then input in_data 012_345_678 +-- becomes 210_543_876 output out_data. +-- . If in_eop is used to mark the end of in_data blocks, then the in_data +-- blocks size should be an integer multiple of g_reverse_len. If after rst +-- release, the in_val is always marking all in_data block data, then it is +-- fine to leave in_eop = '0', so not connected. +-- Remark: +-- . Typically g_reverse_len should not be too large (~< 4), because then the +-- implementation takes relatively too much logic. +-- . This common_reverse_n_data.vhd is used in dp_reverse_n.vhd and verified +-- in tb_dp_reverse_n.vhd. + +ENTITY common_reverse_n_data IS + GENERIC ( + -- Pipeline: 0 for combinatorial, > 0 for registers + g_pipeline_demux_in : NATURAL := 1; -- serial to parallel demux + g_pipeline_demux_out : NATURAL := 0; + g_pipeline_mux_in : NATURAL := 0; -- parallel to serial mux + g_pipeline_mux_out : NATURAL := 1; + g_reverse_len : NATURAL := 2; + g_data_w : NATURAL := 16 + ); + PORT ( + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; + + in_data : IN STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + in_val : IN STD_LOGIC; + in_eop : IN STD_LOGIC := '0'; + out_data : OUT STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + out_val : OUT STD_LOGIC + ); +END common_reverse_n_data; + + +ARCHITECTURE str OF common_reverse_n_data IS + + CONSTANT c_pipeline_total : NATURAL := g_pipeline_demux_in + g_pipeline_demux_out + + g_reverse_len-1 + + g_pipeline_mux_in + g_pipeline_mux_out; + + CONSTANT c_sel_w : NATURAL := ceil_log2(g_reverse_len); + + SIGNAL in_sel : STD_LOGIC_VECTOR(c_sel_w-1 DOWNTO 0); + SIGNAL nxt_in_sel : STD_LOGIC_VECTOR(c_sel_w-1 DOWNTO 0); + + SIGNAL demux_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + SIGNAL demux_data_vec : STD_LOGIC_VECTOR(g_reverse_len*g_data_w-1 DOWNTO 0); + SIGNAL demux_val_vec : STD_LOGIC_VECTOR(g_reverse_len-1 DOWNTO 0); + + SIGNAL reverse_sel : STD_LOGIC_VECTOR(c_sel_w-1 DOWNTO 0); + SIGNAL reverse_data_vec : STD_LOGIC_VECTOR(g_reverse_len*g_data_w-1 DOWNTO 0); + SIGNAL reverse_val_vec : STD_LOGIC_VECTOR(g_reverse_len-1 DOWNTO 0); + SIGNAL reverse_val : STD_LOGIC; + +BEGIN + + p_clk : PROCESS(rst, clk) + BEGIN + IF rst = '1' THEN + in_sel <= (OTHERS=>'0'); + ELSIF rising_edge(clk) THEN + in_sel <= nxt_in_sel; + END IF; + END PROCESS; + + p_in_sel : PROCESS(in_sel, in_val, in_eop) + BEGIN + nxt_in_sel <= in_sel; + + -- Map multiplexed input to parallel demultiplexed signal index in_sel + IF in_val = '1' THEN + IF UNSIGNED(in_sel) < g_reverse_len-1 THEN + nxt_in_sel <= INCR_UVEC(in_sel, 1); + ELSE + nxt_in_sel <= (OTHERS=>'0'); + END IF; + END IF; + + -- Force that serial to parallel mapping restarts at next sop, in case + -- in_data block length is not an integer multiple of g_reverse_len + IF in_eop = '1' THEN + nxt_in_sel <= (OTHERS=>'0'); + END IF; + END PROCESS; + + u_common_demultiplexer : ENTITY work.common_demultiplexer + GENERIC MAP ( + g_pipeline_in => g_pipeline_demux_in, + g_pipeline_out => g_pipeline_demux_out, + g_nof_out => g_reverse_len, + g_dat_w => g_data_w + ) + PORT MAP ( + rst => rst, + clk => clk, + + in_dat => in_data, + in_val => in_val, + + out_sel => in_sel, + out_dat => demux_data_vec, + out_val => demux_val_vec + ); + + -- All g_reverse_len parts in demux_data_vec carry the same data, the + -- demux_val_vec determines for which demux stream it is. Use demux_data + -- only for view in wave window. + demux_data <= demux_data_vec(g_data_w-1 DOWNTO 0); + + -- Reverse is done by delaying the demultiplexed signal and reversing their + -- indices. The delay per parallel signal is 2*I to reverse them in time. + -- The latency of gen_reverse from in_val to out_val is g_reverse_len-1. + -- The timing diagram shows how gen_reverse and u_mux_n_to_one work, without + -- additional demux and mux pipelining to focus on the reverse function. + -- + -- in_data a b c d e f g h i j k l m + -- _________________________ + -- in_val _| + -- + -- in_sel 0 1 2 0 1 2 0 1 2 0 1 2 0 + -- + -- demux_data a b c d e f g h i j k l m = same in each demux_data_vec[] + -- demux_data_vec[0] a b c d e f g h i j k l m + -- demux_data_vec[1] a b c d e f g h i j k l m + -- demux_data_vec[2] a b c d e f g h i j k l m + -- _ _ _ _ _ + -- demux_val_vec[0] _| |___| |___| |___| |___| | + -- _ _ _ _ + -- demux_val_vec[1] ___| |___| |___| |___| |___ + -- _ _ _ _ + -- demux_val_vec[2] _____| |___| |___| |___| |_ + -- + -- reverse_data_vec[0] a b c d e f g h i j k l m = demux_data_vec[2] with 0 delay + -- reverse_data_vec[1] a b c d e f g h i j k l = demux_data_vec[1] with 2 delay + -- reverse_data_vec[2] a b c d e f g h i j = demux_data_vec[0] with 4 delay + -- _ _ _ _ + -- reverse_val_vec[0] _____| |___| |___| |___| |___ = demux_val_vec[2] with 0 delay + -- _ _ _ _ + -- reverse_val_vec[1] _______| |___| |___| |___| |_ = demux_val_vec[1] with 2 delay + -- _ _ _ _ + -- reverse_val_vec[2] _________| |___| |___| |___| | = demux_val_vec[0] with 4 delay + -- ________________________ + -- reverse_val _____| = vector_or(reverse_val_vec) + -- + -- reverse_sel 0 1 2 0 1 2 0 1 2 0 1 2 = in_sel delayed by g_reverse_len-1 + -- + -- out_data c b a f e d i h g l k j + -- ________________________ + -- out_val _____| + -- + gen_reverse : FOR I IN 0 TO g_reverse_len-1 GENERATE + u_reverse_data : ENTITY work.common_pipeline + GENERIC MAP ( + g_pipeline => 2*I, + g_in_dat_w => g_data_w, + g_out_dat_w => g_data_w + ) + PORT MAP ( + rst => rst, + clk => clk, + in_dat => demux_data_vec((g_reverse_len-1 - I + 1)*g_data_w-1 DOWNTO (g_reverse_len-1 - I)*g_data_w), + out_dat => reverse_data_vec((I+1)*g_data_w-1 DOWNTO I*g_data_w) + ); + + u_reverse_val : ENTITY work.common_pipeline_sl + GENERIC MAP ( + g_pipeline => 2*I + ) + PORT MAP ( + rst => rst, + clk => clk, + in_dat => demux_val_vec(g_reverse_len-1 - I), + out_dat => reverse_val_vec(I) + ); + END GENERATE; + + reverse_val <= vector_or(reverse_val_vec); + + -- pipeline in_sel to align reverse_sel to reverse_data_vec and reverse_val_vec + u_pipe_sel : ENTITY work.common_pipeline + GENERIC MAP ( + g_pipeline => g_pipeline_demux_in + g_pipeline_demux_out + g_reverse_len - 1, + g_in_dat_w => c_sel_w, + g_out_dat_w => c_sel_w + ) + PORT MAP ( + rst => rst, + clk => clk, + in_dat => in_sel, + out_dat => reverse_sel + ); + + u_common_multiplexer : ENTITY work.common_multiplexer + GENERIC MAP ( + g_pipeline_in => g_pipeline_mux_in, + g_pipeline_out => g_pipeline_mux_out, + g_nof_in => g_reverse_len, + g_dat_w => g_data_w + ) + PORT MAP ( + rst => rst, + clk => clk, + + in_sel => reverse_sel, + in_dat => reverse_data_vec, + in_val => reverse_val, + + out_dat => out_data, + out_val => out_val -- = in_val delayed by c_pipeline_total + ); + +END str; diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 4dae8aaf5b..bd4c013312 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -158,6 +158,8 @@ synth_files = src/vhdl/dp_offload_rx.vhd src/vhdl/dp_deinterleave_one_to_n.vhd src/vhdl/dp_interleave_n_to_one.vhd + src/vhdl/dp_reverse_n_data.vhd + src/vhdl/dp_reverse_n_data_fc.vhd src/vhdl/dp_deinterleave.vhd src/vhdl/dp_reinterleave.vhd src/vhdl/mms_dp_gain_arr.vhd @@ -231,6 +233,8 @@ test_bench_files = tb/vhdl/tb_dp_deinterleave_one_to_n_to_one.vhd tb/vhdl/tb_dp_deinterleave_interleave_to_one.vhd tb/vhdl/tb_dp_deinterleave.vhd + tb/vhdl/tb_dp_reverse_n_data.vhd + tb/vhdl/tb_dp_reverse_n_data_fc.vhd tb/vhdl/tb_dp_distribute.vhd tb/vhdl/tb_dp_example_dut.vhd tb/vhdl/tb_dp_fifo_fill.vhd @@ -311,6 +315,8 @@ test_bench_files = tb/vhdl/tb_tb_dp_distribute.vhd tb/vhdl/tb_tb_dp_deinterleave_one_to_n_to_one.vhd tb/vhdl/tb_tb_dp_deinterleave_interleave_to_one.vhd + tb/vhdl/tb_tb_dp_reverse_n_data.vhd + tb/vhdl/tb_tb_dp_reverse_n_data_fc.vhd tb/vhdl/tb_tb_dp_example_dut.vhd tb/vhdl/tb_tb_dp_flush.vhd tb/vhdl/tb_tb_dp_fifo_info.vhd @@ -383,6 +389,8 @@ regression_test_vhdl = tb/vhdl/tb_tb_dp_distribute.vhd tb/vhdl/tb_tb_dp_deinterleave_one_to_n_to_one.vhd tb/vhdl/tb_tb_dp_deinterleave_interleave_to_one.vhd + tb/vhdl/tb_tb_dp_reverse_n_data.vhd + tb/vhdl/tb_tb_dp_reverse_n_data_fc.vhd tb/vhdl/tb_tb_dp_example_dut.vhd tb/vhdl/tb_tb_dp_fifo_dc.vhd tb/vhdl/tb_tb_dp_fifo_dc_mixed_widths.vhd diff --git a/libraries/base/dp/src/vhdl/dp_reverse_n_data.vhd b/libraries/base/dp/src/vhdl/dp_reverse_n_data.vhd new file mode 100644 index 0000000000..0b310e901e --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_reverse_n_data.vhd @@ -0,0 +1,129 @@ +-------------------------------------------------------------------------------- +-- +-- 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. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE,common_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE work.dp_stream_pkg.ALL; + +-- Author: +-- . Eric Kooistra, 14 Feb 2023 +-- Purpose: +-- . Reverse the order of multiplexed data per every g_reverse_len values in +-- time. +-- Description: +-- . The snk_in blocks size must be an integer multiple of g_reverse_len. +-- . For example with g_reverse_len = 3, then snk_in input data 012_345_678 +-- becomes 210_543_876 at src_out output. +-- . See common_reverse_n_data.vhd for more detailed description. +-- Remark: +-- . The dp_reverse_n_data.vhd and dp_reverse_n_data_fc.vhd are functionally +-- equivalent. Use dp_reverse_n_data_fc.vhd flow control (fc) is needed. +-- A difference is that dp_reverse_n_data_fc causes extra gaps in the data +-- valid after each g_reverse_len. Therefore use dp_reverse_n_data when no +-- flow control is needed. +-- . Typically g_reverse_len should not be too large (~< 4), because then the +-- implementation takes relatively too much logic. + +ENTITY dp_reverse_n_data IS + GENERIC ( + -- Pipeline: 0 for combinatorial, > 0 for registers + g_pipeline_demux_in : NATURAL := 1; -- serial to parallel section + g_pipeline_demux_out : NATURAL := 0; + g_pipeline_mux_in : NATURAL := 0; -- parallel to serial section + g_pipeline_mux_out : NATURAL := 1; + g_reverse_len : NATURAL := 2; + g_data_w : NATURAL := 16; + g_signed : BOOLEAN := TRUE + ); + PORT ( + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; + + snk_in : IN t_dp_sosi; + src_out : OUT t_dp_sosi + ); +END dp_reverse_n_data; + + +ARCHITECTURE str OF dp_reverse_n_data IS + + CONSTANT c_pipeline_total : NATURAL := g_pipeline_demux_in + g_pipeline_demux_out + + g_reverse_len-1 + + g_pipeline_mux_in + g_pipeline_mux_out; + + SIGNAL in_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + + SIGNAL reversed_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0); + SIGNAL reversed_val : STD_LOGIC; + + SIGNAL snk_in_delayed : t_dp_sosi; + +BEGIN + + in_data <= snk_in.data(g_data_w-1 DOWNTO 0); + + u_common_reverse_n : ENTITY common_lib.common_reverse_n_data + GENERIC MAP ( + -- Pipeline: 0 for combinatorial, > 0 for registers + g_pipeline_demux_in => g_pipeline_demux_in, -- serial to parallel demux + g_pipeline_demux_out => g_pipeline_demux_out, + g_pipeline_mux_in => g_pipeline_mux_in, -- parallel to serial mux + g_pipeline_mux_out => g_pipeline_mux_out, + g_reverse_len => g_reverse_len, + g_data_w => g_data_w + ) + PORT MAP ( + rst => rst, + clk => clk, + + in_data => in_data, + in_val => snk_in.valid, + in_eop => snk_in.eop, + out_data => reversed_data, + out_val => reversed_val -- = snk_in_delayed.valid + ); + + -- Pipeline other sosi fields + u_pipe_input : ENTITY work.dp_pipeline + GENERIC MAP ( + g_pipeline => c_pipeline_total + ) + PORT MAP ( + rst => rst, + clk => clk, + -- ST sink + snk_in => snk_in, + -- ST source + src_out => snk_in_delayed + ); + + p_src_out : PROCESS(snk_in_delayed, reversed_data) + BEGIN + src_out <= snk_in_delayed; + IF g_signed = TRUE THEN + src_out.data <= RESIZE_DP_SDATA(reversed_data); + ELSE + src_out.data <= RESIZE_DP_DATA(reversed_data); + END IF; + END PROCESS; + +END str; diff --git a/libraries/base/dp/src/vhdl/dp_reverse_n_data_fc.vhd b/libraries/base/dp/src/vhdl/dp_reverse_n_data_fc.vhd new file mode 100644 index 0000000000..d29f7bd895 --- /dev/null +++ b/libraries/base/dp/src/vhdl/dp_reverse_n_data_fc.vhd @@ -0,0 +1,108 @@ +-------------------------------------------------------------------------------- +-- +-- 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. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE,common_lib; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; +USE common_lib.common_pkg.ALL; +USE work.dp_stream_pkg.ALL; + +-- Author: +-- . Eric Kooistra, 14 Feb 2023 +-- Purpose: +-- . Reverse the order of multiplexed data per every g_reverse_len values in +-- time. +-- Description: +-- . The snk_in blocks size must be an integer multiple of g_reverse_len. +-- . For example with g_reverse_len = 3, then snk_in input data 012_345_678 +-- becomes 210_543_876 at src_out output. +-- Remark: +-- . The dp_reverse_n_data.vhd and dp_reverse_n_data_fc.vhd are functionally +-- equivalent. Use dp_reverse_n_data_fc.vhd flow control (fc) is needed. +-- A difference is that dp_reverse_n_data_fc causes extra gaps in the data +-- valid after each g_reverse_len. Therefore use dp_reverse_n_data when no +-- flow control is needed. +-- . Typically g_reverse_len should not be too large (~< 4), because then the +-- implementation takes relatively too much logic. + +ENTITY dp_reverse_n_data_fc IS + GENERIC ( + -- Pipeline: 0 for combinatorial, > 0 for registers + g_pipeline_in : NATURAL := 1; -- serial to parallel section + g_pipeline_out : NATURAL := 0; -- parallel to serial section + g_reverse_len : NATURAL + ); + PORT ( + rst : IN STD_LOGIC; + clk : IN STD_LOGIC; + + snk_out : OUT t_dp_siso; + snk_in : IN t_dp_sosi; + src_in : IN t_dp_siso := c_dp_siso_rdy; + src_out : OUT t_dp_sosi + ); +END dp_reverse_n_data_fc; + + +ARCHITECTURE str OF dp_reverse_n_data_fc IS + + SIGNAL demux_siso_arr : t_dp_siso_arr(g_reverse_len-1 DOWNTO 0); + SIGNAL demux_sosi_arr : t_dp_sosi_arr(g_reverse_len-1 DOWNTO 0); + SIGNAL reverse_siso_arr : t_dp_siso_arr(g_reverse_len-1 DOWNTO 0); + SIGNAL reverse_sosi_arr : t_dp_sosi_arr(g_reverse_len-1 DOWNTO 0); + +BEGIN + + u_demux_one_to_n : ENTITY work.dp_deinterleave_one_to_n + GENERIC MAP ( + g_pipeline => g_pipeline_in, + g_nof_outputs => g_reverse_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + snk_out => snk_out, + snk_in => snk_in, + src_in_arr => demux_siso_arr, + src_out_arr => demux_sosi_arr + ); + + gen_reverse : FOR I IN 0 TO g_reverse_len-1 GENERATE + demux_siso_arr(g_reverse_len-1 - I) <= reverse_siso_arr(I); + reverse_sosi_arr(I) <= demux_sosi_arr(g_reverse_len-1 - I); + END GENERATE; + + u_mux_n_to_one : ENTITY work.dp_interleave_n_to_one + GENERIC MAP ( + g_pipeline => g_pipeline_out, + g_nof_inputs => g_reverse_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + snk_out_arr => reverse_siso_arr, + snk_in_arr => reverse_sosi_arr, + src_in => src_in, + src_out => src_out + ); + +END str; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_reverse_n_data.vhd b/libraries/base/dp/tb/vhdl/tb_dp_reverse_n_data.vhd new file mode 100644 index 0000000000..313153ac26 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_dp_reverse_n_data.vhd @@ -0,0 +1,320 @@ +------------------------------------------------------------------------------- +-- +-- 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, 14 feb 2023 +-- Purpose: +-- . Test bench for dp_reverse_n_data and dp_reverse_n_data_fc. +-- Description: +-- Block diagram: +-- +-- reverse reverse back +-- stimuli --> dp_reverse_n_data --> dp_reverse_n_data --> verify +-- +-- The dp_reverse_n_data has no flow control. The tb does also verify +-- the dp_reverse_n_data_fc, but without using flow control. To +-- verify that dp_reverse_n_data and dp_reverse_n_data_fc with +-- c_dp_siso_rdy then yield the same results. +-- Remark: +-- . Stimuli and verification copied from tb_dp_deinterleave_one_to_n_to_one. +-- +-- Usage: +-- . as 5 +-- . run -all + +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_reverse_n_data IS + GENERIC ( + -- specific + g_pipeline : NATURAL := 1; -- 0 for combinatorial, > 0 for registers + g_nof_repeat : NATURAL := 5; + g_reverse_len : NATURAL := 2; + g_pkt_gap : NATURAL := 10 + ); +END tb_dp_reverse_n_data; + + +ARCHITECTURE tb OF tb_dp_reverse_n_data IS + + CONSTANT c_pkt_len : NATURAL := g_reverse_len * 5; + + -- dp_stream_stimuli + CONSTANT c_stimuli_pulse_active : NATURAL := 3; + CONSTANT c_stimuli_pulse_period : NATURAL := 7; + + CONSTANT c_data_w : NATURAL := 16; + CONSTANT c_data_init : NATURAL := 0; + CONSTANT c_re_init : NATURAL := 7; + CONSTANT c_im_init : NATURAL := 17; + 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 : NATURAL := 5; -- fixed + + -- dp_stream_verify + CONSTANT c_flow_control_latency : NATURAL := c_pkt_len; + + CONSTANT c_data_max : UNSIGNED(c_data_w-1 DOWNTO 0) := (OTHERS=>'1'); + CONSTANT c_dsp_max : UNSIGNED(c_data_w-1 DOWNTO 0) := (OTHERS=>'1'); + + --CONSTANT c_verify_snk_in_cnt_max : t_dp_sosi_unsigned := c_dp_sosi_unsigned_rst; -- default 0 is no wrap + CONSTANT c_verify_snk_in_cnt_max : t_dp_sosi_unsigned := TO_DP_SOSI_UNSIGNED('0', '0', '0', '0', c_data_max, c_dsp_max, c_dsp_max, c_unsigned_0, c_unsigned_0, c_unsigned_0, c_unsigned_0); + CONSTANT c_verify_snk_in_cnt_gap : t_dp_sosi_unsigned := c_dp_sosi_unsigned_ones; -- default only accept increment +1 + + -- both + CONSTANT c_sync_period : NATURAL := 10; + CONSTANT c_sync_offset : NATURAL := 7; + + SIGNAL clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '1'; + SIGNAL tb_end : STD_LOGIC := '0'; + + SIGNAL stimuli_src_out : t_dp_sosi; + SIGNAL stimuli_src_out_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); + + SIGNAL reverse_src_out : t_dp_sosi; + SIGNAL reverse_src_out_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); + + SIGNAL reverse_fc_src_out : t_dp_sosi; + SIGNAL reverse_fc_src_out_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); + + SIGNAL verify_snk_in_enable : t_dp_sosi_sl := c_dp_sosi_sl_rst; + SIGNAL last_snk_in : t_dp_sosi; + SIGNAL last_snk_in_evt : STD_LOGIC; + SIGNAL verify_last_snk_in_evt : t_dp_sosi_sl := c_dp_sosi_sl_rst; + + SIGNAL verify_snk_in : t_dp_sosi; + SIGNAL verify_snk_in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); + + SIGNAL verify_fc_snk_in : t_dp_sosi; + SIGNAL verify_fc_snk_in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); + +BEGIN + + clk <= (NOT clk) OR tb_end AFTER clk_period/2; + rst <= '1', '0' AFTER clk_period*7; + + ------------------------------------------------------------------------------ + -- DATA GENERATION + ------------------------------------------------------------------------------ + + u_dp_stream_stimuli : ENTITY work.dp_stream_stimuli + GENERIC MAP ( + g_instance_nr => 0, -- only one stream so choose index 0 + -- flow control + g_flow_control => e_active, -- always active, no flow control + -- initializations + g_sync_period => c_sync_period, + g_sync_offset => c_sync_offset, + g_use_complex => FALSE, + g_data_init => c_data_init, + g_re_init => c_re_init, + g_im_init => c_im_init, + g_bsn_init => c_bsn_init, + g_err_init => c_err_init, + g_channel_init => c_channel_init, + -- specific + g_in_dat_w => c_data_w, + g_nof_repeat => g_nof_repeat, + g_pkt_len => c_pkt_len, + g_pkt_gap => g_pkt_gap, + g_wait_last_evt => c_flow_control_latency -- number of clk cycles to wait with last_snk_in_evt after finishing the stimuli + ) + PORT MAP ( + rst => rst, + clk => clk, + + -- Generate stimuli + src_in => c_dp_siso_rdy, + src_out => stimuli_src_out, + + -- End of stimuli + last_snk_in => last_snk_in, -- expected verify_snk_in after end of stimuli + last_snk_in_evt => last_snk_in_evt, -- trigger verify to verify the last_snk_in + tb_end => tb_end -- signal end of tb as far as this dp_stream_stimuli is concerned + ); + + + ------------------------------------------------------------------------------ + -- DATA VERIFICATION + ------------------------------------------------------------------------------ + + -- Select fields that need to be verified + -- . during the test + verify_snk_in_enable.sync <= '1'; -- or '0' + verify_snk_in_enable.bsn <= '1'; + verify_snk_in_enable.data <= '1'; + verify_snk_in_enable.valid <= '1'; + verify_snk_in_enable.sop <= '1'; + verify_snk_in_enable.eop <= '1'; + verify_snk_in_enable.empty <= '0'; + verify_snk_in_enable.channel <= '1'; + verify_snk_in_enable.err <= '1'; + + -- . after the test + verify_last_snk_in_evt.sync <= last_snk_in_evt; + verify_last_snk_in_evt.bsn <= last_snk_in_evt; + verify_last_snk_in_evt.data <= last_snk_in_evt; + verify_last_snk_in_evt.valid <= last_snk_in_evt; + verify_last_snk_in_evt.sop <= last_snk_in_evt; + verify_last_snk_in_evt.eop <= last_snk_in_evt; + verify_last_snk_in_evt.empty <= '0'; + verify_last_snk_in_evt.channel <= last_snk_in_evt; + verify_last_snk_in_evt.err <= last_snk_in_evt; + + u_dp_stream_verify : ENTITY work.dp_stream_verify + GENERIC MAP ( + g_instance_nr => 0, -- only one stream so choose index 0 + -- flow control + g_flow_control => e_active, -- always active, no flow control + -- initializations + g_sync_period => c_sync_period, + g_sync_offset => c_sync_offset, + g_snk_in_cnt_max => c_verify_snk_in_cnt_max, + g_snk_in_cnt_gap => c_verify_snk_in_cnt_gap, + -- specific + g_in_dat_w => c_data_w, + g_pkt_len => c_pkt_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + -- Verify data + snk_out => OPEN, + snk_in => verify_snk_in, + + -- During stimuli + verify_snk_in_enable => verify_snk_in_enable, -- enable verify to verify that the verify_snk_in fields are incrementing + + -- End of stimuli + expected_snk_in => last_snk_in, -- expected verify_snk_in after end of stimuli + verify_expected_snk_in_evt => verify_last_snk_in_evt -- trigger verify to verify the last_snk_in + ); + + ------------------------------------------------------------------------------ + -- DUT: Using dp_reverse_n_data + ------------------------------------------------------------------------------ + + -- Use g_pipeline_demux_out = 0 and g_pipeline_mux_in = 0, to have that + -- u_reverse and u_reverse_fc, and u_unreverse and u_unreverse_fc use the + -- same total pipeline, so that their outputs can easily be compared. + + -- Reverse + u_reverse : ENTITY work.dp_reverse_n_data + GENERIC MAP ( + g_pipeline_demux_in => g_pipeline, + g_pipeline_demux_out => 0, + g_pipeline_mux_in => 0, + g_pipeline_mux_out => g_pipeline, + g_reverse_len => g_reverse_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + snk_in => stimuli_src_out, + src_out => reverse_src_out + ); + + -- Reverse again to unreverse + u_unreverse : ENTITY work.dp_reverse_n_data + GENERIC MAP ( + g_pipeline_demux_in => g_pipeline, + g_pipeline_demux_out => 0, + g_pipeline_mux_in => 0, + g_pipeline_mux_out => g_pipeline, + g_reverse_len => g_reverse_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + snk_in => reverse_src_out, + src_out => verify_snk_in + ); + + ------------------------------------------------------------------------------ + -- DUT: Using dp_reverse_n_data_fc, but with c_dp_siso_rdy so no flow control + ------------------------------------------------------------------------------ + + -- Reverse + u_reverse_fc : ENTITY work.dp_reverse_n_data_fc + GENERIC MAP ( + g_pipeline_in => g_pipeline, + g_pipeline_out => g_pipeline, + g_reverse_len => g_reverse_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + snk_in => stimuli_src_out, + src_out => reverse_fc_src_out + ); + + -- Reverse again to unreverse + u_unreverse_fc : ENTITY work.dp_reverse_n_data_fc + GENERIC MAP ( + g_pipeline_in => g_pipeline, + g_pipeline_out => g_pipeline, + g_reverse_len => g_reverse_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + snk_in => reverse_fc_src_out, + src_out => verify_fc_snk_in + ); + + -- Verify that dp_reverse_n_data_fc is equivalent to dp_reverse_n_data, when + -- no flow control is used. + p_verify_fc : PROCESS(clk) + BEGIN + IF rising_edge(clk) THEN + IF verify_snk_in.valid = '1' THEN + ASSERT verify_snk_in = verify_fc_snk_in REPORT "Unexpected verify_fc_snk_in at " & TIME'IMAGE(NOW) SEVERITY ERROR; + END IF; + END IF; + END PROCESS; + + ------------------------------------------------------------------------------ + -- Auxiliary + ------------------------------------------------------------------------------ + + -- Map to slv to ease monitoring in wave window + stimuli_src_out_data <= stimuli_src_out.data(c_data_w-1 DOWNTO 0); + + reverse_src_out_data <= reverse_src_out.data(c_data_w-1 DOWNTO 0); + reverse_fc_src_out_data <= reverse_fc_src_out.data(c_data_w-1 DOWNTO 0); + + verify_snk_in_data <= verify_snk_in.data(c_data_w-1 DOWNTO 0); + verify_fc_snk_in_data <= verify_fc_snk_in.data(c_data_w-1 DOWNTO 0); + +END tb; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_reverse_n_data_fc.vhd b/libraries/base/dp/tb/vhdl/tb_dp_reverse_n_data_fc.vhd new file mode 100644 index 0000000000..fc4ade544f --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_dp_reverse_n_data_fc.vhd @@ -0,0 +1,276 @@ +------------------------------------------------------------------------------- +-- +-- 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, 14 feb 2023 +-- Purpose: +-- . Test bench for dp_reverse_n_data_fc. +-- Description: +-- Block diagram: +-- +-- reverse reverse back +-- stimuli --> dp_reverse_n_data_fc --> dp_reverse_n_data_fc --> verify +-- +-- Remark: +-- . Stimuli and verification copied from tb_dp_deinterleave_one_to_n_to_one. +-- +-- Usage: +-- . as 5 +-- . run -all + +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_reverse_n_data_fc IS + GENERIC ( + -- general + g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control + g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control + -- specific + g_pipeline : NATURAL := 1; -- 0 for combinatorial, > 0 for registers + g_nof_repeat : NATURAL := 5; + g_reverse_len : NATURAL := 7; + g_pkt_gap : NATURAL := 10 + ); +END tb_dp_reverse_n_data_fc; + + +ARCHITECTURE tb OF tb_dp_reverse_n_data_fc IS + + CONSTANT c_pkt_len : NATURAL := g_reverse_len * 5; + + -- dp_stream_stimuli + CONSTANT c_stimuli_pulse_active : NATURAL := 3; + CONSTANT c_stimuli_pulse_period : NATURAL := 7; + + CONSTANT c_data_w : NATURAL := 16; + CONSTANT c_data_init : NATURAL := 0; + CONSTANT c_re_init : NATURAL := 7; + CONSTANT c_im_init : NATURAL := 17; + 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 : NATURAL := 5; -- fixed + + -- dp_stream_verify + CONSTANT c_verify_pulse_active : NATURAL := 1; + CONSTANT c_verify_pulse_period : NATURAL := 5; + + CONSTANT c_flow_control_latency_pls : NATURAL := g_nof_repeat * c_pkt_len * (c_verify_pulse_period*c_stimuli_pulse_period) / (c_stimuli_pulse_active*c_verify_pulse_active); + CONSTANT c_flow_control_latency_rnd : NATURAL := g_nof_repeat * c_pkt_len; + CONSTANT c_flow_control_latency : NATURAL := sel_a_b(g_flow_control_stimuli=e_pulse OR g_flow_control_verify=e_pulse, + c_flow_control_latency_pls, + c_flow_control_latency_rnd); -- worst case value + + CONSTANT c_data_max : UNSIGNED(c_data_w-1 DOWNTO 0) := (OTHERS=>'1'); + CONSTANT c_dsp_max : UNSIGNED(c_data_w-1 DOWNTO 0) := (OTHERS=>'1'); + + --CONSTANT c_verify_snk_in_cnt_max : t_dp_sosi_unsigned := c_dp_sosi_unsigned_rst; -- default 0 is no wrap + CONSTANT c_verify_snk_in_cnt_max : t_dp_sosi_unsigned := TO_DP_SOSI_UNSIGNED('0', '0', '0', '0', c_data_max, c_dsp_max, c_dsp_max, c_unsigned_0, c_unsigned_0, c_unsigned_0, c_unsigned_0); + CONSTANT c_verify_snk_in_cnt_gap : t_dp_sosi_unsigned := c_dp_sosi_unsigned_ones; -- default only accept increment +1 + + -- both + CONSTANT c_sync_period : NATURAL := 10; + CONSTANT c_sync_offset : NATURAL := 7; + + SIGNAL clk : STD_LOGIC := '1'; + SIGNAL rst : STD_LOGIC := '1'; + SIGNAL tb_end : STD_LOGIC := '0'; + + SIGNAL stimuli_src_in : t_dp_siso := c_dp_siso_rdy; + SIGNAL stimuli_src_out : t_dp_sosi; + SIGNAL stimuli_src_out_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); + + SIGNAL reverse_src_in : t_dp_siso; + SIGNAL reverse_src_out : t_dp_sosi; + SIGNAL reverse_src_out_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); + + SIGNAL verify_snk_in_enable : t_dp_sosi_sl := c_dp_sosi_sl_rst; + SIGNAL last_snk_in : t_dp_sosi; + SIGNAL last_snk_in_evt : STD_LOGIC; + SIGNAL verify_last_snk_in_evt : t_dp_sosi_sl := c_dp_sosi_sl_rst; + + SIGNAL verify_snk_out : t_dp_siso := c_dp_siso_rdy; + SIGNAL verify_snk_in : t_dp_sosi; + SIGNAL verify_snk_in_data : STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0); + +BEGIN + + clk <= (NOT clk) OR tb_end AFTER clk_period/2; + rst <= '1', '0' AFTER clk_period*7; + + ------------------------------------------------------------------------------ + -- DATA GENERATION + ------------------------------------------------------------------------------ + + u_dp_stream_stimuli : ENTITY work.dp_stream_stimuli + GENERIC MAP ( + g_instance_nr => 0, -- only one stream so choose index 0 + -- flow control + g_random_w => 15, -- use different random width for stimuli and for verify to have different random sequences + g_pulse_active => c_stimuli_pulse_active, + g_pulse_period => c_stimuli_pulse_period, + g_flow_control => g_flow_control_stimuli, -- always active, random or pulse flow control + -- initializations + g_sync_period => c_sync_period, + g_sync_offset => c_sync_offset, + g_use_complex => FALSE, + g_data_init => c_data_init, + g_re_init => c_re_init, + g_im_init => c_im_init, + g_bsn_init => c_bsn_init, + g_err_init => c_err_init, + g_channel_init => c_channel_init, + -- specific + g_in_dat_w => c_data_w, + g_nof_repeat => g_nof_repeat, + g_pkt_len => c_pkt_len, + g_pkt_gap => g_pkt_gap, + g_wait_last_evt => c_flow_control_latency -- number of clk cycles to wait with last_snk_in_evt after finishing the stimuli + ) + PORT MAP ( + rst => rst, + clk => clk, + + -- Generate stimuli + src_in => stimuli_src_in, + src_out => stimuli_src_out, + + -- End of stimuli + last_snk_in => last_snk_in, -- expected verify_snk_in after end of stimuli + last_snk_in_evt => last_snk_in_evt, -- trigger verify to verify the last_snk_in + tb_end => tb_end -- signal end of tb as far as this dp_stream_stimuli is concerned + ); + + + ------------------------------------------------------------------------------ + -- DATA VERIFICATION + ------------------------------------------------------------------------------ + + -- Select fields that need to be verified + -- . during the test + verify_snk_in_enable.sync <= '1'; -- or '0' + verify_snk_in_enable.bsn <= '1'; + verify_snk_in_enable.data <= '1'; + verify_snk_in_enable.valid <= '1'; + verify_snk_in_enable.sop <= '1'; + verify_snk_in_enable.eop <= '1'; + verify_snk_in_enable.empty <= '0'; + verify_snk_in_enable.channel <= '1'; + verify_snk_in_enable.err <= '1'; + + -- . after the test + verify_last_snk_in_evt.sync <= last_snk_in_evt; + verify_last_snk_in_evt.bsn <= last_snk_in_evt; + verify_last_snk_in_evt.data <= last_snk_in_evt; + verify_last_snk_in_evt.valid <= last_snk_in_evt; + verify_last_snk_in_evt.sop <= last_snk_in_evt; + verify_last_snk_in_evt.eop <= last_snk_in_evt; + verify_last_snk_in_evt.empty <= '0'; + verify_last_snk_in_evt.channel <= last_snk_in_evt; + verify_last_snk_in_evt.err <= last_snk_in_evt; + + u_dp_stream_verify : ENTITY work.dp_stream_verify + GENERIC MAP ( + g_instance_nr => 0, -- only one stream so choose index 0 + -- flow control + g_random_w => 14, -- use different random width for stimuli and for verify to have different random sequences + g_pulse_active => c_verify_pulse_active, + g_pulse_period => c_verify_pulse_period, + g_flow_control => g_flow_control_verify, -- always active, random or pulse flow control + -- initializations + g_sync_period => c_sync_period, + g_sync_offset => c_sync_offset, + g_snk_in_cnt_max => c_verify_snk_in_cnt_max, + g_snk_in_cnt_gap => c_verify_snk_in_cnt_gap, + -- specific + g_in_dat_w => c_data_w, + g_pkt_len => c_pkt_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + -- Verify data + snk_out => verify_snk_out, + snk_in => verify_snk_in, + + -- During stimuli + verify_snk_in_enable => verify_snk_in_enable, -- enable verify to verify that the verify_snk_in fields are incrementing + + -- End of stimuli + expected_snk_in => last_snk_in, -- expected verify_snk_in after end of stimuli + verify_expected_snk_in_evt => verify_last_snk_in_evt -- trigger verify to verify the last_snk_in + ); + + ------------------------------------------------------------------------------ + -- DUT + ------------------------------------------------------------------------------ + + -- Reverse + u_reverse_fc : ENTITY work.dp_reverse_n_data_fc + GENERIC MAP ( + g_pipeline_in => g_pipeline, + g_pipeline_out => g_pipeline, + g_reverse_len => g_reverse_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + snk_out => stimuli_src_in, + snk_in => stimuli_src_out, + src_in => reverse_src_in, + src_out => reverse_src_out + ); + + -- Reverse again to unreverse + u_unreverse_fc : ENTITY work.dp_reverse_n_data_fc + GENERIC MAP ( + g_pipeline_in => g_pipeline, + g_pipeline_out => g_pipeline, + g_reverse_len => g_reverse_len + ) + PORT MAP ( + rst => rst, + clk => clk, + + snk_out => reverse_src_in, + snk_in => reverse_src_out, + src_in => verify_snk_out, + src_out => verify_snk_in + ); + + ------------------------------------------------------------------------------ + -- Auxiliary + ------------------------------------------------------------------------------ + + -- Map to slv to ease monitoring in wave window + stimuli_src_out_data <= stimuli_src_out.data(c_data_w-1 DOWNTO 0); + reverse_src_out_data <= reverse_src_out.data(c_data_w-1 DOWNTO 0); + verify_snk_in_data <= verify_snk_in.data(c_data_w-1 DOWNTO 0); + +END tb; diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_reverse_n_data.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_reverse_n_data.vhd new file mode 100644 index 0000000000..832d3e08d8 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_reverse_n_data.vhd @@ -0,0 +1,59 @@ +------------------------------------------------------------------------------- +-- +-- 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, 14 feb 2023 +-- Purpose: Verify multiple variations of tb_dp_reverse_n_data +-- Description: +-- Usage: +-- > as 3 +-- > run -all + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE work.tb_dp_pkg.ALL; + +ENTITY tb_tb_dp_reverse_n_data IS +END tb_tb_dp_reverse_n_data; + + +ARCHITECTURE tb OF tb_tb_dp_reverse_n_data IS + + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' + + CONSTANT c_rep_act : NATURAL := 3; + +BEGIN + +-- g_pipeline : NATURAL := 1; -- 0 for combinatorial, > 0 for registers +-- g_nof_repeat : NATURAL := 5; +-- g_reverse_len : NATURAL := 4; +-- g_pkt_gap : NATURAL := 0 + +-- g_pipeline +-- | g_reverse_len +-- | | g_pkt_gap +-- | | | + u_pipe_1_0 : ENTITY work.tb_dp_reverse_n_data GENERIC MAP(1, c_rep_act, 1, 0); + u_comb_2_0 : ENTITY work.tb_dp_reverse_n_data GENERIC MAP(0, c_rep_act, 2, 0); + u_pipe_2_0 : ENTITY work.tb_dp_reverse_n_data GENERIC MAP(1, c_rep_act, 2, 0); + u_comb_3_5 : ENTITY work.tb_dp_reverse_n_data GENERIC MAP(0, c_rep_act, 3, 5); + u_pipe_3_5 : ENTITY work.tb_dp_reverse_n_data GENERIC MAP(1, c_rep_act, 3, 5); + +END tb; diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_reverse_n_data_fc.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_reverse_n_data_fc.vhd new file mode 100644 index 0000000000..d34661cc68 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_reverse_n_data_fc.vhd @@ -0,0 +1,73 @@ +------------------------------------------------------------------------------- +-- +-- 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, 14 feb 2023 +-- Purpose: Verify multiple variations of tb_dp_reverse_n_data +-- Description: +-- Usage: +-- > as 3 +-- > run -all + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE work.tb_dp_pkg.ALL; + +ENTITY tb_tb_dp_reverse_n_data_fc IS +END tb_tb_dp_reverse_n_data_fc; + + +ARCHITECTURE tb OF tb_tb_dp_reverse_n_data_fc IS + + SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' + + CONSTANT c_rep_act : NATURAL := 3; + CONSTANT c_rep_rnd : NATURAL := 100; + +BEGIN + +-- -- general +-- g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control +-- g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always e_active, e_random or e_pulse flow control +-- -- specific +-- g_pipeline : NATURAL := 1; -- 0 for combinatorial, > 0 for registers +-- g_nof_repeat : NATURAL := 5; +-- g_reverse_len : NATURAL := 4; +-- g_pkt_gap : NATURAL := 0 + +-- g_pipeline +-- | g_reverse_len +-- | | g_pkt_gap +-- | | | + u_act_act_pipe_1_0 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_active, e_active, 1, c_rep_act, 1, 0); + u_act_act_pipe_2_0 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_active, e_active, 1, c_rep_act, 2, 0); + u_act_act_pipe_4_7 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_active, e_active, 1, c_rep_act, 4, 7); + u_act_act_comb_4_7 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_active, e_active, 0, c_rep_act, 4, 7); + + u_rnd_rnd_pipe_1_0 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_random, e_random, 1, c_rep_rnd, 1, 0); + u_rnd_rnd_pipe_2_0 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_random, e_random, 1, c_rep_rnd, 2, 0); + u_rnd_rnd_pipe_4_0 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_random, e_random, 1, c_rep_rnd, 4, 0); + u_rnd_rnd_pipe_4_7 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_random, e_random, 1, c_rep_rnd, 4, 7); + + u_pls_pls_comb_3_0 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_pulse, e_pulse, 0, c_rep_rnd, 3, 0); + u_pls_pls_pipe_3_0 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_pulse, e_pulse, 1, c_rep_rnd, 3, 0); + u_rnd_rnd_comb_3_0 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_random, e_random, 0, c_rep_rnd, 3, 0); + u_rnd_rnd_pipe_3_0 : ENTITY work.tb_dp_reverse_n_data_fc GENERIC MAP(e_random, e_random, 1, c_rep_rnd, 3, 0); + +END tb; -- GitLab