From 9747ac57db58090e77f68b1176544a5cc4fe32af Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Wed, 29 Sep 2021 16:10:45 +0200
Subject: [PATCH] Use g_tb_nof_restart. Added verify_en_delayed_arr using
 out_sosi_arr_exp. Improved out_sosi_arr_exp.

---
 .../base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd    | 164 ++++++++++--------
 1 file changed, 92 insertions(+), 72 deletions(-)

diff --git a/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd b/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd
index ef8cea35ca..cc561ee13f 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd
@@ -37,11 +37,11 @@ USE dp_lib.tb_dp_pkg.ALL;
 ENTITY tb_dp_bsn_align_v2 IS
   GENERIC (
     -- DUT
-    g_nof_streams          : NATURAL := 5;      -- number of input and output streams
+    g_nof_streams          : NATURAL := 2;      -- number of input and output streams
     g_bsn_latency_max      : NATURAL := 2;      -- Maximum travel latency of a remote block in number of block periods T_blk
     g_nof_aligners_max     : POSITIVE := 1;     -- 1 when only align at last node, > 1 when align at every intermediate node
     g_block_size           : NATURAL := 11;     -- > 1, g_block_size=1 is not supported
-    g_gap_size             : NATURAL :=  9;     -- block period = g_block_size + g_gap_size
+    g_block_period         : NATURAL := 20;     -- >= g_block_size, = g_block_size + c_gap_size
     g_bsn_w                : NATURAL := c_dp_stream_bsn_w;  -- number of bits in sosi BSN
     g_data_w               : NATURAL := 16;     -- number of bits in sosi data
     g_replacement_value    : INTEGER := 17;      -- output sosi data replacement value for missing input blocks
@@ -50,8 +50,9 @@ ENTITY tb_dp_bsn_align_v2 IS
     g_rd_latency           : NATURAL := 2;      -- 1 or 2, choose 2 to ease timing closure
 
     -- TB
-    g_diff_delay_max       : NATURAL := 45;      -- maximum nof clk delay between any inputs, <= c_align_latency
-    g_nof_repeat           : NATURAL := 8
+    g_tb_diff_delay_max    : NATURAL := 10;      -- maximum nof clk delay between any inputs, <= c_align_latency_nof_clk
+    g_tb_nof_restart       : NATURAL := 2;       -- number of times to restart the input stimuli
+    g_tb_nof_blocks        : NATURAL := 20       -- number of input blocks per restart
   );
 END tb_dp_bsn_align_v2;
 
@@ -62,17 +63,21 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS
   
   CONSTANT c_data_w                   : NATURAL := 16;
   CONSTANT c_data_init                : INTEGER := 0;
-  CONSTANT c_bsn_w                    : NATURAL := 16;
-  CONSTANT c_bsn_init                 : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := TO_UVEC(3, c_bsn_w);
+  CONSTANT c_bsn_w                    : NATURAL := 16;  -- use <= 31 bit to fit NATURAL
+  CONSTANT c_bsn_init                 : NATURAL := 3;
   CONSTANT c_channel_init             : INTEGER := 0;
   CONSTANT c_err_init                 : NATURAL := 247;
   CONSTANT c_sync_period              : NATURAL := 7;
   CONSTANT c_sync_offset              : NATURAL := 2;
   
-  CONSTANT c_block_period             : NATURAL := g_block_size + g_gap_size;
+  CONSTANT c_gap_size                 : NATURAL := g_block_period - g_block_size;
   CONSTANT c_dut_latency              : NATURAL := g_pipeline_input + g_rd_latency + 2;
-  CONSTANT c_align_latency            : NATURAL := g_bsn_latency_max * c_block_period;
-  CONSTANT c_total_latency            : NATURAL := c_dut_latency + c_align_latency;
+  CONSTANT c_align_latency_nof_valid  : NATURAL := g_bsn_latency_max * g_block_size;
+  CONSTANT c_align_latency_nof_clk    : NATURAL := g_bsn_latency_max * g_block_period;
+  CONSTANT c_total_latency            : NATURAL := c_dut_latency + c_align_latency_nof_clk;
+  CONSTANT c_verify_nof_blocks        : NATURAL := g_tb_nof_blocks - g_bsn_latency_max;  -- skip last blocks
+
+  TYPE t_tb_state IS (s_idle, s_start, s_restart, s_lost);
 
   TYPE t_data_arr    IS ARRAY (g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
   TYPE t_bsn_arr     IS ARRAY (g_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0);
@@ -86,18 +91,18 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS
     out_sosi_arr : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
   END RECORD;
 
-  SIGNAL tb_end_arr            : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'0');
+  SIGNAL tb_end_arr            : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0');
   SIGNAL tb_end                : STD_LOGIC;
   SIGNAL clk                   : STD_LOGIC := '1';
   SIGNAL rst                   : STD_LOGIC := '1';
 
   SIGNAL node_index            : NATURAL := 0;
 
-  SIGNAL stream_en_arr         : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'1');  -- default all streams are enabled
+  SIGNAL stream_en_arr         : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '1');  -- default all streams are enabled
 
-  SIGNAL ref_siso_arr          : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
+  SIGNAL ref_siso_arr          : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
   SIGNAL ref_sosi_arr          : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
-  SIGNAL in_sosi_arr           : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_sosi_rst);
+  SIGNAL in_sosi_arr           : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
 
   SIGNAL in_sync_arr           : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
   SIGNAL in_sop_arr            : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
@@ -119,8 +124,9 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS
   SIGNAL r                     : t_reg;
   SIGNAL nxt_r                 : t_reg;
 
-  SIGNAL out_siso_arr          : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
+  SIGNAL out_siso_arr          : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
   SIGNAL out_sosi_arr          : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
+  SIGNAL out_sosi              : t_dp_sosi;
 
   SIGNAL out_sync_arr          : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
   SIGNAL out_sop_arr           : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
@@ -131,14 +137,18 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS
   SIGNAL out_channel_arr       : t_channel_arr;
   SIGNAL out_err_arr           : t_err_arr;
 
+  SIGNAL tb_state              : t_tb_state;
   SIGNAL tb_bsn                : INTEGER;
-  SIGNAL ref_sosi_arr_dly      : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
-  SIGNAL out_sosi_arr_exp      : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
-  SIGNAL verify_done_arr       : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS=>'0');
-  SIGNAL verify_en_prev_arr    : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
-  SIGNAL verify_en_delayed_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
-
-  SIGNAL hold_out_sop_arr      : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0);
+  SIGNAL restart_cnt_arr       : t_nat_integer_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => -1);
+  SIGNAL restart_cnt           : INTEGER := 0;
+  SIGNAL ref_sosi_arr_dly      : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL out_sosi_arr_exp      : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL out_sosi_exp          : t_dp_sosi;
+  SIGNAL verify_done_arr       : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0');
+  SIGNAL verify_en_prev_arr    : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0');
+  SIGNAL verify_en_delayed_arr : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0');
+
+  SIGNAL hold_out_sop_arr      : STD_LOGIC_VECTOR(g_nof_streams-1 DOWNTO 0) := (OTHERS => '0');
   SIGNAL prev_out_bsn_arr      : t_bsn_arr;
   SIGNAL expected_out_bsn_arr  : t_bsn_arr;
   SIGNAL prev_out_data_arr     : t_data_arr;
@@ -147,10 +157,10 @@ ARCHITECTURE tb OF tb_dp_bsn_align_v2 IS
   -- Return input delay as function of inputs stream index I
   FUNCTION func_input_delay(I : NATURAL) RETURN NATURAL IS
   BEGIN
-    RETURN g_diff_delay_max * I / (g_nof_streams - 1);
+    RETURN g_tb_diff_delay_max * I / (g_nof_streams - 1);
   END;
 
-  SIGNAL dbg_diff_delay_max : NATURAL := g_diff_delay_max;
+  SIGNAL dbg_tb_diff_delay_max : NATURAL := g_tb_diff_delay_max;
   SIGNAL dbg_func_delay_max : NATURAL := func_input_delay(g_nof_streams - 1);
 
 BEGIN
@@ -166,35 +176,34 @@ BEGIN
   gen_input : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE
     p_stimuli : PROCESS
       VARIABLE v_sync      : STD_LOGIC := '0';
-      VARIABLE v_bsn       : STD_LOGIC_VECTOR(c_bsn_w-1 DOWNTO 0) := c_bsn_init;
+      VARIABLE v_bsn       : NATURAL;
       VARIABLE v_data      : NATURAL := c_data_init;
       VARIABLE v_channel   : NATURAL := c_channel_init;
       VARIABLE v_err       : NATURAL := c_err_init;
-      VARIABLE v_diff_bsn  : NATURAL := 0;
     BEGIN
       v_data := v_data + I;
       ref_sosi_arr(I) <= c_dp_sosi_rst;
       proc_common_wait_until_low(clk, rst);
       proc_common_wait_some_cycles(clk, 10);
-      
+      restart_cnt_arr(I) <= restart_cnt_arr(I) + 1;
+
       -- Begin of stimuli
-      FOR R IN 0 TO g_nof_repeat-v_diff_bsn-1 LOOP
-        v_sync := sel_a_b(TO_UINT(v_bsn) MOD c_sync_period = c_sync_offset, '1', '0');
-        proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_data_w, v_data, 0, 0, g_block_size, v_channel, v_err, v_sync, v_bsn, clk, stream_en_arr(I), ref_siso_arr(I), ref_sosi_arr(I));
-        v_bsn  := INCR_UVEC(v_bsn, 1);
-        v_data := v_data + g_block_size;
-        proc_common_wait_some_cycles(clk, g_gap_size);  -- create gap between frames
+      FOR S IN 0 TO g_tb_nof_restart-1 LOOP
+        v_bsn := c_bsn_init;
+        FOR R IN 0 TO g_tb_nof_blocks-1 LOOP
+          v_sync := sel_a_b(v_bsn MOD c_sync_period = c_sync_offset, '1', '0');
+          proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_data_w, v_data, 0, 0, g_block_size, v_channel, v_err, v_sync, TO_UVEC(v_bsn, c_bsn_w), clk, stream_en_arr(I), ref_siso_arr(I), ref_sosi_arr(I));
+          v_bsn  := v_bsn + 1;
+          v_data := v_data + g_block_size;
+          proc_common_wait_some_cycles(clk, c_gap_size);  -- create gap between frames
+        END LOOP;
+        -- no gap between restarts, to ease verification by maintaining fixed latency of out_sosi_arr_exp
+        restart_cnt_arr(I) <= restart_cnt_arr(I) + 1;
       END LOOP;
-      
+
       -- End of stimuli, g_bsn_latency_max blocks remain in DUT buffer
-      expected_out_bsn_arr(I)  <= INCR_UVEC(v_bsn, -1 - g_bsn_latency_max);
-      IF func_input_delay(I) <= c_align_latency THEN
-        -- Verify expected input data
-        expected_out_data_arr(I) <= TO_UVEC(v_data-1 -g_bsn_latency_max*g_block_size, c_data_w);
-      ELSE
-        -- Verify expected replacement data for lost input block
-        expected_out_data_arr(I) <= TO_UVEC(g_replacement_value, c_data_w);
-      END IF;
+      expected_out_bsn_arr(I) <= TO_UVEC(v_bsn-1 - g_bsn_latency_max, c_bsn_w);
+      expected_out_data_arr(I) <= TO_UVEC(v_data-1 - c_align_latency_nof_valid, c_data_w);
       
       proc_common_wait_some_cycles(clk, 100);
       verify_done_arr(I) <= '1';
@@ -206,6 +215,17 @@ BEGIN
     END PROCESS;
   END GENERATE;
 
+  -- Use tb_state to view tb progress in Wave window
+  restart_cnt <= restart_cnt_arr(0);
+
+  p_tb_state : PROCESS(restart_cnt)
+  BEGIN
+    tb_state <= s_idle;
+    IF restart_cnt = 0 THEN tb_state <= s_start; END IF;
+    IF restart_cnt = 1 THEN tb_state <= s_restart; END IF;
+    IF restart_cnt = 2 THEN tb_state <= s_lost; END IF;
+  END PROCESS;
+
   -- Create latency misalignment between the input streams
   gen_in_sosi_arr : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE
     in_sosi_arr(I) <= TRANSPORT ref_sosi_arr(I) AFTER func_input_delay(I) * clk_period;
@@ -236,25 +256,36 @@ BEGIN
     out_err_arr(I)     <= out_sosi_arr(I).err;
   END GENERATE;
 
+  out_sosi <= out_sosi_arr(0);  -- take out_sosi control and info from out_sosi_arr(0)
+
   ------------------------------------------------------------------------------
   -- DATA VERIFICATION, use multiple ways to increase coverage
   -- a) Use proc_dp_verify_*() to verify output compared to prev output
   -- b) Use delayed in_sosi_arr as expected out_sosi_arr
   ------------------------------------------------------------------------------
 
+  tb_bsn <= TO_UINT(out_sosi.bsn);
+
+  ref_sosi_arr_dly <= TRANSPORT ref_sosi_arr AFTER c_total_latency * clk_period;
+  out_sosi_arr_exp <= ref_sosi_arr_dly WHEN rising_edge(clk);
+  out_sosi_exp <= out_sosi_arr_exp(0);  -- take out_sosi_exp control and info from out_sosi_arr_exp(0)
+
   ------------------------------------------------------------------------------
   -- a) Use proc_dp_verify_()
   ------------------------------------------------------------------------------
   p_verify_en_prev_arr : PROCESS
   BEGIN
-    verify_en_prev_arr <= (OTHERS => '0');
-    IF g_diff_delay_max <= c_align_latency THEN
+    WAIT UNTIL rising_edge(clk);
+    IF g_tb_diff_delay_max <= c_align_latency_nof_clk THEN
       -- Can only verify incrementing sosi data when no blocks get lost
-      -- Skip sample of first block from verification, because then there is no prev_out_bsn_arr, prev_out_data_arr yet
-      proc_common_wait_until_high(clk, out_sosi_arr(0).sop);
-      verify_en_prev_arr <= (OTHERS => '1');
+      -- Use sop to skip sample of first block from verification, because then there is no prev_out_bsn_arr, prev_out_data_arr yet
+      IF out_sosi_exp.sop = '1' THEN
+        verify_en_prev_arr <= (OTHERS => '0');
+        IF TO_UINT(out_sosi_exp.bsn) - c_bsn_init < c_verify_nof_blocks THEN
+          verify_en_prev_arr <= (OTHERS => '1');
+        END IF;
+      END IF;
     END IF;
-    WAIT;
   END PROCESS;
   
   gen_verify_prev_sosi : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE
@@ -263,8 +294,8 @@ BEGIN
     proc_dp_verify_sop_and_eop(clk, out_val_arr(I), out_sop_arr(I), out_eop_arr(I), hold_out_sop_arr(I));
     
     -- . Verify that the output is incrementing, like the input stimuli
-    proc_dp_verify_data("out_sosi.data", c_rl, clk, verify_en_prev_arr(I), out_siso_arr(I).ready, out_val_arr(I), out_data_arr(I), prev_out_data_arr(I));
-    proc_dp_verify_data("out_sosi.bsn", c_rl, clk, verify_en_prev_arr(I), out_siso_arr(I).ready, out_sop_arr(I), out_bsn_arr(I), prev_out_bsn_arr(I));
+    proc_dp_verify_data("out_sosi_arr().data", c_rl, clk, verify_en_prev_arr(I), out_siso_arr(I).ready, out_val_arr(I), out_data_arr(I), prev_out_data_arr(I));
+    proc_dp_verify_data("out_sosi_arr().bsn", c_rl, clk, verify_en_prev_arr(I), out_siso_arr(I).ready, out_sop_arr(I), out_bsn_arr(I), prev_out_bsn_arr(I));
     
     -- . Verify that the stimuli have been applied at all
     proc_dp_verify_value("out_data_arr", e_equal, clk, verify_done_arr(I), expected_out_data_arr(I), prev_out_data_arr(I));
@@ -274,19 +305,16 @@ BEGIN
   ------------------------------------------------------------------------------
   -- b) Use delayed in_sosi_arr as expected out_sosi_arr
   ------------------------------------------------------------------------------
-  tb_bsn <= TO_UINT(out_sosi_arr(0).bsn);
-
-  ref_sosi_arr_dly <= TRANSPORT ref_sosi_arr AFTER c_total_latency * clk_period;
-  out_sosi_arr_exp <= ref_sosi_arr_dly WHEN rising_edge(clk);
-
-  p_verify_en_delayed_arr : PROCESS
+  p_verify_en_delayed_arr : PROCESS(out_sosi_exp)
   BEGIN
-    verify_en_delayed_arr <= (OTHERS => '1');
-    -- Skip last blocks that are still in DUT buffer
-    proc_common_wait_until_value(TO_UINT(c_bsn_init) + g_nof_repeat - g_bsn_latency_max - 1, clk, tb_bsn);
-    proc_common_wait_until_high(clk, out_sosi_arr(0).eop);
-    verify_en_delayed_arr <= (OTHERS => '0');
-    WAIT;
+    IF g_tb_diff_delay_max <= c_align_latency_nof_clk THEN
+      -- Can only verify incrementing sosi data when no blocks get lost
+      -- Skip sample of first block from verification, because then there is no prev_out_bsn_arr, prev_out_data_arr yet
+      verify_en_delayed_arr <= (OTHERS => '1');
+      IF TO_UINT(out_sosi_exp.bsn) - c_bsn_init >= c_verify_nof_blocks THEN
+          verify_en_delayed_arr <= (OTHERS => '0');
+      END IF;
+    END IF;
   END PROCESS;
 
   gen_verify_delayed_sosi : FOR I IN g_nof_streams-1 DOWNTO 0 GENERATE
@@ -298,17 +326,9 @@ BEGIN
            ASSERT out_sosi_arr(I).sop = out_sosi_arr_exp(I).sop REPORT "Wrong sop for output " & int_to_str(I) SEVERITY ERROR;
            ASSERT out_sosi_arr(I).eop = out_sosi_arr_exp(I).eop REPORT "Wrong eop for output " & int_to_str(I) SEVERITY ERROR;
            ASSERT out_sosi_arr(I).valid = out_sosi_arr_exp(I).valid REPORT "Wrong valid for output " & int_to_str(I) SEVERITY ERROR;
-           IF func_input_delay(I) <= c_align_latency THEN
-             -- Verify expected input data
-             ASSERT out_sosi_arr(I).data  = out_sosi_arr_exp(I).data REPORT "Wrong data for output " & int_to_str(I) & " : "
-                                                                            & int_to_str(TO_UINT(out_sosi_arr(I).data)) & " /= "
-                                                                            & int_to_str(TO_UINT(out_sosi_arr_exp(I).data)) SEVERITY ERROR;
-           ELSE
-             -- Verify expected replacement data for lost input block
-             ASSERT TO_UINT(out_sosi_arr(I).data) = g_replacement_value REPORT "Wrong replacement data for output " & int_to_str(I) & " : "
-                                                                               & int_to_str(TO_UINT(out_sosi_arr(I).data)) & " /= "
-                                                                               & int_to_str(g_replacement_value) SEVERITY ERROR;
-           END IF;
+           ASSERT out_sosi_arr(I).data  = out_sosi_arr_exp(I).data REPORT "Wrong data for output " & int_to_str(I) & " : "
+                                                                          & int_to_str(TO_UINT(out_sosi_arr(I).data)) & " /= "
+                                                                          & int_to_str(TO_UINT(out_sosi_arr_exp(I).data)) SEVERITY ERROR;
         END IF;
       END IF;
     END PROCESS;
-- 
GitLab