From 958fdb48bbee3e85fa9a832f674968c4f74e363a Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Wed, 28 Sep 2022 13:15:00 +0200
Subject: [PATCH] Use block counts at sync for MM read..

---
 .../dp/src/vhdl/dp_block_validate_err.vhd     | 53 +++++++++++++++----
 .../dp/tb/vhdl/tb_dp_block_validate_err.vhd   | 40 +++++++++++---
 2 files changed, 76 insertions(+), 17 deletions(-)

diff --git a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
index 74e3db58e9..0cac366741 100644
--- a/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
+++ b/libraries/base/dp/src/vhdl/dp_block_validate_err.vhd
@@ -120,13 +120,22 @@ ARCHITECTURE rtl OF dp_block_validate_err IS
   -- Registers in st_clk domain
   SIGNAL count_reg     : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0');
 
+  SIGNAL nxt_cnt_en       : STD_LOGIC;
+  SIGNAL cnt_en           : STD_LOGIC := '0';
+  SIGNAL cnt_this_eop     : STD_LOGIC;
+
   SIGNAL mm_cnt_clr       : STD_LOGIC;
   SIGNAL cnt_clr          : STD_LOGIC;
   SIGNAL cnt_blk          : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0);
+  SIGNAL cnt_blk_en       : STD_LOGIC;
   SIGNAL cnt_discarded    : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0);
   SIGNAL cnt_discarded_en : STD_LOGIC;
-  SIGNAL cnt_err          : t_cnt_err_arr(g_nof_err_counts-1 DOWNTO 0);
-  SIGNAL cnt_err_en       : STD_LOGIC_VECTOR(g_nof_err_counts-1 DOWNTO 0);
+  SIGNAL cnt_err_arr      : t_cnt_err_arr(g_nof_err_counts-1 DOWNTO 0);
+  SIGNAL cnt_err_en_arr   : STD_LOGIC_VECTOR(g_nof_err_counts-1 DOWNTO 0);
+
+  SIGNAL hold_cnt_blk        : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0);
+  SIGNAL hold_cnt_discarded  : STD_LOGIC_VECTOR(g_cnt_w-1 DOWNTO 0);
+  SIGNAL hold_cnt_err_arr    : t_cnt_err_arr(g_nof_err_counts-1 DOWNTO 0);
 
   SIGNAL err_ok          : STD_LOGIC;
   SIGNAL err_ok_reg      : STD_LOGIC;
@@ -152,7 +161,15 @@ BEGIN
       out_pulse => cnt_clr
     );
 
+  -- . clear block counters immediately at cnt_clr
+  -- . start block counters after sync, e.g. to align block counters in different nodes in
+  --   case the snk_in was (already) active during the cnt_clr
+  nxt_cnt_en <= '0' WHEN cnt_clr = '1' ELSE '1' WHEN snk_in.sync = '1' ELSE cnt_en;
+  cnt_en <= nxt_cnt_en WHEN rising_edge(dp_clk);
+  cnt_this_eop <= cnt_en AND snk_in.eop;
+
   -- block counter
+  cnt_blk_en <= cnt_this_eop;
   u_blk_counter : ENTITY common_lib.common_counter
   GENERIC MAP (
     g_width => g_cnt_w,
@@ -163,12 +180,12 @@ BEGIN
     clk => dp_clk,
 
     cnt_clr => cnt_clr, 
-    cnt_en  => snk_in.eop,
+    cnt_en  => cnt_blk_en,
     count   => cnt_blk
   );
 
   -- discarded block counter
-  cnt_discarded_en <= snk_in.eop WHEN TO_UINT(snk_in.err(g_nof_err_counts-1 DOWNTO 0)) > 0 ELSE '0';
+  cnt_discarded_en <= cnt_this_eop WHEN TO_UINT(snk_in.err(g_nof_err_counts-1 DOWNTO 0)) > 0 ELSE '0';
   u_discarded_counter : ENTITY common_lib.common_counter
   GENERIC MAP (
     g_width => g_cnt_w,
@@ -185,7 +202,7 @@ BEGIN
 
   -- error counters
   gen_err_counters : FOR I IN 0 TO g_nof_err_counts-1 GENERATE
-    cnt_err_en(I) <= snk_in.eop AND snk_in.err(I);
+    cnt_err_en_arr(I) <= cnt_this_eop AND snk_in.err(I);
     u_blk_counter : ENTITY common_lib.common_counter
     GENERIC MAP (
       g_width => g_cnt_w,
@@ -196,17 +213,33 @@ BEGIN
       clk => dp_clk,
   
       cnt_clr => cnt_clr, 
-      cnt_en  => cnt_err_en(I),
-      count   => cnt_err(I)
+      cnt_en  => cnt_err_en_arr(I),
+      count   => cnt_err_arr(I)
     );
   END GENERATE;
 
+  -- Hold counter values at snk_in.sync to have stable values for MM read for comparision between nodes
+  p_hold_counters : PROCESS(dp_clk)
+  BEGIN
+    IF rising_edge(dp_clk) THEN
+      IF cnt_clr = '1' THEN
+        hold_cnt_blk <= (OTHERS=>'0');
+        hold_cnt_discarded <= (OTHERS=>'0');
+        hold_cnt_err_arr <= (OTHERS=>(OTHERS=>'0'));
+      ELSIF snk_in.sync = '1' THEN
+        hold_cnt_blk <= cnt_blk;
+        hold_cnt_discarded <= cnt_discarded;
+        hold_cnt_err_arr <= cnt_err_arr;
+      END IF;
+    END IF;
+  END PROCESS;
+
   -- Register mapping
   gen_reg : FOR I IN 0 TO g_nof_err_counts-1 GENERATE
-    count_reg((I + 1) * c_word_w - 1 DOWNTO I * c_word_w) <= RESIZE_UVEC(cnt_err(I), c_word_w);
+    count_reg((I + 1) * c_word_w - 1 DOWNTO I * c_word_w) <= RESIZE_UVEC(hold_cnt_err_arr(I), c_word_w);
   END GENERATE;
-  count_reg((g_nof_err_counts+1) * c_word_w - 1 DOWNTO  g_nof_err_counts    * c_word_w ) <= RESIZE_UVEC(cnt_discarded, c_word_w);  
-  count_reg((g_nof_err_counts+2) * c_word_w - 1 DOWNTO (g_nof_err_counts+1) * c_word_w ) <= RESIZE_UVEC(cnt_blk,       c_word_w);  
+  count_reg((g_nof_err_counts+1) * c_word_w - 1 DOWNTO  g_nof_err_counts    * c_word_w ) <= RESIZE_UVEC(hold_cnt_discarded, c_word_w);
+  count_reg((g_nof_err_counts+2) * c_word_w - 1 DOWNTO (g_nof_err_counts+1) * c_word_w ) <= RESIZE_UVEC(hold_cnt_blk,       c_word_w);
 
   u_reg : ENTITY common_lib.common_reg_r_w_dc
   GENERIC MAP (
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd
index 9b0c20e901..4061a3570a 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_block_validate_err.vhd
@@ -49,7 +49,7 @@ ENTITY tb_dp_block_validate_err IS
     g_max_block_size       : NATURAL := 9;
     g_nof_err_counts       : NATURAL := 8;
     g_gap_size             : NATURAL := 4;
-    g_cnt_w                : NATURAL := 3 
+    g_cnt_w                : NATURAL := 3
   );
 END tb_dp_block_validate_err;
 
@@ -64,10 +64,11 @@ ARCHITECTURE tb OF tb_dp_block_validate_err IS
 
   CONSTANT c_dut_pipeline             : NATURAL := g_nof_data_per_blk + 3;
   CONSTANT c_nof_sync                 : NATURAL := 5;
-  CONSTANT c_nof_blk                  : NATURAL := g_nof_blocks_per_sync * c_nof_sync;
+  CONSTANT c_nof_blk                  : NATURAL := g_nof_blocks_per_sync * (c_nof_sync - 1);
   CONSTANT c_nof_discarded            : NATURAL := c_nof_blk - ceil_div(c_nof_blk, 2**g_nof_err_counts);
   CONSTANT c_max_cnt                  : NATURAL := 2**g_cnt_w -1;
   
+  CONSTANT c_mm_addr_dp_clear         : NATURAL := g_nof_err_counts+2;
   CONSTANT c_mm_addr_dp_blk_cnt       : NATURAL := g_nof_err_counts+1;
   CONSTANT c_mm_addr_dp_discarded_cnt : NATURAL := g_nof_err_counts;
   CONSTANT c_exp_blk_cnt              : NATURAL := sel_a_b(c_nof_blk < c_max_cnt, c_nof_blk, c_max_cnt);
@@ -78,6 +79,7 @@ ARCHITECTURE tb OF tb_dp_block_validate_err IS
   SIGNAL rst    : STD_LOGIC := '1';
   SIGNAL tb_end : STD_LOGIC := '0';
   
+  SIGNAL stimuli_rst       : STD_LOGIC := '1';
   SIGNAL stimuli_end       : STD_LOGIC;
   SIGNAL stimuli_sosi      : t_dp_sosi;
   SIGNAL stimuli_siso      : t_dp_siso;
@@ -91,6 +93,11 @@ ARCHITECTURE tb OF tb_dp_block_validate_err IS
   SIGNAL reference_siso    : t_dp_siso := c_dp_siso_rdy;
   SIGNAL reg_mosi          : t_mem_mosi := c_mem_mosi_rst;
   SIGNAL reg_miso          : t_mem_miso := c_mem_miso_rst;
+
+  SIGNAL rd_blk_cnt        : NATURAL;
+  SIGNAL rd_discarded_cnt  : NATURAL;
+  SIGNAL rd_err_cnt_arr    : t_natural_arr(g_nof_err_counts-1 DOWNTO 0);
+
 BEGIN
   
   ------------------------------------------------------------------------------
@@ -99,11 +106,13 @@ BEGIN
   dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2;
   mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2;
   rst <= '1', '0' AFTER c_dp_clk_period*7;
-  
+
   ------------------------------------------------------------------------------
   -- Stimuli: 
   ------------------------------------------------------------------------------
 
+  stimuli_rst <= '1', '0' AFTER c_dp_clk_period*17;
+
   -- Generate snk_in with data frames
   u_stimuli : ENTITY work.dp_stream_stimuli
   GENERIC MAP (
@@ -115,7 +124,7 @@ BEGIN
     g_err_incr    => 1
   )
   PORT MAP (
-    rst               => rst,
+    rst               => stimuli_rst,
     clk               => dp_clk,
   
     -- Generate stimuli
@@ -212,14 +221,19 @@ BEGIN
     -- this can be calculated as the dp error field is a counter up to c_nof_blk - 1.
     VARIABLE v_N : INTEGER := 0;
   BEGIN
+    proc_common_wait_until_low(mm_clk, rst);
+    proc_mem_mm_bus_wr(c_mm_addr_dp_clear, 1, mm_clk, reg_mosi);
+
     proc_common_wait_until_lo_hi(dp_clk, stimuli_end);
     proc_common_wait_some_cycles(dp_clk, c_dut_pipeline + 1);
-    proc_common_wait_until_lo_hi(mm_clk, mm_clk);
+    proc_common_wait_some_cycles(mm_clk, 1);
     proc_mem_mm_bus_rd(c_mm_addr_dp_discarded_cnt, mm_clk, reg_miso, reg_mosi);
     proc_mem_mm_bus_rd_latency(1, mm_clk);
+    rd_discarded_cnt <= TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0));
     ASSERT c_exp_discarded_cnt = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong total discarded block count" SEVERITY ERROR;
     proc_mem_mm_bus_rd(c_mm_addr_dp_blk_cnt, mm_clk, reg_miso, reg_mosi);
     proc_mem_mm_bus_rd_latency(1, mm_clk);
+    rd_blk_cnt <= TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0));
     ASSERT c_exp_blk_cnt = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong total block count" SEVERITY ERROR;
     FOR I IN 0 TO g_nof_err_counts-1 LOOP
       v_X := 2**I * ((c_nof_blk-1) / 2**(I+1));
@@ -236,13 +250,25 @@ BEGIN
 
       proc_mem_mm_bus_rd(I, mm_clk, reg_miso, reg_mosi);
       proc_mem_mm_bus_rd_latency(1, mm_clk);
+      rd_err_cnt_arr(I) <= TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0));
       ASSERT v_N = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong error count" SEVERITY ERROR;
     END LOOP;
     proc_common_wait_some_cycles(dp_clk, 10);
+
+    -- check cnt clear
+    proc_mem_mm_bus_wr(c_mm_addr_dp_clear, 1, mm_clk, reg_mosi);
+    proc_common_wait_cross_clock_domain_latency(mm_clk, dp_clk);
+
+    proc_mem_mm_bus_rd(c_mm_addr_dp_discarded_cnt, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    ASSERT 0 = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong cleared total discarded block count" SEVERITY ERROR;
+    proc_mem_mm_bus_rd(c_mm_addr_dp_blk_cnt, mm_clk, reg_miso, reg_mosi);
+    proc_mem_mm_bus_rd_latency(1, mm_clk);
+    ASSERT 0 = TO_UINT(reg_miso.rddata(c_word_w-1 DOWNTO 0)) REPORT "Wrong cleared total block count" SEVERITY ERROR;
+    proc_common_wait_some_cycles(dp_clk, 10);
+
     tb_end <= '1';
     WAIT;
   END PROCESS;
   
-  tb_end <= '0', stimuli_end AFTER (1 + 10*c_dut_pipeline)*c_dp_clk_period;
-  
 END tb;
-- 
GitLab