From 21f43b38aea243fd48a1d685b3e8ccb531c69724 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Fri, 8 Oct 2021 14:12:45 +0200
Subject: [PATCH] Added verification of the BSN monitors by checking the
 measured latency.

---
 .../dp/tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd     | 114 ++++++++++++++----
 1 file changed, 90 insertions(+), 24 deletions(-)

diff --git a/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd
index f4f2544d58..0b5a6f61f4 100644
--- a/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_mmp_dp_bsn_align_v2.vhd
@@ -21,8 +21,13 @@
 -- Description:
 --    The functional part is already verified by tb_tb_dp_bsn_align_v2.vhd.
 --    Tb features:
---    . verify expected end values in gen_verify_ctrl to ensure that test has
---      ran
+--    . verify expected end values for output data and bsn in gen_verify_ctrl
+--      to ensure that test has ran
+--    . verify MM access to input stream enable in p_mm_verify_bsn_align
+--    . verify MM access to input BSN monitors by verifiying expected input
+--      latencies for different input delays
+--    . verify MM access to output BSN monitor by verifiying expected output
+--      latencies.
 --
 -- Usage:
 -- > as 5
@@ -51,25 +56,40 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS
 
   CONSTANT c_rl                         : NATURAL := 1;
   CONSTANT c_tb_nof_restart             : NATURAL := 2;    -- number of times to restart the input stimuli
-  CONSTANT c_tb_nof_blocks              : NATURAL := 20;   -- number of input blocks per restart
+  CONSTANT c_tb_nof_blocks              : NATURAL := 50;   -- number of input blocks per restart
 
   -- Fixed dut generics
   -- . for dp_bsn_align_v2
-  CONSTANT c_nof_streams                : NATURAL := 2;
+  CONSTANT c_nof_streams                : NATURAL := 3;
   CONSTANT c_bsn_latency_max            : NATURAL := 1;
   CONSTANT c_nof_aligners_max           : POSITIVE := 1;   -- fixed in this tb
   CONSTANT c_block_size                 : NATURAL := 11;
-  CONSTANT c_block_period               : NATURAL := 20;
+  CONSTANT c_block_period               : NATURAL := 11;
   CONSTANT c_bsn_w                      : NATURAL := c_dp_stream_bsn_w;
   CONSTANT c_data_w                     : NATURAL := 16;
   CONSTANT c_data_replacement_value     : INTEGER := 17;
   CONSTANT c_use_mm_output              : BOOLEAN := FALSE;
   CONSTANT c_pipeline_input             : NATURAL := 1;
+  CONSTANT c_pipeline_output            : NATURAL := 1;
   CONSTANT c_rd_latency                 : NATURAL := 2;
   -- . for mms_dp_bsn_monitor_v2
   CONSTANT c_nof_clk_per_sync           : NATURAL := 200*10**6;
-  CONSTANT c_nof_input_bsn_monitors     : NATURAL := 0;
-  CONSTANT c_use_bsn_output_monitor     : BOOLEAN := FALSE;
+  CONSTANT c_nof_input_bsn_monitors     : NATURAL := c_nof_streams;
+  CONSTANT c_use_bsn_output_monitor     : BOOLEAN := TRUE;
+
+  CONSTANT c_reg_bsn_monitor_adr_w      : NATURAL := ceil_log2(7);
+  CONSTANT c_reg_bsn_monitor_span       : NATURAL := 2**c_reg_bsn_monitor_adr_w;
+
+  -- maximum nof clk delay between any inputs, <= c_align_latency_nof_clk
+  -- . the -1 is due to some acceptable pipeline detail related to dp_block_from_mm
+  CONSTANT c_diff_delay_max             : NATURAL := c_bsn_latency_max * c_block_period - sel_a_b(c_rd_latency > 1, 0, 1);
+  CONSTANT c_diff_delay                 : NATURAL := c_diff_delay_max;
+
+  -- Return input delay as function of inputs stream index I
+  FUNCTION func_input_delay(I : NATURAL) RETURN NATURAL IS
+  BEGIN
+    RETURN c_diff_delay * I / (c_nof_streams - 1);
+  END;
 
   -- Input stream settings
   CONSTANT c_data_init                  : INTEGER := 0;
@@ -81,16 +101,16 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS
   CONSTANT c_gap_size                   : NATURAL := c_block_period - c_block_size;
 
   -- DUT latency
-  CONSTANT c_mm_to_dp_latency         : NATURAL := 1;
-  CONSTANT c_dut_latency              : NATURAL := c_pipeline_input + c_rd_latency + c_mm_to_dp_latency;
+  CONSTANT c_mm_to_dp_latency           : NATURAL := 1;
+  CONSTANT c_dut_latency                : NATURAL := c_pipeline_input + c_rd_latency + c_mm_to_dp_latency + c_pipeline_output;
 
-  CONSTANT c_align_latency_nof_blocks : NATURAL := c_bsn_latency_max * c_nof_aligners_max;  -- in number blocks
-  CONSTANT c_align_latency_nof_valid  : NATURAL := c_bsn_latency_max * c_nof_aligners_max * c_block_size;  -- in number of data samples
-  CONSTANT c_align_latency_nof_clk    : NATURAL := c_bsn_latency_max * c_nof_aligners_max * c_block_period;  -- in number clk cycles
+  CONSTANT c_align_latency_nof_blocks   : NATURAL := c_bsn_latency_max * c_nof_aligners_max;  -- in number blocks
+  CONSTANT c_align_latency_nof_valid    : NATURAL := c_bsn_latency_max * c_nof_aligners_max * c_block_size;  -- in number of data samples
+  CONSTANT c_align_latency_nof_clk      : NATURAL := c_bsn_latency_max * c_nof_aligners_max * c_block_period;  -- in number clk cycles
 
   -- Total DUT chain latency
-  CONSTANT c_total_latency            : NATURAL := c_dut_latency + c_align_latency_nof_clk;
-  CONSTANT c_verify_nof_blocks        : NATURAL := c_tb_nof_blocks - c_align_latency_nof_blocks;  -- skip last blocks that are still in the DUT buffer
+  CONSTANT c_total_latency              : NATURAL := c_dut_latency + c_align_latency_nof_clk;
+  CONSTANT c_verify_nof_blocks          : NATURAL := c_tb_nof_blocks - c_align_latency_nof_blocks;  -- skip last blocks that are still in the DUT buffer
 
   -- Signal monitoring and verification
   TYPE t_data_arr    IS ARRAY (c_nof_streams-1 DOWNTO 0) OF STD_LOGIC_VECTOR(c_data_w-1 DOWNTO 0);
@@ -104,6 +124,8 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS
   SIGNAL dp_end                   : STD_LOGIC := '0';
   SIGNAL tb_end                   : STD_LOGIC := '0';
   SIGNAL streams_enabled          : STD_LOGIC := '0';
+  SIGNAL restart_cnt_arr          : t_nat_integer_arr(c_nof_streams-1 DOWNTO 0) := (OTHERS => -1);
+  SIGNAL restart_cnt              : INTEGER := 0;
 
   -- MM clock domain
   SIGNAL mm_clk                   : STD_LOGIC := '1';
@@ -116,6 +138,9 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS
   SIGNAL reg_output_monitor_copi  : t_mem_copi := c_mem_copi_rst;
   SIGNAL reg_output_monitor_cipo  : t_mem_cipo;
 
+  SIGNAL mon_latency_input_arr    : t_nat_natural_arr(c_nof_streams-1 DOWNTO 0);
+  SIGNAL mon_latency_output       : NATURAL;
+
   -- DP clock domain
   SIGNAL dp_clk                   : STD_LOGIC := '1';
   SIGNAL dp_rst                   : STD_LOGIC := '1';
@@ -148,12 +173,20 @@ ARCHITECTURE tb OF tb_mmp_dp_bsn_align_v2 IS
   SIGNAL out_err_arr              : t_err_arr;
 
   SIGNAL verify_done_arr          : STD_LOGIC_VECTOR(c_nof_streams-1 DOWNTO 0) := (OTHERS => '0');
+  SIGNAL verify_done              : STD_LOGIC;
 
   SIGNAL hold_out_sop_arr         : STD_LOGIC_VECTOR(c_nof_streams-1 DOWNTO 0) := (OTHERS => '0');
   SIGNAL expected_out_bsn_arr     : t_bsn_arr;
   SIGNAL expected_out_data_arr    : t_data_arr;
   SIGNAL expected_out_channel_arr : t_channel_arr;
 
+  -- Debug signals for view in Wave window
+  SIGNAL dbg_c_align_latency_nof_blocks : NATURAL := c_align_latency_nof_blocks;
+  SIGNAL dbg_c_align_latency_nof_valid  : NATURAL := c_align_latency_nof_valid;
+  SIGNAL dbg_c_align_latency_nof_clk    : NATURAL := c_align_latency_nof_clk;
+  SIGNAL dbg_c_total_latency            : NATURAL := c_total_latency;
+  SIGNAL dbg_c_verify_nof_blocks        : NATURAL := c_verify_nof_blocks;
+
 BEGIN
 
   dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2;
@@ -170,39 +203,60 @@ BEGIN
   -- MM stimuli and verification
   ------------------------------------------------------------------------------
 
-  p_stimuli_and_verify_mm : PROCESS
-    VARIABLE v_bsn : NATURAL;
+  p_mm_verify_bsn_align : PROCESS
   BEGIN
     proc_common_wait_until_low(dp_clk, mm_rst);
     proc_common_wait_until_low(dp_clk, dp_rst);
     proc_common_wait_some_cycles(mm_clk, 5);
 
-    -- . Read stream enable bits, default '0' after power up
+    -- Read stream enable bits, default '0' after power up
     FOR I IN 0 TO c_nof_streams-1 LOOP
       proc_mem_mm_bus_rd(I, mm_clk, reg_bsn_align_cipo, reg_bsn_align_copi);
       proc_mem_mm_bus_rd_latency(1, mm_clk);
       ASSERT reg_bsn_align_cipo.rddata(0) = '0' REPORT "Wrong stream disable for output " & int_to_str(I) SEVERITY ERROR;
     END LOOP;
 
-    -- . Write stream enable bits for stream_en_arr
+    -- Write stream enable bits for stream_en_arr
     FOR I IN 0 TO c_nof_streams-1 LOOP
       proc_mem_mm_bus_wr(I, 1,  mm_clk, reg_bsn_align_cipo, reg_bsn_align_copi);
     END LOOP;
     proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency);
     proc_common_wait_some_cycles(dp_clk, c_cross_clock_domain_latency);
 
-    -- . Read stream enable bits, should now be '1'
+    -- Read stream enable bits, should now be '1'
     FOR I IN 0 TO c_nof_streams-1 LOOP
       proc_mem_mm_bus_rd(I, mm_clk, reg_bsn_align_cipo, reg_bsn_align_copi);
       proc_mem_mm_bus_rd_latency(1, mm_clk);
-      ASSERT reg_bsn_align_cipo.rddata(0) = '1' REPORT "Wrong stream enable for output " & int_to_str(I) SEVERITY ERROR;
+      ASSERT reg_bsn_align_cipo.rddata(0) = '1' REPORT "Wrong BSN align stream enable for output " & int_to_str(I) SEVERITY ERROR;
     END LOOP;
 
+    -- End of MM test
     streams_enabled <= '1';
+    WAIT;
+  END PROCESS;
+
+  p_mm_verify_bsn_monitors : PROCESS
+  BEGIN
+    proc_common_wait_until_high(mm_clk, verify_done);
 
-    ---------------------------------------------------------------------------
-    -- End of test
-    ---------------------------------------------------------------------------
+    -- Read input BSN monitors
+    FOR I IN 0 TO c_nof_streams-1 LOOP
+      proc_mem_mm_bus_rd(6 + I*c_reg_bsn_monitor_span, mm_clk, reg_input_monitor_cipo, reg_input_monitor_copi);
+      proc_mem_mm_bus_rd_latency(1, mm_clk);
+      mon_latency_input_arr(I) <= TO_UINT(reg_input_monitor_cipo.rddata);
+      proc_common_wait_some_cycles(mm_clk, 1);
+      ASSERT mon_latency_input_arr(I) = func_input_delay(I) REPORT "Wrong input BSN monitor latency for input " & int_to_str(I) SEVERITY ERROR;
+    END LOOP;
+
+    -- Read output BSN monitor
+    proc_mem_mm_bus_rd(6, mm_clk, reg_output_monitor_cipo, reg_output_monitor_copi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    mon_latency_output <= TO_UINT(reg_output_monitor_cipo.rddata);
+
+    proc_common_wait_some_cycles(mm_clk, 1);
+    ASSERT mon_latency_output = c_total_latency REPORT "Wrong output BSN monitor latency" SEVERITY ERROR;
+
+    -- End of MM test
     mm_end <= '1';
     WAIT;
   END PROCESS;
@@ -225,6 +279,7 @@ BEGIN
       proc_common_wait_until_low(dp_clk, dp_rst);
       proc_common_wait_until_high(dp_clk, streams_enabled);
       proc_common_wait_some_cycles(dp_clk, 10);
+      restart_cnt_arr(I) <= restart_cnt_arr(I) + 1;
 
       -- Begin of stimuli
       FOR S IN 0 TO c_tb_nof_restart-1 LOOP
@@ -238,6 +293,7 @@ BEGIN
         END LOOP;
         -- Create gap between restarts
         proc_common_wait_some_cycles(dp_clk, 100);
+        restart_cnt_arr(I) <= restart_cnt_arr(I) + 1;
       END LOOP;
 
       -- End of stimuli
@@ -252,15 +308,24 @@ BEGIN
       proc_common_wait_some_cycles(dp_clk, 1);
       verify_done_arr(I) <= '0';
 
+      -- Simulate some more to easy recognizing verify_done in Wave window
+      proc_common_wait_some_cycles(dp_clk, 100);
       dp_end_arr(I) <= '1';
       WAIT;
     END PROCESS;
   END GENERATE;
 
-  in_sosi_arr <= ref_sosi_arr;
+  verify_done <= verify_done_arr(0);
+  restart_cnt <= restart_cnt_arr(0);
 
   dp_end <= vector_and(dp_end_arr);
 
+  -- Model misalignment latency between the input streams to have different
+  -- input BSN monitor latencies
+  gen_rx_sosi_arr : FOR I IN c_nof_streams-1 DOWNTO 0 GENERATE
+    in_sosi_arr(I) <= TRANSPORT ref_sosi_arr(I) AFTER func_input_delay(I) * c_dp_clk_period;
+  END GENERATE;
+
   ------------------------------------------------------------------------------
   -- Data verification
   ------------------------------------------------------------------------------
@@ -317,6 +382,7 @@ BEGIN
     g_data_replacement_value     => c_data_replacement_value,
     g_use_mm_output              => c_use_mm_output,
     g_pipeline_input             => c_pipeline_input,
+    g_pipeline_output            => c_pipeline_output,
     g_rd_latency                 => c_rd_latency,
     g_nof_clk_per_sync           => c_nof_clk_per_sync,
     g_nof_input_bsn_monitors     => c_nof_input_bsn_monitors,
-- 
GitLab