From 19c982f3d9a1eb56a392715da22777a1c8391448 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Thu, 21 Sep 2023 10:48:36 +0200
Subject: [PATCH] Verify g_pkt_len_merge /= g_pkt_len_unmerge.

---
 .../dp/tb/vhdl/tb_dp_packet_merge_unmerge.vhd | 60 +++++++++++++------
 .../tb/vhdl/tb_tb_dp_packet_merge_unmerge.vhd | 12 ++++
 2 files changed, 54 insertions(+), 18 deletions(-)

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
index 3d62c5a15a..e1038d56ab 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_packet_merge_unmerge.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_packet_merge_unmerge.vhd
@@ -23,22 +23,31 @@
 -- Description:
 -- . The p_stimuli_st uses proc_dp_gen_block_data to generate g_nof_repeat
 --   stimuli_src_out packets of length g_pkt_len_merge.
---   The u_dp_packet_merge merges g_nof_pkt packets from stimuli_src_out into
+-- . The u_dp_packet_merge merges g_nof_pkt packets from stimuli_src_out into
 --   dp_packet_merge_src_out.
---   The p_stimuli_unmerge provides stimuli for the .err and .empty fields of
+-- . The p_stimuli_unmerge provides stimuli for the .err and .empty fields of
 --   dp_packet_merge_src_out to get dp_packet_merge_sosi
---   The u_dp_packet_unmerge unmerges the dp_packet_merge_sosi into packets
---   of length g_pkt_len_unmerge into verify_snk_in.
---   If g_pkt_len_unmerge /= g_pkt_len_merge, then the last unmerged packet
---   may be shorter then g_pkt_len_unmerge, to contain the remaining data.
+-- . The u_dp_packet_unmerge unmerges the dp_packet_merge_sosi into packets
+--   of length g_pkt_len_unmerge into verify_snk_in. If g_pkt_len_unmerge /=
+--   g_pkt_len_merge, then:
+--   - the last unmerged packet may be shorter then g_pkt_len_unmerge, to
+--     contain the remaining data.
+--   - the number of unmerged packets c_nof_pkt_unmerge, may differ from
+--     g_nof_pkt.
+--   - use c_bsn_increment_unmerge = 0 for u_dp_packet_unmerge and expect BSN
+--     increment of 0 for unmerged packets from same merged packet or
+--     c_nof_pkt_unmerge for unmerged packets from subsequent merged packets.
+--     Verify this only manually in wave window, because verifying different
+--     increments is not supported by proc_dp_verify_data().
+-- . The p_verify section does the verification of verify_snk_in.
+-- . Flow control is verified via g_flow_control_*.
+-- . Block diagram:
 --
 --   p_stimuli_st --> u_dp_packet_merge --+--> u_dp_packet_unmerge --> p_verify
 --                                        ^
 --                                        |
 --                    p_stimuli_unmerge --/
 --
--- . Flow control is verified via g_flow_control_*.
---
 -- Usage:
 -- > as 10
 -- > run -all
@@ -64,10 +73,10 @@ entity tb_dp_packet_merge_unmerge is
     g_data_w                 : natural := 16;
     g_nof_repeat             : natural := 14;
     g_nof_pkt                : natural := 3;
-    g_pkt_len_merge          : natural := 9;
-    g_pkt_len_unmerge        : natural := 9;
+    g_pkt_len_merge          : natural := 7;
+    g_pkt_len_unmerge        : natural := 6;
     g_pkt_gap                : natural := 0;
-    g_bsn_increment          : natural := 2
+    g_bsn_increment          : natural := 1
   );
 end tb_dp_packet_merge_unmerge;
 
@@ -87,6 +96,9 @@ architecture tb of tb_dp_packet_merge_unmerge is
   constant c_bsn_increment_w          : natural := ceil_log2(g_bsn_increment + 1);
   constant c_unsigned_bsn_increment   : unsigned(c_bsn_increment_w - 1 downto 0) := to_unsigned(g_bsn_increment, c_bsn_increment_w);
 
+  constant c_nof_pkt_unmerge          : natural := ceil_div(g_nof_pkt * g_pkt_len_merge, g_pkt_len_unmerge);
+  constant c_bsn_increment_unmerge    : natural := sel_a_b(g_nof_pkt = c_nof_pkt_unmerge, g_bsn_increment, 0);
+
   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));
   -- verify that at least some packets have been merged, not exact to allow variation by p_stimuli_mm
@@ -122,6 +134,7 @@ architecture tb of tb_dp_packet_merge_unmerge is
 
   signal input_pkt_cnt              : natural := 0;
   signal merged_pkt_cnt             : natural := 0;
+  signal output_pkt_cnt             : natural := 0;
   signal exp_channel                : natural := 0;
   signal exp_error                  : natural := 0;
   signal exp_empty                  : natural := 0;
@@ -238,9 +251,11 @@ begin
                       verify_snk_in.valid, verify_snk_in.data, prev_verify_snk_in.data);
 
   -- Verify that the output is incrementing BSN, like the input stimuli
-  proc_dp_verify_data("verify_snk_in.bsn", c_rl, c_unsigned_0, c_unsigned_bsn_increment,
-                       clk, verify_en_sop, verify_snk_out.ready,
-                       verify_snk_in.sop, verify_snk_in.bsn, prev_verify_snk_in.bsn);
+  gen_verify_bsn : if g_nof_pkt = c_nof_pkt_unmerge generate
+    proc_dp_verify_data("verify_snk_in.bsn", c_rl, c_unsigned_0, c_unsigned_bsn_increment,
+                         clk, verify_en_sop, verify_snk_out.ready,
+                         verify_snk_in.sop, verify_snk_in.bsn, prev_verify_snk_in.bsn);
+  end generate;
 
   -- 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);
@@ -256,7 +271,7 @@ begin
       -- is that the channel (at sop) and err, empty (at eop) are valid during
       -- the entire unmerged packet.
       if verify_snk_in.valid = '1' then
-        -- Verify that output channel yields index of unmerged packet, in range(g_nof_pkt)
+        -- Verify that output channel yields index of unmerged packet, in range(c_nof_pkt_unmerge)
         assert unsigned(verify_snk_in.channel) = exp_channel
           report "Wrong unmerged verify_snk_in.channel"
           severity ERROR;
@@ -316,9 +331,18 @@ begin
   ------------------------------------------------------------------------------
   input_pkt_cnt <= input_pkt_cnt + 1 when rising_edge(clk) and stimuli_src_out.eop = '1';
   merged_pkt_cnt <= merged_pkt_cnt + 1 when rising_edge(clk) and dp_packet_merge_src_out.eop = '1';
+  output_pkt_cnt <= output_pkt_cnt + 1 when rising_edge(clk) and verify_snk_in.eop = '1';
 
   -- get expected value, aligned with output packet boundaries
-  exp_channel <= input_pkt_cnt mod g_nof_pkt when rising_edge(clk) and verify_snk_in.eop = '1';
+  p_exp_channel : process(output_pkt_cnt)
+  begin
+    -- Avoid divide by 0
+    exp_channel <= 0;
+    if c_nof_pkt_unmerge > 0 then
+      exp_channel <= output_pkt_cnt mod c_nof_pkt_unmerge;
+    end if;
+  end process;
+
   exp_error <= merged_pkt_cnt when rising_edge(clk) and verify_snk_in.eop = '1';
   exp_empty <= exp_error + 1;
 
@@ -329,9 +353,9 @@ begin
   generic map (
     g_use_ready       => c_use_ready,
     g_pipeline_ready  => g_pipeline_ready,
-    g_nof_pkt         => g_nof_pkt,
+    g_nof_pkt         => c_nof_pkt_unmerge,
     g_pkt_len         => g_pkt_len_unmerge,
-    g_bsn_increment   => g_bsn_increment
+    g_bsn_increment   => c_bsn_increment_unmerge
   )
   port map (
     rst       => rst,
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
index c13ca82c8e..aa5fc9fa20 100644
--- 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
@@ -48,6 +48,7 @@ begin
   --     g_pkt_gap                : natural := 0;
   --     g_bsn_increment          : natural := 0;
 
+  -- No flow control
   u_act_act_8_nof_0       : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active,  true, 8, c_nof_repeat, 0, 29, 29, 0, 1);
   u_act_act_8_nof_1       : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active,  true, 8, c_nof_repeat, 1, 29, 29, 0, 1);
   u_act_act_8_nof_2       : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active,  true, 8, c_nof_repeat, 2, 29, 29, 0, 1);
@@ -59,6 +60,17 @@ begin
   u_act_act_8_nof_6       : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active,  true, 8, c_nof_repeat, 6, 29, 29, 0, 1);
   u_act_act_8_nof_7       : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active,  true, 8, c_nof_repeat, 7, 29, 29, 0, 1);
 
+  -- Fractional unmerge
+  -- . u_act_act_8_nof_3_more_unmerge  : ceil((3 * 7) / 6) = 4 and (3 * 7) mod 6 = 3, so there are 4 unmerged packets and last has length 3
+  -- . u_act_act_8_nof_3_last_len_1    : (3 * 7) mod 10 = 1, so last unmerged packet has length 1
+  -- . u_act_act_8_nof_3_only_one      : (3 * 7) / 21 = 1, so there is only one unmerged packet with length 21
+  -- . u_act_act_8_nof_3_only_one_frac : (3 * 7) / 22 = 0 and (3 * 7) mod 22 = 21, so there is only one unmerged packet with length 21
+  u_act_act_8_nof_3_more_unmerge  : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active,  true, 8, c_nof_repeat, 3, 7,  6, 0, 1);
+  u_act_act_8_nof_3_last_len_1    : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active,  true, 8, c_nof_repeat, 3, 7, 10, 0, 1);
+  u_act_act_8_nof_3_only_one      : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active,  true, 8, c_nof_repeat, 3, 7, 21, 0, 1);
+  u_act_act_8_nof_3_only_one_frac : entity work.tb_dp_packet_merge_unmerge generic map ( e_active, e_active,  true, 8, c_nof_repeat, 3, 7, 21, 0, 1);
+
+  -- Flow control
   u_rnd_act_8_nof_3       : entity work.tb_dp_packet_merge_unmerge generic map ( e_random, e_active,  true, 8, c_nof_repeat, 3, 29, 29, 0, 1);
   u_rnd_rnd_8_nof_3_comb  : entity work.tb_dp_packet_merge_unmerge generic map ( e_random, e_random, false, 8, c_nof_repeat, 3, 29, 29, 0, 1);
   u_rnd_rnd_8_nof_3_reg   : entity work.tb_dp_packet_merge_unmerge generic map ( e_random, e_random,  true, 8, c_nof_repeat, 3, 29, 29, 0, 1);
-- 
GitLab