From ba11989df668b934ffcef99a4184940cbeca18a0 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Tue, 15 Aug 2023 15:17:31 +0200
Subject: [PATCH] Verify dynamic reorder control. Verify g_inter_valid_gap.

---
 .../tb/vhdl/tb_reorder_col_select_all.vhd     | 258 ++++++++++++++----
 .../tb/vhdl/tb_tb_reorder_col_select_all.vhd  |  24 +-
 2 files changed, 222 insertions(+), 60 deletions(-)

diff --git a/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd b/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd
index 8701d6a9ca..8b4640ebd3 100644
--- a/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd
+++ b/libraries/base/reorder/tb/vhdl/tb_reorder_col_select_all.vhd
@@ -21,13 +21,25 @@
 -------------------------------------------------------------------------------
 -- Author : E. Kooistra
 -- Purpose:
---   Verify reorder_col_select using two instances and selects all inputdata.
+--   Verify reorder_col_select using two instances and select all input data,
+--   so that second instance can restore the original input data order.
 -- Description:
 --   The second reorder_col_select instances undo's the reordering of the
 --   first reorder_col_select instance. All data in the input block is used,
 --   so that the output of the second reorder_col_select instance is equal
---   to the tb input data, except for a delay, so that the output data can
---   easily be verified.
+--   to the tb input data, except for a delay and data valid gaps.
+--   The data and info fields are incrementing, so that the out_sosi can be
+--   verified with dp_stream_verify.
+--
+--               p_comb_transpose     p_comb_undo_transpose
+--                        |                   |
+--                    ____v_____          ____v_____
+--                   |reorder   |        |reorder   |
+--   p_st_stimuli -->|col_select|------->|col_select|--> p_verify
+--                   |__________|        |__________|
+--      in_sosi             transposed_sosi         out_sosi
+--      nof_ch_input        nof_ch_transposed       nof_ch_output
+--
 -- Remark:
 -- * Development order from basic functionality to all verifying features:
 --   . verify reorder 1 packet
@@ -38,12 +50,16 @@
 --     designs.
 --   . verify reorder multiple packets with and without interpacket gaps
 --   . verify g_use_complex
---   . verify all sosi fields using proc_dp_verify_sosi_equal()
+--   . verify all sosi fields using dp_stream_verify. Cannot use delayed
+--     in_sosi and proc_dp_verify_sosi_equal(), because the out_sosi does
+--     not have data valid gaps within a packet.
 --   . add tb_tb_reorder_col_select_all
---   . verify dynamic change of nof_blocks_per_packet, nof_data_per_block
+--   . verify dynamic change of nof_blocks_per_packet, nof_data_per_block.
+--   . only support changing the nof_ch_in and nof_ch_sel when the no
+--     reordering is busy.
 --
 -- Usage:
--- > as 10
+-- > as 8
 -- > run -all
 -- * The tb is self stopping and self checking, tb_end will stop the simulation
 --   by stopping the clk and thus all toggling.
@@ -61,12 +77,14 @@ use work.reorder_pkg.all;
 entity tb_reorder_col_select_all is
   generic(
     g_dsp_data_w            : natural := 16;  -- complex data width, = c_data_w / 2
-    g_nof_sync              : natural := 1;
+    g_nof_sync              : natural := 5;
     g_nof_packets_per_sync  : natural := 3;
     g_nof_blocks_per_packet : natural := 5;
     g_nof_data_per_block    : natural := 3;
-    g_inter_packet_gap      : natural := 0;
-    g_use_complex           : boolean := false
+    g_inter_valid_gap       : natural := 0;  -- nof clk gap in in_sosi.valid
+    g_inter_packet_gap      : natural := 3;  -- nof clk gap betweek in_sosi.eop and next in_sosi.sop
+    g_use_complex           : boolean := false;
+    g_use_dynamic_selection : boolean := false
   );
 end tb_reorder_col_select_all;
 
@@ -76,33 +94,53 @@ architecture tb of tb_reorder_col_select_all is
   constant c_clk_period   : time := 10 ns;
   constant c_rl           : natural := 1;
 
-  constant c_use_data       : boolean := not g_use_complex;
-  constant c_data_w         : natural := c_nof_complex * g_dsp_data_w;
-  constant c_nof_ch         : natural := g_nof_blocks_per_packet * g_nof_data_per_block;
+  constant c_use_data     : boolean := not g_use_complex;
+  constant c_data_w       : natural := c_nof_complex * g_dsp_data_w;
 
-  constant c_nof_blocks_max : natural:= largest(g_nof_blocks_per_packet, g_nof_data_per_block) + 1;
-  constant c_addr_max       : natural := c_nof_ch + c_nof_blocks_max;
-  constant c_cnt_max        : natural := c_nof_blocks_max;
+  -- Match c_nof_sync with p_nof_ch_stimuli
+  constant c_nof_sync     : natural := sel_a_b(g_use_dynamic_selection, 2, g_nof_sync);
+  constant c_factor_blk   : natural := sel_a_b(g_use_dynamic_selection, 2, 1);  -- factor for more blocks per packet
+  constant c_factor_dat   : natural := sel_a_b(g_use_dynamic_selection, 1, 1);  -- factor for more data per block
+  constant c_factor_ch    : natural := c_factor_blk * c_factor_dat;  -- factor for more data per packet
+  constant c_nof_ch       : natural := g_nof_blocks_per_packet * g_nof_data_per_block;
+  constant c_nof_ch_long  : natural := c_nof_ch * c_factor_ch;
+  constant c_sel_gap      : natural := c_nof_ch_long * 2;
 
   -- Total output latency for transpose and undo transpose
-  constant c_retrieve_lat   : natural := 2;  -- rd latency of reorder_col_select
-  constant c_output_lat     : natural := (c_nof_ch + c_retrieve_lat) * 2;
+  constant c_retrieve_lat    : natural := 2;  -- rd latency of reorder_col_select
+  constant c_output_lat      : natural := (c_nof_ch + c_retrieve_lat) * 2;
+  constant c_output_lat_long : natural := (c_nof_ch_long + c_retrieve_lat) * 2;
 
   signal rst              : std_logic;
   signal clk              : std_logic := '1';
   signal tb_end           : std_logic := '0';
 
+  signal verify_en_sosi          : t_dp_sosi_sl;
+  signal verify_en_out_sosi      : t_dp_sosi_sl;
+  signal verify_en_out_sosi_long : t_dp_sosi_sl;
+
   -- Data
   signal in_en            : std_logic := '1';
   signal in_sosi          : t_dp_sosi := c_dp_sosi_rst;
   signal in_siso          : t_dp_siso := c_dp_siso_rdy;  -- used for proc_dp_gen_block_data
   signal transposed_sosi  : t_dp_sosi;
   signal out_sosi         : t_dp_sosi;
-  signal in_sosi_dly      : t_dp_sosi := c_dp_sosi_rst;
-  signal expected_sosi    : t_dp_sosi := c_dp_sosi_rst;
 
-  -- Reorder and undo reorder control
-  signal nof_ch           : natural range 0 to c_nof_ch := c_nof_ch;
+  -- Reorder control for transpose and undo transpose
+  signal sel_long                         : boolean := false;
+  signal reorder_busy_transposed          : std_logic;
+  signal reorder_busy_output              : std_logic;
+  signal reorder_busy                     : std_logic;
+  signal nof_ch_input                     : natural := c_nof_ch;
+  signal nof_ch_transposed                : natural;
+  signal nof_ch_output                    : natural;
+  signal nof_blocks_per_packet_input      : natural := g_nof_blocks_per_packet;
+  signal nof_blocks_per_packet_transposed : natural;
+  signal nof_blocks_per_packet_output     : natural;
+  signal nof_data_per_block_input         : natural := g_nof_data_per_block;
+  signal nof_data_per_block_transposed    : natural;
+  signal nof_data_per_block_output        : natural;
+
   signal select_cipo      : t_mem_cipo;
   signal undo_select_cipo : t_mem_cipo;
   signal r_transpose      : t_reorder_transpose;
@@ -115,11 +153,20 @@ begin
   clk <= (not clk) or tb_end after c_clk_period / 2;
   rst <= '1', '0' after c_clk_period * 7;
 
+  -- Pulse in_en to control in_sosi.valid
+  proc_common_gen_pulse(1, 1 + g_inter_valid_gap, '1', rst, clk, in_en);
+
+  -- Dynamic reorder control
+  nof_ch_input <= sel_a_b(sel_long, c_nof_ch_long, c_nof_ch);
+
   -- Input data packets stimuli
   p_st_stimuli : process
-    variable v_bsn  : std_logic_vector(31 downto 0) := (others => '0');
-    variable v_data : natural := 0;
+    variable v_nof_ch : natural := c_nof_ch;
+    variable v_bsn    : std_logic_vector(31 downto 0) := (others => '0');
+    variable v_info   : natural := 0;
+    variable v_data   : natural := 0;
   begin
+    sel_long <= false;
     proc_common_wait_until_low(clk, rst);
     proc_common_wait_some_cycles(clk, 5);
 
@@ -141,8 +188,9 @@ begin
     --   signal   in_en            : in  std_logic;  -- when '0' then no valid output even when src_in is ready
     --   signal   src_in           : in  t_dp_siso;
     --   signal   src_out          : out t_dp_sosi);
-    for I in 0 to g_nof_sync - 1 loop
+    for I in 0 to c_nof_sync - 1 loop
       -- First packet in sync interval
+      v_nof_ch := nof_ch_input;
       proc_dp_gen_block_data(c_rl,
                              c_use_data,
                              g_dsp_data_w,
@@ -150,9 +198,9 @@ begin
                              v_data,      -- data
                              v_data,      -- re
                              v_data + 1,  -- im
-                             c_nof_ch,
-                             v_data + 2,  -- channel
-                             v_data + 3,  -- error
+                             v_nof_ch,
+                             v_info + 2,  -- channel
+                             v_info + 3,  -- error
                              '1',  -- with sync
                              v_bsn,  -- bsn
                              clk,
@@ -162,8 +210,10 @@ begin
       proc_common_wait_some_cycles(clk, g_inter_packet_gap);
       for J in 0 to g_nof_packets_per_sync - 2 loop
         -- Next packets in sync interval
+        v_nof_ch := nof_ch_input;
         v_bsn := INCR_UVEC(v_bsn, 1);
-        v_data := v_data + c_nof_ch;
+        v_info := v_info + 1;
+        v_data := v_data + v_nof_ch;
         proc_dp_gen_block_data(c_rl,
                                c_use_data,
                                g_dsp_data_w,
@@ -171,9 +221,9 @@ begin
                                v_data,      -- data
                                v_data,      -- re
                                v_data + 1,  -- im
-                               c_nof_ch,
-                               v_data + 2,  -- channel
-                               v_data + 3,  -- error
+                               v_nof_ch,
+                               v_info + 2,  -- channel
+                               v_info + 3,  -- error
                                '0',  -- no sync
                                v_bsn,  -- bsn
                                clk,
@@ -182,9 +232,19 @@ begin
                                in_sosi);
         proc_common_wait_some_cycles(clk, g_inter_packet_gap);
       end loop;
+      v_bsn := INCR_UVEC(v_bsn, 1);
+      v_info := v_info + 1;
+      v_data := v_data + v_nof_ch;
+
+      if g_use_dynamic_selection then
+        -- Toggle dynamic reorder control
+        proc_common_wait_until_low(clk, reorder_busy);
+        sel_long <= not sel_long;
+        proc_common_wait_some_cycles(clk, 1);
+      end if;
     end loop;
     in_sosi <= c_dp_sosi_rst;
-    proc_common_wait_some_cycles(clk, c_nof_ch * 2);
+    proc_common_wait_some_cycles(clk, c_nof_ch_long * 2);
     proc_common_wait_some_cycles(clk, 10);
     tb_end <= '1';
     wait;
@@ -194,31 +254,104 @@ begin
   -- Verification
   ------------------------------------------------------------------------------
 
-  in_sosi_dly <= transport in_sosi after c_output_lat * c_clk_period;
-  expected_sosi <= in_sosi_dly when rising_edge(clk);
-
-  p_verify : process(rst, clk)
+  p_verify_en_sosi : process
   begin
-    if rst = '1' then
-    elsif rising_edge(clk) then
-      proc_dp_verify_sosi_equal(g_use_complex, out_sosi, expected_sosi);
+    verify_en_sosi <= c_dp_sosi_sl_rst;
+    proc_common_wait_until_low(clk, rst);
+
+    -- Verify all sosi fields, except for some
+    verify_en_sosi <= c_dp_sosi_sl_ones;
+    if g_use_complex then
+      verify_en_sosi.data <= '0';
+    else
+      verify_en_sosi.re <= '0';
+      verify_en_sosi.im <= '0';
     end if;
+    verify_en_sosi.empty <= '0';
+    wait;
   end process;
 
+  verify_en_out_sosi      <= verify_en_sosi when sel_long = false else c_dp_sosi_sl_rst;
+  verify_en_out_sosi_long <= verify_en_sosi when sel_long = true  else c_dp_sosi_sl_rst;
+
+  u_verify_out_sosi : entity dp_lib.dp_stream_verify
+  generic map (
+    -- initializations
+    g_sync_period     => g_nof_packets_per_sync,  -- BSN increment per sync interval
+    g_sync_offset     => 0,  -- first BSN
+    -- specific
+    g_in_dat_w        => c_data_w,
+    g_pkt_len         => c_nof_ch
+  )
+  port map (
+    rst                        => rst,
+    clk                        => clk,
+    -- Verify data
+    snk_in                     => out_sosi,
+    -- During stimuli
+    verify_snk_in_enable       => verify_en_out_sosi,
+
+    -- End of stimuli
+    expected_snk_in            => c_dp_sosi_rst,
+    verify_expected_snk_in_evt => c_dp_sosi_sl_rst
+  );
+
+  -- When g_use_dynamic_selection = true then c_nof_sync = 2 and second sync interval
+  -- will contain the long packets. All sync intervals have g_nof_packets_per_sync.
+  -- The first sync interval will start with BSN = g_sync_offset = 0, so the second
+  -- sync interval with the long packets, will start with BSN = g_sync_offset =
+  -- g_nof_packets_per_sync.
+  u_verify_out_sosi_long : entity dp_lib.dp_stream_verify
+  generic map (
+    -- initializations
+    g_sync_period     => g_nof_packets_per_sync,
+    g_sync_offset     => g_nof_packets_per_sync,
+    -- specific
+    g_in_dat_w        => c_data_w,
+    g_pkt_len         => c_nof_ch_long
+  )
+  port map (
+    rst                        => rst,
+    clk                        => clk,
+    -- Verify data
+    snk_in                     => out_sosi,
+    -- During stimuli
+    verify_snk_in_enable       => verify_en_out_sosi_long,
+
+    -- End of stimuli
+    expected_snk_in            => c_dp_sosi_rst,
+    verify_expected_snk_in_evt => c_dp_sosi_sl_rst
+  );
+
   ------------------------------------------------------------------------------
   -- DUT
   ------------------------------------------------------------------------------
-  r_transpose <= d_transpose when rising_edge(clk);
-  r_undo_transpose <= d_undo_transpose when rising_edge(clk);
+
+  p_clk : process(rst, clk)
+  begin
+    if rst = '1' then
+      r_transpose      <= c_reorder_transpose_rst;
+      r_undo_transpose <= c_reorder_transpose_rst;
+    elsif rising_edge(clk) then
+      r_transpose      <= d_transpose;
+      r_undo_transpose <= d_undo_transpose;
+    end if;
+  end process;
 
   -- The p_comb_transpose and p_comb_undo_transpose can both use
   -- func_reorder_transpose(), by swapping the transpose dimensions.
+
+  nof_blocks_per_packet_input <= g_nof_blocks_per_packet when nof_ch_input = c_nof_ch else
+                                 g_nof_blocks_per_packet * c_factor_blk;
+  nof_data_per_block_input <= g_nof_data_per_block when nof_ch_input = c_nof_ch else
+                              g_nof_data_per_block * c_factor_dat;
+
   p_comb_transpose : process(rst, r_transpose, select_cipo)
     variable v : t_reorder_transpose;
   begin
     if select_cipo.waitrequest = '0' then
       -- Read from reorder_col_select page
-      v := func_reorder_transpose(g_nof_data_per_block, g_nof_blocks_per_packet, r_transpose);
+      v := func_reorder_transpose(nof_data_per_block_input, nof_blocks_per_packet_input, r_transpose);
     else
       -- No read, new reorder_col_select page not available yet
       v := c_reorder_transpose_rst;
@@ -230,12 +363,17 @@ begin
     d_transpose <= v;
   end process;
 
+  nof_blocks_per_packet_transposed <= g_nof_blocks_per_packet when nof_ch_transposed = c_nof_ch else
+                                      g_nof_blocks_per_packet * c_factor_blk;
+  nof_data_per_block_transposed <= g_nof_data_per_block when nof_ch_transposed = c_nof_ch else
+                                   g_nof_data_per_block * c_factor_dat;
+
   p_comb_undo_transpose : process(rst, r_undo_transpose, undo_select_cipo)
     variable v : t_reorder_transpose;
   begin
     if undo_select_cipo.waitrequest = '0' then
       -- Read from reorder_col_select page
-      v := func_reorder_transpose(g_nof_blocks_per_packet, g_nof_data_per_block, r_undo_transpose);
+      v := func_reorder_transpose(nof_blocks_per_packet_transposed, nof_data_per_block_transposed, r_undo_transpose);
     else
       -- No read, new reorder_col_select page not available yet
       v := c_reorder_transpose_rst;
@@ -247,20 +385,31 @@ begin
     d_undo_transpose <= v;
   end process;
 
+  nof_blocks_per_packet_output <= g_nof_blocks_per_packet when nof_ch_output = c_nof_ch else
+                                  g_nof_blocks_per_packet * c_factor_blk;
+  nof_data_per_block_output <= g_nof_data_per_block when nof_ch_output = c_nof_ch else
+                               g_nof_data_per_block * c_factor_dat;
+
   u_transpose : entity work.reorder_col_select
   generic map (
     g_dsp_data_w  => g_dsp_data_w,
-    g_nof_ch_in   => c_nof_ch,
-    g_nof_ch_sel  => c_nof_ch,
+    g_nof_ch_in   => c_nof_ch_long,
+    g_nof_ch_sel  => c_nof_ch_long,
     g_use_complex => g_use_complex
   )
   port map (
     dp_rst          => rst,
     dp_clk          => clk,
 
+    reorder_busy    => reorder_busy_transposed,
+
     -- Dynamic reorder block size control
-    nof_ch_in       => nof_ch,
-    nof_ch_sel      => nof_ch,
+    nof_ch_in       => nof_ch_input,
+    nof_ch_sel      => nof_ch_input,
+
+    -- Captured reorder block size control used for output_sosi
+    output_nof_ch_in  => nof_ch_transposed,
+    output_nof_ch_sel => open,
 
     -- Memory Mapped
     col_select_mosi => r_transpose.select_copi,
@@ -274,17 +423,23 @@ begin
   u_undo_transpose : entity work.reorder_col_select
   generic map (
     g_dsp_data_w  => g_dsp_data_w,
-    g_nof_ch_in   => c_nof_ch,
-    g_nof_ch_sel  => c_nof_ch,
+    g_nof_ch_in   => c_nof_ch_long,
+    g_nof_ch_sel  => c_nof_ch_long,
     g_use_complex => g_use_complex
   )
   port map (
     dp_rst          => rst,
     dp_clk          => clk,
 
+    reorder_busy    => reorder_busy_output,
+
     -- Dynamic reorder block size control
-    nof_ch_in       => nof_ch,
-    nof_ch_sel      => nof_ch,
+    nof_ch_in       => nof_ch_transposed,
+    nof_ch_sel      => nof_ch_transposed,
+
+    -- Captured reorder block size control used for output_sosi
+    output_nof_ch_in  => nof_ch_output,
+    output_nof_ch_sel => open,
 
     -- Memory Mapped
     col_select_mosi => r_undo_transpose.select_copi,
@@ -295,4 +450,5 @@ begin
     output_sosi     => out_sosi
   );
 
+  reorder_busy <= reorder_busy_transposed or reorder_busy_output;
 end tb;
diff --git a/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd b/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd
index 7f25104d31..bd66fd81f0 100644
--- a/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd
+++ b/libraries/base/reorder/tb/vhdl/tb_tb_reorder_col_select_all.vhd
@@ -38,17 +38,23 @@ architecture tb of tb_tb_reorder_col_select_all is
 begin
 
 -- g_dsp_data_w            : natural := 16;  -- complex data width, = c_data_w / 2
--- g_nof_sync              : natural := 1;
+-- g_nof_sync              : natural := 2;
 -- g_nof_packets_per_sync  : natural := 3;
 -- g_nof_blocks_per_packet : natural := 5;
 -- g_nof_data_per_block    : natural := 3;
--- g_inter_packet_gap      : natural := 0;
--- g_use_complex           : boolean := false
-
-  u_complex_5_3_no_gaps    : entity work.tb_reorder_col_select_all generic map(16, 3, 2, 5, 3, 0, true);
-  u_data_5_3_no_gaps       : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3, 0, false);
-  u_data_5_1_no_gaps       : entity work.tb_reorder_col_select_all generic map(16, 3, 4, 5, 1, 0, false);
-  u_data_1_3_no_gaps       : entity work.tb_reorder_col_select_all generic map(16, 3, 5, 1, 3, 0, false);
-  u_data_3_5_gap_1         : entity work.tb_reorder_col_select_all generic map(16, 3, 6, 3, 5, 1, false);
+-- g_inter_valid_gap       : natural := 5;  -- nof clk gap in in_sosi.valid
+-- g_inter_packet_gap      : natural := 0;  -- nof clk gap between in_sosi.eop and next in_sosi.sop
+-- g_use_complex           : boolean := false;
+-- g_use_dynamic_selection : boolean := true
+
+  u_complex_5_3_no_gaps      : entity work.tb_reorder_col_select_all generic map(16, 3, 2, 5, 3, 0, 0, true,  false);
+  u_data_5_3_no_gaps         : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3, 0, 0, false, false);
+  u_data_5_1_no_gaps         : entity work.tb_reorder_col_select_all generic map(16, 3, 4, 5, 1, 0, 0, false, false);
+  u_data_1_3_no_gaps         : entity work.tb_reorder_col_select_all generic map(16, 3, 5, 1, 3, 0, 0, false, false);
+  u_data_3_5_pkt_gap_1       : entity work.tb_reorder_col_select_all generic map(16, 3, 6, 3, 5, 0, 1, false, false);
+  u_data_3_5_valid_gap_1     : entity work.tb_reorder_col_select_all generic map(16, 3, 6, 3, 5, 1, 0, false, false);
+
+  u_dynamic_data_5_3_no_gaps : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3, 0,  0, false, true);
+  u_dynamic_data_5_3_gaps    : entity work.tb_reorder_col_select_all generic map(16, 3, 3, 5, 3,10,100, false, true);
 
 end tb;
-- 
GitLab