From 689a41b4decf5c91aee8be90565f315e3e08f2e5 Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Wed, 6 Sep 2023 10:53:49 +0200 Subject: [PATCH] Add dp_packet_unmerge.vhd with tb and tb_tb. --- libraries/base/dp/hdllib.cfg | 33 +- .../base/dp/src/vhdl/dp_packet_unmerge.vhd | 135 +++++++- .../dp/tb/vhdl/tb_dp_packet_merge_unmerge.vhd | 299 ++++++++++++++++++ .../tb/vhdl/tb_tb_dp_packet_merge_unmerge.vhd | 74 +++++ 4 files changed, 517 insertions(+), 24 deletions(-) create mode 100644 libraries/base/dp/tb/vhdl/tb_dp_packet_merge_unmerge.vhd create mode 100644 libraries/base/dp/tb/vhdl/tb_tb_dp_packet_merge_unmerge.vhd diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg index 8d50013850..f205872d5f 100644 --- a/libraries/base/dp/hdllib.cfg +++ b/libraries/base/dp/hdllib.cfg @@ -1,8 +1,8 @@ hdl_lib_name = dp hdl_library_clause_name = dp_lib -hdl_lib_uses_synth = mm common common_mult easics -hdl_lib_uses_sim = -hdl_lib_technology = +hdl_lib_uses_synth = mm common common_mult easics +hdl_lib_uses_sim = +hdl_lib_technology = synth_files = src/vhdl/dp_stream_pkg.vhd @@ -10,7 +10,7 @@ synth_files = src/vhdl/dp_example_dut.vhd src/vhdl/dp_packetizing_pkg.vhd src/vhdl/dp_packet_pkg.vhd - + src/vhdl/dp_eop_extend.vhd src/vhdl/dp_validate.vhd src/vhdl/dp_ready.vhd @@ -147,7 +147,7 @@ synth_files = src/vhdl/dp_packet_unmerge.vhd src/vhdl/dp_offload_tx_legacy.vhd - src/vhdl/dp_offload_tx_len_calc.vhd + src/vhdl/dp_offload_tx_len_calc.vhd src/vhdl/dp_sync_insert.vhd src/vhdl/dp_sync_insert_v2.vhd src/vhdl/dp_sync_recover.vhd @@ -192,20 +192,20 @@ synth_files = src/vhdl/dp_selector_arr.vhd src/vhdl/dp_selector.vhd src/vhdl/mms_dp_scale.vhd - + tb/vhdl/dp_stream_player.vhd tb/vhdl/dp_sosi_recorder.vhd tb/vhdl/dp_stream_rec_play.vhd tb/vhdl/dp_statistics.vhd - + tb/vhdl/tb_dp_pkg.vhd - -test_bench_files = - + +test_bench_files = + tb/vhdl/dp_phy_link.vhd tb/vhdl/dp_stream_stimuli.vhd tb/vhdl/dp_stream_verify.vhd - + tb/vhdl/tb_dp_strobe_total_count.vhd tb/vhdl/tb_dp_block_select.vhd tb/vhdl/tb_dp_block_validate_length.vhd @@ -266,6 +266,7 @@ test_bench_files = tb/vhdl/tb_dp_concat_field_blk.vhd tb/vhdl/tb_dp_packet.vhd tb/vhdl/tb_dp_packet_merge.vhd + tb/vhdl/tb_dp_packet_merge_unmerge.vhd tb/vhdl/tb_dp_packetizing.vhd tb/vhdl/tb_dp_pad_insert_remove.vhd tb/vhdl/tb_dp_pipeline.vhd @@ -344,6 +345,7 @@ test_bench_files = tb/vhdl/tb_tb_dp_packetizing.vhd tb/vhdl/tb_tb_dp_packet.vhd tb/vhdl/tb_tb_dp_packet_merge.vhd + tb/vhdl/tb_tb_dp_packet_merge_unmerge.vhd tb/vhdl/tb_tb_dp_concat_field_blk.vhd tb/vhdl/tb_tb_dp_pipeline.vhd tb/vhdl/tb_tb_dp_pipeline_ready.vhd @@ -360,7 +362,7 @@ test_bench_files = tb/vhdl/tb_tb_dp_throttle_xon.vhd tb/vhdl/tb_tb_dp_counter.vhd tb/vhdl/tb_tb_dp_xonoff.vhd - + tb/vhdl/tb_tb_tb_dp_backpressure.vhd tb/vhdl/tb_dp_offload_tx_v3.vhd tb/vhdl/tb_tb_dp_offload_tx_v3.vhd @@ -368,7 +370,7 @@ test_bench_files = tb/vhdl/tb_dp_selector_arr.vhd tb/vhdl/tb_mms_dp_scale.vhd -regression_test_vhdl = +regression_test_vhdl = tb/vhdl/tb_dp_fifo_to_mm.vhd tb/vhdl/tb_dp_fifo_xonoff.vhd tb/vhdl/tb_dp_latency_adapter.vhd @@ -403,8 +405,8 @@ regression_test_vhdl = 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 + tb/vhdl/tb_tb_dp_fifo_dc.vhd + tb/vhdl/tb_tb_dp_fifo_dc_mixed_widths.vhd tb/vhdl/tb_tb_dp_fifo_fill.vhd tb/vhdl/tb_tb_dp_fifo_fill_sc.vhd tb/vhdl/tb_tb_dp_fifo_fill_eop.vhd @@ -417,6 +419,7 @@ regression_test_vhdl = tb/vhdl/tb_tb3_dp_mux.vhd tb/vhdl/tb_tb_dp_packet.vhd tb/vhdl/tb_tb_dp_packet_merge.vhd + tb/vhdl/tb_tb_dp_packet_merge_unmerge.vhd tb/vhdl/tb_tb_dp_concat_field_blk.vhd tb/vhdl/tb_tb_dp_pad_insert_remove.vhd tb/vhdl/tb_tb_dp_pipeline.vhd diff --git a/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd b/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd index 1fe7ebd08f..d7f294f821 100644 --- a/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd +++ b/libraries/base/dp/src/vhdl/dp_packet_unmerge.vhd @@ -19,13 +19,31 @@ -- -------------------------------------------------------------------------------- --- Purpose: Unmerge each input packet into g_nof_pkt output packets. Below is the --- waveform when g_nof_pkt = 3. The numbers in snk_in.sop and snk_in.eop --- match pkt_cnt. +-- Purpose: Unmerge each input packet into output packets of length g_pkt_len. +-- Description: +-- . The merged packet length of the snk_in input packets must be an integer +-- multiple of g_pkt_len. The number of output packets g_nof_pkt_max is only +-- used to determine the maximum supported pkt_cnt range. The actual number +-- of output packets has to be <= g_nof_pkt_max, and is determined by input +-- packet length / g_pkt_len. Hence the dp_packet_unmerge can dynamically +-- handle different sizes of input packets, provided that their length is an +-- integer multiple of g_pkt_len. +-- . The pkt_cnt is passed on as src_out.channel index. +-- . The g_bsn_increment sets the BSN increment for the unmerged output +-- packets relative to the BSN of the snk_in input packet. When +-- g_bsn_increment = 0, then all unmerged output packets get the same BSN as +-- the input packet. +-- . The input snk_in.err and snk_in.empty are valid at the snk_in.eop, but +-- that is too late to apply them to the unmerged packets. Therefor assume +-- that the snk_in.err and snk_in_eop are already valid at the snk_in.sop +-- and remain valid until the snk_in.eop. Hence these signals are then valid +-- when snk_in.valid = '1'. Use same snk_in.err and snk_in.empty value for +-- all unmerged packets. +-- -- _ _ _ --- snk_in.sop _____|0|___________________________|1|___________________________|2|_ +-- snk_in.sop _____| |___________________________| |___________________________| |_ -- _ _ --- snk_in.sop _________________________________|0|___________________________|1|___ +-- snk_in.eop _________________________________| |___________________________| |___ -- _ _ _ _ _ _ _ -- src_out.sop _____|0|_______|1|_______|2|_______|0|_______|1|_______|2|_______|0|_ -- _ _ _ _ _ _ @@ -39,8 +57,9 @@ use work.dp_stream_pkg.all; entity dp_packet_unmerge is generic ( - g_nof_pkt : natural := 1; -- Nof packets to unmerge each incoming packet to - g_pkt_len : natural := 1 -- Length of the unmerged packets + g_nof_pkt_max : natural := 1; -- Maximum nof packets to unmerge each incoming packet to + g_pkt_len : natural := 1; -- Length of the unmerged packets + g_bsn_increment : natural := 0 ); port ( rst : in std_logic; @@ -55,8 +74,106 @@ entity dp_packet_unmerge is end dp_packet_unmerge; architecture rtl of dp_packet_unmerge is + type t_reg is record + pkt_cnt : natural range 0 to g_nof_pkt_max + 1; + val_cnt : natural range 0 to g_pkt_len + 1; + src_out : t_dp_sosi; + end record; + + constant c_reg_rst : t_reg := (0, 0, c_dp_sosi_rst); + + signal r : t_reg; + signal d : t_reg; + begin - -- Temporary void component that assigns output = input + -- Map t_reg outputs to entity outputs snk_out <= src_in; - src_out <= snk_in; + src_out <= r.src_out; + + -- p_reg + r <= d when rising_edge(clk); + + p_comb : process(rst, r, snk_in) + variable v : t_reg; + begin + -- Default + v := r; + + -- Function + -- _ _ _ + -- snk_in.sop __| |_______________| |_______________| |_______________| + -- _ _ _ + -- snk_in.eop _________________| |_______________| |_______________| |_ + -- _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ + -- snk_in.valid __| + -- v.val_cnt 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + -- v.pkt_cnt 0 1 2 0 1 2 0 1 2 + -- ______________ _______________ _______________ _ + -- v.busy __| |_| |_| |_| + -- _ _ _ _ _ _ _ _ _ + -- v.src_out.sop __|0|___|1|___|2|___|0|___|1|___|2|___|0|___|1|___|2|___| + -- _ _ _ _ _ _ _ _ _ + -- v.src_out.eop _____|0|___|1|___|2|___|0|___|1|___|2|___|0|___|1|___|2|_ + + -- input valid counter + if snk_in.sop = '1' then + v.val_cnt := 0; + elsif snk_in.valid = '1' then + if r.val_cnt < g_pkt_len - 1 then + v.val_cnt := r.val_cnt + 1; + else + v.val_cnt := 0; + end if; + end if; + + -- output packet counter + if snk_in.sop = '1' then + v.pkt_cnt := 0; + elsif snk_in.valid = '1' and v.val_cnt = 0 then + v.pkt_cnt := r.pkt_cnt + 1; + end if; + + -- output packet bsn, sync, sop and eop + v.src_out := snk_in; -- passes on snk_in.sync, data, re, im + v.src_out.bsn := r.src_out.bsn; + v.src_out.channel := r.src_out.channel; + v.src_out.empty := r.src_out.empty; + v.src_out.err := r.src_out.err; + v.src_out.sop := '0'; + v.src_out.eop := '0'; + + -- . output sop, eop + if snk_in.valid = '1' then + if v.val_cnt = 0 then + v.src_out.sop := '1'; + end if; + if v.val_cnt = g_pkt_len - 1 then + v.src_out.eop := '1'; + end if; + end if; + + -- . output bsn + if snk_in.sop = '1' then + v.src_out.bsn := snk_in.bsn; + elsif v.src_out.sop = '1' then + v.src_out.bsn := incr_uvec(r.src_out.bsn, g_bsn_increment); + end if; + + -- . output channel + v.src_out.channel := TO_DP_CHANNEL(v.pkt_cnt); + + -- . output err, empty. assume they are valid during entire input packet, + -- so not only at the snk_in.eop + if snk_in.valid = '1' then + v.src_out.empty := snk_in.empty; + v.src_out.err := snk_in.err; + end if; + + -- Synchronous reset + if rst = '1' then + v := c_reg_rst; + end if; + + d <= v; + end process; end rtl; diff --git a/libraries/base/dp/tb/vhdl/tb_dp_packet_merge_unmerge.vhd b/libraries/base/dp/tb/vhdl/tb_dp_packet_merge_unmerge.vhd new file mode 100644 index 0000000000..6277b534f3 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_dp_packet_merge_unmerge.vhd @@ -0,0 +1,299 @@ +-- -------------------------------------------------------------------------- +-- 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: E. Kooistra +-- Purpose: +-- . Test bench for dp_packet_merge and dp_packet_unmerge +-- Description: +-- . The p_stimuli_st uses proc_dp_gen_block_data to generate g_nof_repeat packets for the DUT. The output of the DUT needs +-- to be similar e.g. by means of an inverse DUT component so that the proc_dp_verify_* procedures can be used to verify +-- that the counter data in the sosi data fields is passed on correctly. Furthermore the proc_dp_verify_* procedures +-- verify that the test bench has yielded output results at all and that the output valid, sop, eop, and ready fits the +-- streaming interface specification. +-- Usage: +-- > as 10 +-- > 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_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_packet_merge_unmerge is + generic ( + -- general + g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control + g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control + -- specific + g_data_w : natural := 16; + g_nof_repeat : natural := 24; + g_nof_pkt : natural := 3; + g_pkt_len : natural := 10; + g_pkt_gap : natural := 0; + g_align_at_sync : boolean := false; + g_verify_bsn_err : boolean := false; + g_bsn_increment : natural := 1 + ); +end tb_dp_packet_merge_unmerge; + +architecture tb of tb_dp_packet_merge_unmerge is + constant c_rl : natural := 1; + + constant c_pulse_active : natural := 1; + constant c_pulse_period : natural := 7; + + constant c_sync_period : natural := 10; + constant c_sync_offset : natural := 7; + + constant c_data_max : unsigned(g_data_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_bsn_err_bi : natural := 31; -- use sufficiently high bsn error bit index, that is outside counter range of c_err_init + constant c_channel_init : integer := 5; -- fixed + + constant c_nof_pkt_not_zero : natural := sel_a_b(g_nof_pkt = 0, 1, g_nof_pkt); + constant c_nof_merged_sop : natural := sel_a_b(g_nof_pkt = 0, 0, ceil_div(g_nof_repeat, c_nof_pkt_not_zero)); + constant c_verify_at_least : natural := largest(1,c_nof_merged_sop / 2); -- verify that at least some packets have been merged, not exact to allow variation by p_stimuli_mm + constant c_verify_data_gap : natural := g_nof_pkt; + constant c_verify_bsn_gap : natural := g_nof_pkt * g_bsn_increment; + + signal tb_end : std_logic := '0'; + signal clk : std_logic := '1'; + signal rst : std_logic := '1'; + signal sl1 : std_logic := '1'; + + signal random_0 : std_logic_vector(14 downto 0) := (others => '0'); -- use different lengths to have different random sequences + signal random_1 : std_logic_vector(15 downto 0) := (others => '0'); -- use different lengths to have different random sequences + signal pulse_0 : std_logic; + signal pulse_1 : std_logic; + signal pulse_en : std_logic := '1'; + + signal stimuli_en : std_logic := '1'; + signal stimuli_src_in : t_dp_siso; + signal stimuli_src_out : t_dp_sosi; + signal stimuli_data : std_logic_vector(g_data_w - 1 downto 0); + + signal dp_packet_merge_snk_in : t_dp_siso; + signal dp_packet_merge_src_out : t_dp_sosi; + signal dp_packet_merge_siso : t_dp_siso; + signal dp_packet_merge_sosi : t_dp_sosi; + + signal prev_verify_snk_out : t_dp_siso; + signal verify_snk_out : t_dp_siso := c_dp_siso_rdy; + signal verify_snk_in : t_dp_sosi; + signal verify_data : std_logic_vector(g_data_w - 1 downto 0); + signal prev_verify_snk_in : t_dp_sosi; + signal merged_pkt_cnt : natural := 0; + signal exp_channel : natural := 0; + + signal verify_hold_sop : std_logic := '0'; + signal verify_en_valid : std_logic := '0'; + signal verify_en_sop : std_logic := '0'; + signal verify_en_eop : std_logic := '0'; + signal verify_done : std_logic := '0'; + signal verify_value_en : std_logic := sel_a_b(g_nof_pkt = 0, '0', '1'); + + signal expected_verify_snk_in : t_dp_sosi; +begin + clk <= (not clk) or tb_end after clk_period / 2; + rst <= '1', '0' after clk_period * 7; + + random_0 <= func_common_random(random_0) when rising_edge(clk); + random_1 <= func_common_random(random_1) when rising_edge(clk); + + proc_common_gen_duty_pulse(c_pulse_active, c_pulse_period, '1', rst, clk, pulse_en, pulse_0); + proc_common_gen_duty_pulse(c_pulse_active, c_pulse_period + 1, '1', rst, clk, pulse_en, pulse_1); + + ------------------------------------------------------------------------------ + -- STREAM CONTROL + ------------------------------------------------------------------------------ + + stimuli_en <= '1' when g_flow_control_stimuli = e_active else + random_0(random_0'high) when g_flow_control_stimuli = e_random else + pulse_0 when g_flow_control_stimuli = e_pulse; + + verify_snk_out.ready <= '1' when g_flow_control_verify = e_active else + random_1(random_1'high) when g_flow_control_verify = e_random else + pulse_1 when g_flow_control_verify = e_pulse; + + ------------------------------------------------------------------------------ + -- DATA GENERATION + ------------------------------------------------------------------------------ + + -- Generate data path input data + p_stimuli_st : process + variable v_sosi : t_dp_sosi := c_dp_sosi_rst; + variable v_bsn : std_logic_vector(c_dp_stream_bsn_w - 1 downto 0); + begin + -- Adjust initial sosi field values by -1 to compensate for auto increment + v_sosi.bsn := INCR_UVEC(c_bsn_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, g_bsn_increment); + -- insert sync starting at BSN=c_sync_offset and with period c_sync_period + v_sosi.sync := sel_a_b((unsigned(v_sosi.bsn) mod c_sync_period) = c_sync_offset, '1', '0'); + v_sosi.data := INCR_UVEC(v_sosi.data, g_pkt_len); + v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_data_w - 1 downto 0)); -- wrap when >= 2**g_data_w + + -- Send packet + proc_dp_gen_block_data(g_data_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; + + -- Determine expected sosi field values after end of stimuli + -- . e_qual (account for merge size g_nof_pkt) + -- . e_at_least + v_sosi.bsn := std_logic_vector(unsigned(c_bsn_init) + c_verify_at_least * g_nof_pkt); + + -- . account for g_pkt_len + v_sosi.data := INCR_UVEC(v_sosi.data, g_pkt_len - 1); + v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_data_w - 1 downto 0)); -- wrap when >= 2**g_data_w + expected_verify_snk_in <= v_sosi; + + -- Signal end of stimuli + -- . latency from stimuli to verify depends on the flow control, so wait + -- sufficiently long for last packet to have passed through + proc_common_wait_some_cycles(clk, 100); + if verify_value_en = '1' then + proc_common_gen_pulse(clk, verify_done); + end if; + proc_common_wait_some_cycles(clk, 50); + tb_end <= '1'; + wait; + end process; + + ------------------------------------------------------------------------------ + -- DATA VERIFICATION + ------------------------------------------------------------------------------ + + -- Start verify after first valid, sop or eop + verify_en_valid <= '1' when verify_snk_in.valid = '1' and rising_edge(clk); + verify_en_sop <= '1' when verify_snk_in.sop = '1' and rising_edge(clk); + verify_en_eop <= '1' when verify_snk_in.eop = '1' and rising_edge(clk); + + -- Verify that the stimuli have been applied at all + proc_dp_verify_value("verify_snk_in.valid", clk, verify_done, sl1, verify_en_valid); + proc_dp_verify_value("verify_snk_in.sop", clk, verify_done, sl1, verify_en_sop); + proc_dp_verify_value("verify_snk_in.eop", clk, verify_done, sl1, verify_en_eop); + proc_dp_verify_value("verify_snk_in.data", e_equal, clk, verify_done, expected_verify_snk_in.data, verify_snk_in.data); + proc_dp_verify_value("verify_snk_in.bsn", e_at_least, clk, verify_done, expected_verify_snk_in.bsn, verify_snk_in.bsn); + + -- Verify that the output is incrementing data, like the input stimuli + proc_dp_verify_data("verify_snk_in.data", c_rl, c_data_max, c_unsigned_1, + clk, verify_en_valid, verify_snk_out.ready, + verify_snk_in.valid, verify_snk_in.data, prev_verify_snk_in.data); + + proc_dp_verify_data("verify_snk_in.bsn", c_rl, c_unsigned_0, to_unsigned(c_verify_bsn_gap, 32), + clk, verify_en_sop, verify_snk_out.ready, + verify_snk_in.sop, verify_snk_in.bsn, prev_verify_snk_in.bsn); + + -- Verify output packet ctrl + proc_dp_verify_sop_and_eop(clk, verify_snk_in.valid, verify_snk_in.sop, verify_snk_in.eop, verify_hold_sop); + + -- Verify output ready latency + proc_dp_verify_valid(clk, verify_en_valid, verify_snk_out.ready, prev_verify_snk_out.ready, verify_snk_in.valid); + + -- Verify output channel + p_verify_channel : process(clk) + begin + if rising_edge(clk) then + if verify_snk_in.sop = '1' then + assert unsigned(verify_snk_in.channel) = exp_channel + report "wrong unmerged verify_snk_in.channel" + severity ERROR; + end if; + end if; + end process; + + ------------------------------------------------------------------------------ + -- DUT dp_packet_merge + ------------------------------------------------------------------------------ + + -- Merge every g_nof_pkt incomming packets into output packets + u_dp_packet_merge : entity work.dp_packet_merge + generic map ( + g_nof_pkt => g_nof_pkt, + g_align_at_sync => g_align_at_sync, + g_bsn_increment => g_bsn_increment, + g_bsn_err_bi => c_bsn_err_bi + ) + port map ( + rst => rst, + clk => clk, + + snk_out => stimuli_src_in, + snk_in => stimuli_src_out, + + src_in => dp_packet_merge_snk_in, + src_out => dp_packet_merge_src_out + ); + + merged_pkt_cnt <= merged_pkt_cnt + 1 when rising_edge(clk) and dp_packet_merge_src_out.eop = '1'; + + exp_channel <= merged_pkt_cnt mod g_nof_pkt; + + dp_packet_merge_snk_in <= dp_packet_merge_siso; + + p_stimuli_unmerge : process(dp_packet_merge_src_out) + begin + dp_packet_merge_sosi <= dp_packet_merge_src_out; + dp_packet_merge_sosi.err <= TO_DP_ERROR(merged_pkt_cnt); + end process; + + ------------------------------------------------------------------------------ + -- Optional reverse DUT dp_packet_unmerge + ------------------------------------------------------------------------------ + u_dp_packet_unmerge : entity work.dp_packet_unmerge + generic map ( + g_nof_pkt_max => g_nof_pkt, + g_pkt_len => g_pkt_len, + g_bsn_increment => g_bsn_increment + ) + port map ( + rst => rst, + clk => clk, + + snk_out => dp_packet_merge_siso, + snk_in => dp_packet_merge_sosi, + + src_in => verify_snk_out, + src_out => verify_snk_in + ); + + -- Map to slv to ease monitoring in wave window + stimuli_data <= stimuli_src_out.data(g_data_w - 1 downto 0); + verify_data <= verify_snk_in.data(g_data_w - 1 downto 0); +end tb; diff --git a/libraries/base/dp/tb/vhdl/tb_tb_dp_packet_merge_unmerge.vhd b/libraries/base/dp/tb/vhdl/tb_tb_dp_packet_merge_unmerge.vhd new file mode 100644 index 0000000000..daa8ab9db6 --- /dev/null +++ b/libraries/base/dp/tb/vhdl/tb_tb_dp_packet_merge_unmerge.vhd @@ -0,0 +1,74 @@ +-- -------------------------------------------------------------------------- +-- 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, dp_lib; +use IEEE.std_logic_1164.all; +use dp_lib.tb_dp_pkg.all; + +-- Author: E. Kooistra +-- Purpose: Verify multiple variations of tb_dp_packet_merge_unmerge +-- Description: +-- Usage: +-- > as 3 +-- > run -all + +entity tb_tb_dp_packet_merge_unmerge is +end tb_tb_dp_packet_merge_unmerge; + +architecture tb of tb_tb_dp_packet_merge_unmerge is + constant c_nof_repeat : natural := 100; + signal tb_end : std_logic := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' +begin + -- -- general + -- g_flow_control_stimuli : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control + -- g_flow_control_verify : t_dp_flow_control_enum := e_active; -- always active, random or pulse flow control + -- -- specific + -- g_data_w : natural := 4; + -- g_nof_repeat : natural := 20; + -- g_nof_pkt : natural := 3; + -- g_pkt_len : natural := 29; + -- g_pkt_gap : natural := 0; + -- g_align_at_sync : boolean := false; + -- g_verify_bsn_err : boolean := false; + -- g_bsn_increment : natural := 0; + + u_act_act_8_nof_0 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 0, 29, 0, false, false, 1); + u_act_act_8_nof_1 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 1, 29, 0, false, false, 1); + u_act_act_8_nof_2 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 2, 29, 0, false, false, 1); + u_act_act_8_nof_3 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 3, 29, 0, false, false, 1); + u_act_act_8_nof_4 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 4, 29, 0, false, false, 1); + u_act_act_8_nof_5 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 5, 29, 0, false, false, 1); + u_act_act_8_nof_6 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 6, 29, 0, false, false, 1); + u_act_act_8_nof_7 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 7, 29, 0, false, false, 1); + + u_rnd_act_8_nof_3 : entity work.tb_dp_packet_merge_unmerge generic map ( e_random, e_active, 8, c_nof_repeat, 3, 29, 0, false, false, 2); + u_rnd_rnd_8_nof_3 : entity work.tb_dp_packet_merge_unmerge generic map ( e_random, e_random, 8, c_nof_repeat, 3, 29, 0, false, false, 3); + u_pls_act_8_nof_3 : entity work.tb_dp_packet_merge_unmerge generic map ( e_pulse, e_active, 8, c_nof_repeat, 3, 29, 0, false, false, 4); + u_pls_rnd_8_nof_3 : entity work.tb_dp_packet_merge_unmerge generic map ( e_pulse, e_random, 8, c_nof_repeat, 3, 29, 0, false, false, 5); + u_pls_pls_8_nof_3 : entity work.tb_dp_packet_merge_unmerge generic map ( e_pulse, e_pulse, 8, c_nof_repeat, 3, 29, 0, false, false, 6); + + u_rnd_act_8_nof_1 : entity work.tb_dp_packet_merge_unmerge generic map ( e_random, e_active, 8, c_nof_repeat, 1, 29, 0, false, false, 1); + u_rnd_act_8_nof_3_gap : entity work.tb_dp_packet_merge_unmerge generic map ( e_random, e_active, 8, c_nof_repeat, 3, 29, 17, false, false, 1); + + u_act_act_8_nof_3_no_err : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 3, 29, 0, false, true, 0); + u_act_act_8_nof_3_err_10 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 3, 29, 0, false, true, 1); + u_act_act_8_nof_3_err_11 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 3, 29, 0, false, true, 1); + u_act_act_8_nof_3_err_12 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 3, 29, 0, false, true, 1); + u_act_act_8_nof_3_err_13 : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active, 8, c_nof_repeat, 3, 29, 0, false, true, 1); +end tb; -- GitLab