From eba962b7001f2884d3f28128eaea0ad09ed96682 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Tue, 29 Apr 2025 14:32:42 +0200
Subject: [PATCH] Verify g_dump_nof_pages = 0.

---
 .../tb_lofar2_unb2c_sdp_station_tbuf_one.vhd  | 133 ++++++++++--------
 ...b_tb_lofar2_unb2c_sdp_station_tbuf_one.vhd |   6 +-
 .../sdp/src/vhdl/sdp_tbuf_reader.vhd          |  10 +-
 3 files changed, 81 insertions(+), 68 deletions(-)

diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_one/tb_lofar2_unb2c_sdp_station_tbuf_one.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_one/tb_lofar2_unb2c_sdp_station_tbuf_one.vhd
index 1ea793cfff..338e89fe3f 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_one/tb_lofar2_unb2c_sdp_station_tbuf_one.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_one/tb_lofar2_unb2c_sdp_station_tbuf_one.vhd
@@ -98,9 +98,9 @@ entity tb_lofar2_unb2c_sdp_station_tbuf_one is
     g_rs_nof_periods_per_block : real := 1.17;  -- number of WG periods per rs_block for WG in g_sp
     g_dump_inter_packet_gap    : natural := 0;
     g_dump_page_offset         : natural := 1;  -- offset relative to recorded_first_page
-    g_dump_nof_pages           : natural := 2;  -- g_dump_page_offset + g_dump_nof_pages <= c_nof_pages_in_buffer, else
+    g_dump_nof_pages           : natural := 1;  -- g_dump_page_offset + g_dump_nof_pages <= c_nof_pages_in_buffer, else
                                                 -- there will occur read RSN errors for pages that are not available
-    g_dump_enables             : std_logic_vector(c_sdp_A_pn - 1 downto 0) := "000010"
+    g_dump_enables             : std_logic_vector(c_sdp_A_pn - 1 downto 0) := "100010"
   );
   port (
     tb_end : out std_logic
@@ -1154,50 +1154,52 @@ begin
     proc_common_wait_cross_clock_domain_latency(
         c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency * 2);
 
-    -- Time dump begin
-    read_busy <= '1';
-    v_Begin := NOW / c_1ns;
-    proc_common_wait_some_cycles(tb_clk, 1);
-
-    -- Read back enabled dump
-    mmf_mm_bus_rd(c_mm_file_reg_tbuf, 16, rd_data_control, tb_clk);
-    tbuf_registers_rd.dump_enables <= rd_data_control(c_sdp_A_pn - 1 downto 0);
-    proc_common_wait_some_cycles(tb_clk, 1);
-    assert to_uint(tbuf_registers_rd.dump_enables) = to_uint(tbuf_registers_wr.dump_enables)
-      report c_tb_str & "Wrong tbuf_registers_rd.dump_enables enabled"
-      severity ERROR;
-    print_str(c_tb_str & "tbuf_registers_rd.dump_enables = " & slv_to_str(tbuf_registers_rd.dump_enables));
-
-    -- Read DDR4 read FIFO status
-    proc_common_wait_some_cycles(ext_clk, 10);
-    proc_read_ddr4_rd_fifo_status(tb_clk, rd_data_fifo, ddr_rd_fifo_used, ddr_rd_fifo_full);
-
-    ----------------------------------------------------------------------------
-    -- Wait until dump is done
-    ----------------------------------------------------------------------------
-    mmf_mm_wait_until_value(
-        c_mm_file_reg_tbuf, 17,  -- read dump_done
-        "UNSIGNED", rd_data_dump_done, "=", 1,  -- this is the wait until condition
-        c_T_rd_interval, ext_clk);
-    tbuf_registers_ro.dump_done <= rd_data_dump_done(0);
-    proc_common_wait_some_cycles(tb_clk, 1);
+    if g_dump_nof_pages > 0 then
+      -- Time dump begin
+      read_busy <= '1';
+      v_Begin := NOW / c_1ns;
+      proc_common_wait_some_cycles(tb_clk, 1);
 
-    -- Time dump end
-    read_busy <= '0';
-    v_End := NOW / c_1ns;
-    v_Period := real(v_End - v_Begin);  -- dump time in ns
-    v_dump_rate_Gbps := real(c_dump_total_nof_packets * c_sdp_W_ant * g_rs_block_size) / v_Period;
-    dump_rate_Gbps <= v_dump_rate_Gbps;
-
-    -- Verify dump rate over sufficient number of packets
-    if c_dump_total_nof_packets > 5 and g_ddr_access_rate_pct = 100 then
-      -- . use almost_equal(a/b, 1.0, max_ratio) to verify that a and b differ less than max_ratio/100 percent
-      assert almost_equal(v_dump_rate_Gbps / c_exp_dump_rate_Gbps, 1.0, c_dump_rate_delta)
-        report c_tb_str & "Wrong dump rate"
+      -- Read back enabled dump
+      mmf_mm_bus_rd(c_mm_file_reg_tbuf, 16, rd_data_control, tb_clk);
+      tbuf_registers_rd.dump_enables <= rd_data_control(c_sdp_A_pn - 1 downto 0);
+      proc_common_wait_some_cycles(tb_clk, 1);
+      assert to_uint(tbuf_registers_rd.dump_enables) = to_uint(tbuf_registers_wr.dump_enables)
+        report c_tb_str & "Wrong tbuf_registers_rd.dump_enables enabled"
         severity ERROR;
+      print_str(c_tb_str & "tbuf_registers_rd.dump_enables = " & slv_to_str(tbuf_registers_rd.dump_enables));
+
+      -- Read DDR4 read FIFO status
+      proc_common_wait_some_cycles(ext_clk, 10);
+      proc_read_ddr4_rd_fifo_status(tb_clk, rd_data_fifo, ddr_rd_fifo_used, ddr_rd_fifo_full);
+
+      ----------------------------------------------------------------------------
+      -- Wait until dump is done
+      ----------------------------------------------------------------------------
+      mmf_mm_wait_until_value(
+          c_mm_file_reg_tbuf, 17,  -- read dump_done
+          "UNSIGNED", rd_data_dump_done, "=", 1,  -- this is the wait until condition
+          c_T_rd_interval, ext_clk);
+      tbuf_registers_ro.dump_done <= rd_data_dump_done(0);
+      proc_common_wait_some_cycles(tb_clk, 1);
+
+      -- Time dump end
+      read_busy <= '0';
+      v_End := NOW / c_1ns;
+      v_Period := real(v_End - v_Begin);  -- dump time in ns
+      v_dump_rate_Gbps := real(c_dump_total_nof_packets * c_sdp_W_ant * g_rs_block_size) / v_Period;
+      dump_rate_Gbps <= v_dump_rate_Gbps;
+
+      -- Verify dump rate over sufficient number of packets
+      if c_dump_total_nof_packets > 5 and g_ddr_access_rate_pct = 100 then
+        -- . use almost_equal(a/b, 1.0, max_ratio) to verify that a and b differ less than max_ratio/100 percent
+        assert almost_equal(v_dump_rate_Gbps / c_exp_dump_rate_Gbps, 1.0, c_dump_rate_delta)
+          report c_tb_str & "Wrong dump rate"
+          severity ERROR;
+      end if;
+      print_str(c_tb_str & "Dump rate = " & real_to_str(v_dump_rate_Gbps, 4, 2) & " Gbps" &
+                " (Expected " & real_to_str(c_exp_dump_rate_Gbps, 4, 2) & " Gbps)");
     end if;
-    print_str(c_tb_str & "Dump rate = " & real_to_str(v_dump_rate_Gbps, 4, 2) & " Gbps" &
-              " (Expected " & real_to_str(c_exp_dump_rate_Gbps, 4, 2) & " Gbps)");
 
     -- Wait some time for latency in sdp_tbuf_output and 10GbE Tx - Rx network
     proc_common_wait_some_cycles(ext_clk, g_rs_block_size * 4);
@@ -1327,26 +1329,33 @@ begin
     variable v_bool       : boolean;
   begin
     wait until rising_edge(ext_clk);
-    -- Count rx_dump_sosi packets at sop
-    if rx_dump_sosi.sop = '1' then
-      rx_dump_packet_cnt <= rx_dump_packet_cnt + 1;
-
-      -- Determine expected antenna_input_index assuming c_dump_nof_packets_per_ai per ai
-      v_dump_index := rx_dump_packet_cnt / c_dump_nof_packets_per_ai;
-      v_ai_local := c_dump_ai_indices(v_dump_index);
-      exp_dump_ai <= c_ai_offset + v_ai_local;
-
-      -- Determine expected RSN assuming c_dump_nof_packets_per_ai per ai
-      v_time_index := rx_dump_packet_cnt mod c_dump_nof_packets_per_ai;
-      exp_dp_rsn <= to_uint(tbuf_registers_wr.dump_start_rsn) + v_time_index * g_rs_block_size;
-    end if;
-    -- Verify header at eop
-    if rx_dump_sosi.eop = '1' then
-      v_bool := func_sdp_tbuf_verify_cep_header(rx_dump_header, exp_dump_header);
+    if c_dump_nof_packets_per_ai > 0 then
+      -- Count rx_dump_sosi packets at sop
+      if rx_dump_sosi.sop = '1' then
+        rx_dump_packet_cnt <= rx_dump_packet_cnt + 1;
+
+        -- Determine expected antenna_input_index assuming c_dump_nof_packets_per_ai per ai
+        v_dump_index := rx_dump_packet_cnt / c_dump_nof_packets_per_ai;
+        v_ai_local := c_dump_ai_indices(v_dump_index);
+        exp_dump_ai <= c_ai_offset + v_ai_local;
+
+        -- Determine expected RSN assuming c_dump_nof_packets_per_ai per ai
+        v_time_index := rx_dump_packet_cnt mod c_dump_nof_packets_per_ai;
+        exp_dp_rsn <= to_uint(tbuf_registers_wr.dump_start_rsn) + v_time_index * g_rs_block_size;
+      end if;
+      -- Verify header at eop
+      if rx_dump_sosi.eop = '1' then
+        v_bool := func_sdp_tbuf_verify_cep_header(rx_dump_header, exp_dump_header);
+      end if;
+      -- View variables in Wave Window
+      dump_index <= v_dump_index;
+      time_index <= v_time_index;
+    else
+      -- Expect no dump packets when g_dump_nof_pages = 0
+      assert rx_dump_sosi.sop = '0'
+        report c_tb_str & "Wrong unexpected rx_dump_sosi packet for g_dump_nof_pages = 0"
+        severity ERROR;
     end if;
-    -- View variables in Wave Window
-    dump_index <= v_dump_index;
-    time_index <= v_time_index;
   end process;
 
   -----------------------------------------------------------------------------
diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_one/tb_tb_lofar2_unb2c_sdp_station_tbuf_one.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_one/tb_tb_lofar2_unb2c_sdp_station_tbuf_one.vhd
index 842467a3f5..6d65f8569b 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_one/tb_tb_lofar2_unb2c_sdp_station_tbuf_one.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_one/tb_tb_lofar2_unb2c_sdp_station_tbuf_one.vhd
@@ -35,7 +35,7 @@ end tb_tb_lofar2_unb2c_sdp_station_tbuf_one;
 
 architecture tb of tb_tb_lofar2_unb2c_sdp_station_tbuf_one is
   -- Multi tb
-  constant c_tb_w       : natural := 10;  -- sufficiently long to fit all tb instances
+  constant c_tb_w       : natural := 11;  -- sufficiently long to fit all tb instances
   constant c_tb_end_vec : std_logic_vector(c_tb_w - 1 downto 0) := (others => '1');
 
   signal tb_end_vec   : std_logic_vector(c_tb_w - 1 downto 0) := c_tb_end_vec;  -- best view as hex in Wave Window
@@ -109,6 +109,10 @@ begin
       generic map(false, 9, false, false, false, false, 3, 100, 256, 100, 10, 1.17, 0, 6, 1, "000010")
       port map (tb_end_vec(9));
 
+  u_dump_zero_pages : entity work.tb_lofar2_unb2c_sdp_station_tbuf_one
+      generic map(false, 10, false, false, false, false, 3, 100, 256, 102, 10, 1.0, 0, 1, 0, "100010")
+      port map (tb_end_vec(10));
+
   tb_end <= '1' after 1 us when tb_end_vec = c_tb_end_vec else '0';
   proc_common_stop_simulation(tb_end);
 end tb;
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_tbuf_reader.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_tbuf_reader.vhd
index df2f73a7d7..5bc156427f 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_tbuf_reader.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_tbuf_reader.vhd
@@ -336,17 +336,17 @@ begin
         v.dump_done := '0';
         v.dump_start_rsn := reg_dump_start_rsn_rw;
         v.dump_start_page := reg_dump_start_page_rw;
+        v.dump_nof_pages := reg_dump_nof_pages_rw;
         if v.dump_start_page >= c_nof_pages_in_buffer then
-          -- Force to recovery value within buffer range, this will lead to read RSN errors due to mismatch with
-          -- dump_start_rsn.
+          -- Start page not in buffer range, cannot do dump.
           v.dump_start_page := 0;
+          v.dump_nof_pages := 0;
         end if;
-        v.dump_nof_pages := reg_dump_nof_pages_rw;
         if v.dump_nof_pages >= c_nof_pages_in_buffer then
-          -- Limit to buffer size
+          -- Limit nof pages to buffer size
           v.dump_nof_pages := c_nof_pages_in_buffer;
         end if;
-        if dump_en = '1' then
+        if dump_en = '1' and r.dump_nof_pages > 0 then
           v.latency_cnt := c_start_latency;
           v.fsm := s_dump_start;
         end if;
-- 
GitLab