Skip to content
Snippets Groups Projects
Commit 689a41b4 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Add dp_packet_unmerge.vhd with tb and tb_tb.

parent d5eb1015
No related branches found
No related tags found
1 merge request!353Resolve L2SDP-962
Pipeline #57252 passed with warnings
hdl_lib_name = dp hdl_lib_name = dp
hdl_library_clause_name = dp_lib hdl_library_clause_name = dp_lib
hdl_lib_uses_synth = mm common common_mult easics hdl_lib_uses_synth = mm common common_mult easics
hdl_lib_uses_sim = hdl_lib_uses_sim =
hdl_lib_technology = hdl_lib_technology =
synth_files = synth_files =
src/vhdl/dp_stream_pkg.vhd src/vhdl/dp_stream_pkg.vhd
...@@ -10,7 +10,7 @@ synth_files = ...@@ -10,7 +10,7 @@ synth_files =
src/vhdl/dp_example_dut.vhd src/vhdl/dp_example_dut.vhd
src/vhdl/dp_packetizing_pkg.vhd src/vhdl/dp_packetizing_pkg.vhd
src/vhdl/dp_packet_pkg.vhd src/vhdl/dp_packet_pkg.vhd
src/vhdl/dp_eop_extend.vhd src/vhdl/dp_eop_extend.vhd
src/vhdl/dp_validate.vhd src/vhdl/dp_validate.vhd
src/vhdl/dp_ready.vhd src/vhdl/dp_ready.vhd
...@@ -147,7 +147,7 @@ synth_files = ...@@ -147,7 +147,7 @@ synth_files =
src/vhdl/dp_packet_unmerge.vhd src/vhdl/dp_packet_unmerge.vhd
src/vhdl/dp_offload_tx_legacy.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.vhd
src/vhdl/dp_sync_insert_v2.vhd src/vhdl/dp_sync_insert_v2.vhd
src/vhdl/dp_sync_recover.vhd src/vhdl/dp_sync_recover.vhd
...@@ -192,20 +192,20 @@ synth_files = ...@@ -192,20 +192,20 @@ synth_files =
src/vhdl/dp_selector_arr.vhd src/vhdl/dp_selector_arr.vhd
src/vhdl/dp_selector.vhd src/vhdl/dp_selector.vhd
src/vhdl/mms_dp_scale.vhd src/vhdl/mms_dp_scale.vhd
tb/vhdl/dp_stream_player.vhd tb/vhdl/dp_stream_player.vhd
tb/vhdl/dp_sosi_recorder.vhd tb/vhdl/dp_sosi_recorder.vhd
tb/vhdl/dp_stream_rec_play.vhd tb/vhdl/dp_stream_rec_play.vhd
tb/vhdl/dp_statistics.vhd tb/vhdl/dp_statistics.vhd
tb/vhdl/tb_dp_pkg.vhd tb/vhdl/tb_dp_pkg.vhd
test_bench_files = test_bench_files =
tb/vhdl/dp_phy_link.vhd tb/vhdl/dp_phy_link.vhd
tb/vhdl/dp_stream_stimuli.vhd tb/vhdl/dp_stream_stimuli.vhd
tb/vhdl/dp_stream_verify.vhd tb/vhdl/dp_stream_verify.vhd
tb/vhdl/tb_dp_strobe_total_count.vhd tb/vhdl/tb_dp_strobe_total_count.vhd
tb/vhdl/tb_dp_block_select.vhd tb/vhdl/tb_dp_block_select.vhd
tb/vhdl/tb_dp_block_validate_length.vhd tb/vhdl/tb_dp_block_validate_length.vhd
...@@ -266,6 +266,7 @@ test_bench_files = ...@@ -266,6 +266,7 @@ test_bench_files =
tb/vhdl/tb_dp_concat_field_blk.vhd tb/vhdl/tb_dp_concat_field_blk.vhd
tb/vhdl/tb_dp_packet.vhd tb/vhdl/tb_dp_packet.vhd
tb/vhdl/tb_dp_packet_merge.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_packetizing.vhd
tb/vhdl/tb_dp_pad_insert_remove.vhd tb/vhdl/tb_dp_pad_insert_remove.vhd
tb/vhdl/tb_dp_pipeline.vhd tb/vhdl/tb_dp_pipeline.vhd
...@@ -344,6 +345,7 @@ test_bench_files = ...@@ -344,6 +345,7 @@ test_bench_files =
tb/vhdl/tb_tb_dp_packetizing.vhd tb/vhdl/tb_tb_dp_packetizing.vhd
tb/vhdl/tb_tb_dp_packet.vhd tb/vhdl/tb_tb_dp_packet.vhd
tb/vhdl/tb_tb_dp_packet_merge.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_concat_field_blk.vhd
tb/vhdl/tb_tb_dp_pipeline.vhd tb/vhdl/tb_tb_dp_pipeline.vhd
tb/vhdl/tb_tb_dp_pipeline_ready.vhd tb/vhdl/tb_tb_dp_pipeline_ready.vhd
...@@ -360,7 +362,7 @@ test_bench_files = ...@@ -360,7 +362,7 @@ test_bench_files =
tb/vhdl/tb_tb_dp_throttle_xon.vhd tb/vhdl/tb_tb_dp_throttle_xon.vhd
tb/vhdl/tb_tb_dp_counter.vhd tb/vhdl/tb_tb_dp_counter.vhd
tb/vhdl/tb_tb_dp_xonoff.vhd tb/vhdl/tb_tb_dp_xonoff.vhd
tb/vhdl/tb_tb_tb_dp_backpressure.vhd tb/vhdl/tb_tb_tb_dp_backpressure.vhd
tb/vhdl/tb_dp_offload_tx_v3.vhd tb/vhdl/tb_dp_offload_tx_v3.vhd
tb/vhdl/tb_tb_dp_offload_tx_v3.vhd tb/vhdl/tb_tb_dp_offload_tx_v3.vhd
...@@ -368,7 +370,7 @@ test_bench_files = ...@@ -368,7 +370,7 @@ test_bench_files =
tb/vhdl/tb_dp_selector_arr.vhd tb/vhdl/tb_dp_selector_arr.vhd
tb/vhdl/tb_mms_dp_scale.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_to_mm.vhd
tb/vhdl/tb_dp_fifo_xonoff.vhd tb/vhdl/tb_dp_fifo_xonoff.vhd
tb/vhdl/tb_dp_latency_adapter.vhd tb/vhdl/tb_dp_latency_adapter.vhd
...@@ -403,8 +405,8 @@ regression_test_vhdl = ...@@ -403,8 +405,8 @@ regression_test_vhdl =
tb/vhdl/tb_tb_dp_reverse_n_data.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_reverse_n_data_fc.vhd
tb/vhdl/tb_tb_dp_example_dut.vhd tb/vhdl/tb_tb_dp_example_dut.vhd
tb/vhdl/tb_tb_dp_fifo_dc.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_mixed_widths.vhd
tb/vhdl/tb_tb_dp_fifo_fill.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_sc.vhd
tb/vhdl/tb_tb_dp_fifo_fill_eop.vhd tb/vhdl/tb_tb_dp_fifo_fill_eop.vhd
...@@ -417,6 +419,7 @@ regression_test_vhdl = ...@@ -417,6 +419,7 @@ regression_test_vhdl =
tb/vhdl/tb_tb3_dp_mux.vhd tb/vhdl/tb_tb3_dp_mux.vhd
tb/vhdl/tb_tb_dp_packet.vhd tb/vhdl/tb_tb_dp_packet.vhd
tb/vhdl/tb_tb_dp_packet_merge.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_concat_field_blk.vhd
tb/vhdl/tb_tb_dp_pad_insert_remove.vhd tb/vhdl/tb_tb_dp_pad_insert_remove.vhd
tb/vhdl/tb_tb_dp_pipeline.vhd tb/vhdl/tb_tb_dp_pipeline.vhd
......
...@@ -19,13 +19,31 @@ ...@@ -19,13 +19,31 @@
-- --
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
-- Purpose: Unmerge each input packet into g_nof_pkt output packets. Below is the -- Purpose: Unmerge each input packet into output packets of length g_pkt_len.
-- waveform when g_nof_pkt = 3. The numbers in snk_in.sop and snk_in.eop -- Description:
-- match pkt_cnt. -- . 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|_ -- src_out.sop _____|0|_______|1|_______|2|_______|0|_______|1|_______|2|_______|0|_
-- _ _ _ _ _ _ -- _ _ _ _ _ _
...@@ -39,8 +57,9 @@ use work.dp_stream_pkg.all; ...@@ -39,8 +57,9 @@ use work.dp_stream_pkg.all;
entity dp_packet_unmerge is entity dp_packet_unmerge is
generic ( generic (
g_nof_pkt : natural := 1; -- Nof packets to unmerge each incoming packet to 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_pkt_len : natural := 1; -- Length of the unmerged packets
g_bsn_increment : natural := 0
); );
port ( port (
rst : in std_logic; rst : in std_logic;
...@@ -55,8 +74,106 @@ entity dp_packet_unmerge is ...@@ -55,8 +74,106 @@ entity dp_packet_unmerge is
end dp_packet_unmerge; end dp_packet_unmerge;
architecture rtl of dp_packet_unmerge is 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 begin
-- Temporary void component that assigns output = input -- Map t_reg outputs to entity outputs
snk_out <= src_in; 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; end rtl;
-- --------------------------------------------------------------------------
-- 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;
-- --------------------------------------------------------------------------
-- 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;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment