From 3c95ef11ee6f07265af6ba896fad55a139b8f569 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Thu, 4 Aug 2022 11:46:38 +0200
Subject: [PATCH] Support and use prev_crosslets_info_rec.

---
 .../sdp/src/vhdl/node_sdp_correlator.vhd      | 14 +++--
 .../src/vhdl/sdp_crosslets_subband_select.vhd | 45 ++++++++++----
 .../sdp/src/vhdl/sdp_statistics_offload.vhd   | 23 +++++---
 .../vhdl/tb_sdp_crosslets_subband_select.vhd  | 58 +++++++++++--------
 .../sdp/tb/vhdl/tb_sdp_statistics_offload.vhd |  8 +--
 5 files changed, 92 insertions(+), 56 deletions(-)

diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd
index 43c17b7a77..17f3ac609a 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_correlator.vhd
@@ -131,7 +131,7 @@ ARCHITECTURE str OF node_sdp_correlator IS
   SIGNAL crosslets_cipo_arr            : t_mem_cipo_arr(g_P_sq-1 DOWNTO 0) := (OTHERS => c_mem_cipo_rst); 
   SIGNAL mon_xst_udp_sosi_arr          : t_dp_sosi_arr(0 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
 
-  SIGNAL crosslets_info                : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0);
+  SIGNAL prev_crosslets_info_rec       : t_sdp_crosslets_info;
   SIGNAL nof_crosslets_reg             : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0);
   SIGNAL nof_crosslets                 : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0);
 BEGIN
@@ -184,7 +184,8 @@ BEGIN
     reg_bsn_sync_scheduler_xsub_mosi => reg_bsn_sync_scheduler_xsub_copi,
     reg_bsn_sync_scheduler_xsub_miso => reg_bsn_sync_scheduler_xsub_cipo,
                             
-    out_crosslets_info => crosslets_info
+    cur_crosslets_info_rec => OPEN,
+    prev_crosslets_info_rec => prev_crosslets_info_rec
   );
  
   -- Use xsel_sosi as local bsn and sync reference since the sync
@@ -425,6 +426,7 @@ BEGIN
     in_reg   => nof_crosslets,
     out_reg  => nof_crosslets_reg
   );
+
   -- Force nof crosslets to max nof crosslets if a higher value is written or to 1 if a lower value is written via MM.
   nof_crosslets <= TO_UVEC(1, c_sdp_nof_crosslets_reg_w) WHEN TO_UINT(nof_crosslets_reg) < 1 ELSE 
                    nof_crosslets_reg WHEN TO_UINT(nof_crosslets_reg) <= c_sdp_N_crosslets_max ELSE 
@@ -434,6 +436,7 @@ BEGIN
   -- XST UDP offload 
   ---------------------------------------------------------------
   xst_udp_sosi <= mon_xst_udp_sosi_arr(0);
+
   u_sdp_xst_udp_offload: ENTITY work.sdp_statistics_offload
   GENERIC MAP (
     g_statistics_type          => "XST",
@@ -472,9 +475,10 @@ BEGIN
     gn_index       => TO_UINT(gn_id),
     ring_info      => ring_info,
     sdp_info       => sdp_info,
-    weighted_subbands_flag  => '1',  -- because XSub uses in_sosi_arr = fsub_sosi_arr, so weighted subbands
-    nof_crosslets  => nof_crosslets,
-    crosslets_info => crosslets_info
+    weighted_subbands_flag => '1',  -- because XSub uses in_sosi_arr = fsub_sosi_arr, so weighted subbands
+
+    nof_crosslets      => nof_crosslets,
+    crosslets_info_rec => prev_crosslets_info_rec
   );
 
 END str;
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd
index 2cc902a393..d76f1d6833 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_crosslets_subband_select.vhd
@@ -24,8 +24,15 @@
 -- Purpose: 
 -- Select subbands from incoming blocks
 -- Description:
--- The Crosslet subband select selects N_crosslets from each incoming block. Per 
--- crosslet there are S_pn = 12 subbands, one from each signal input of the PN.
+--   The Crosslet subband select selects N_crosslets from each incoming block.
+--   Per crosslet there are S_pn = 12 subbands, one from each signal input of
+--   the PN.
+--   The cur_crosslets_info is valid at the out_sosi.sync and for the entire
+--   sync interval. The cur_crosslets_info identifies the crosslets that are
+--   being calculated during this out_sosi.sync interval.
+--   The prev_crosslets_info identifies the crosslets that were calculated
+--   during the previous out_sosi.sync interval, so the XST for those crosslets
+--   are then pending to be offloaded.
 -- Remark:
 -- . See L5 SDPFW Design Document: Subband Correlator
 --   Link: https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L5+SDPFW+Design+Document%3A+Subband+Correlator
@@ -60,13 +67,13 @@ ENTITY sdp_crosslets_subband_select IS
     reg_bsn_sync_scheduler_xsub_mosi : IN  t_mem_mosi := c_mem_mosi_rst;
     reg_bsn_sync_scheduler_xsub_miso : OUT t_mem_miso := c_mem_miso_rst;
        
-    out_crosslets_info : OUT STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0)
+    cur_crosslets_info_rec  : OUT t_sdp_crosslets_info;
+    prev_crosslets_info_rec : OUT t_sdp_crosslets_info
   );
 END sdp_crosslets_subband_select;
 
 ARCHITECTURE str OF sdp_crosslets_subband_select IS
 
-
   CONSTANT c_crosslets_info_dly  : NATURAL := 1;
   CONSTANT c_col_select_addr_w   : NATURAL := ceil_log2(c_sdp_Q_fft * c_sdp_N_sub);
   CONSTANT c_row_select_slv_w    : NATURAL := ceil_log2(c_sdp_P_pfb);
@@ -104,13 +111,13 @@ ARCHITECTURE str OF sdp_crosslets_subband_select IS
   SIGNAL crosslets_info_reg    : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0');
   SIGNAL crosslets_info_reg_in : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0');
   SIGNAL active_crosslets_info : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0');
-  SIGNAL i_out_crosslets_info  : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0');
+  SIGNAL cur_crosslets_info    : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0');
+  SIGNAL prev_crosslets_info   : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0');
 
   -- Map crosslets_info slv to record for easier view in Wave window
   SIGNAL crosslets_info_rec        : t_sdp_crosslets_info;
   SIGNAL crosslets_info_rec_inout  : t_sdp_crosslets_info;
   SIGNAL active_crosslets_info_rec : t_sdp_crosslets_info;
-  SIGNAL out_crosslets_info_rec    : t_sdp_crosslets_info;
 
 BEGIN
 
@@ -160,10 +167,10 @@ BEGIN
     out_reg  => crosslets_info_reg
   );
 
-  p_set_unused_crosslets : PROCESS(i_out_crosslets_info)
+  p_set_unused_crosslets : PROCESS(cur_crosslets_info)
   BEGIN
     -- MM readback the currently active crosslets info, instead of the initial MM written crosslets_info_reg
-    crosslets_info_reg_in <= i_out_crosslets_info; -- Always use crosslets info 6:0 + step(@ index 15)
+    crosslets_info_reg_in <= cur_crosslets_info; -- Always use crosslets info 6:0 + step(@ index 15)
     -- Set crosslets 14:7 to -1
     FOR I IN g_N_crosslets TO c_sdp_mm_reg_crosslets_info.nof_dat - 2 LOOP
       crosslets_info_reg_in((I+1) * c_sdp_crosslets_index_w - 1 DOWNTO I * c_sdp_crosslets_index_w ) <= TO_SVEC(-1, c_sdp_crosslets_index_w);
@@ -319,7 +326,7 @@ BEGIN
   END GENERATE;
 
   -- pipeline for alignment with sync
-  u_common_pipeline : ENTITY common_lib.common_pipeline
+  u_common_pipeline_cur : ENTITY common_lib.common_pipeline
   GENERIC MAP(
     g_pipeline  => c_crosslets_info_dly,
     g_in_dat_w  => c_sdp_crosslets_info_reg_w,
@@ -330,10 +337,22 @@ BEGIN
     clk => dp_clk,
     in_en => row_sosi.sync,
     in_dat => active_crosslets_info,
-    out_dat => i_out_crosslets_info
+    out_dat => cur_crosslets_info
   );
 
-  out_crosslets_info <= i_out_crosslets_info;
+  u_common_pipeline_prev : ENTITY common_lib.common_pipeline
+  GENERIC MAP(
+    g_pipeline  => c_crosslets_info_dly,
+    g_in_dat_w  => c_sdp_crosslets_info_reg_w,
+    g_out_dat_w => c_sdp_crosslets_info_reg_w
+  )
+  PORT MAP(
+    rst => dp_rst,
+    clk => dp_clk,
+    in_en => row_sosi.sync,
+    in_dat => cur_crosslets_info,
+    out_dat => prev_crosslets_info
+  );
 
   ---------------------------------------------------------------
   -- Out sosi pipeline
@@ -355,6 +374,8 @@ BEGIN
   crosslets_info_rec        <= func_sdp_map_crosslets_info(crosslets_info_reg);
   crosslets_info_rec_inout  <= func_sdp_map_crosslets_info(crosslets_info_reg_in);
   active_crosslets_info_rec <= func_sdp_map_crosslets_info(active_crosslets_info);
-  out_crosslets_info_rec    <= func_sdp_map_crosslets_info(i_out_crosslets_info);
+
+  cur_crosslets_info_rec    <= func_sdp_map_crosslets_info(cur_crosslets_info);
+  prev_crosslets_info_rec   <= func_sdp_map_crosslets_info(prev_crosslets_info);
 
 END str;
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
index 1338fe6d15..d37221c8c5 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
@@ -156,8 +156,9 @@ ENTITY sdp_statistics_offload IS
     ring_info               : IN t_ring_info := c_ring_info_rst;  -- only needed for XST
     sdp_info                : IN t_sdp_info;
     weighted_subbands_flag  : IN STD_LOGIC := '0';
+
     nof_crosslets           : IN STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0) := (OTHERS => '0');
-    crosslets_info          : IN STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0')
+    crosslets_info_rec      : IN t_sdp_crosslets_info := c_sdp_crosslets_info_rst
   );
 END sdp_statistics_offload;
 
@@ -202,8 +203,7 @@ ARCHITECTURE str OF sdp_statistics_offload IS
     crosslets_info_rec   : t_sdp_crosslets_info;
   END RECORD;
 
-  CONSTANT c_crosslets_info_rst : t_sdp_crosslets_info := (offset_arr => (OTHERS => 0), step => 0);
-  CONSTANT c_reg_rst            : t_reg := (0, 0, '0', '0', (OTHERS => '0'), '0', 0, 0, 0, 0, 0, 0, 0, 0, c_crosslets_info_rst);
+  CONSTANT c_reg_rst : t_reg := (0, 0, '0', '0', (OTHERS => '0'), '0', 0, 0, 0, 0, 0, 0, 0, 0, c_sdp_crosslets_info_rst);
 
   SIGNAL r     : t_reg;
   SIGNAL nxt_r : t_reg;
@@ -239,6 +239,8 @@ ARCHITECTURE str OF sdp_statistics_offload IS
 
   SIGNAL bsn_at_sync              : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0) := (OTHERS => '0');
   SIGNAL dp_header_info           : STD_LOGIC_VECTOR(1023 DOWNTO 0):= (OTHERS => '0');
+  SIGNAL r_dp_header_sop          : STD_LOGIC;
+  SIGNAL r_dp_header_rec          : t_sdp_stat_header;
 
   -- Debug signals for view in Wave window
   SIGNAL dbg_c_marker                    : NATURAL := c_marker;
@@ -353,7 +355,7 @@ BEGIN
 
   data_id_slv <= func_sdp_map_stat_data_id(g_statistics_type, data_id_rec);
 
-  p_control_packet_offload : PROCESS(r, in_sosi, local_si_offset, trigger_offload, nof_crosslets, crosslets_info, nof_packets, dp_sop, dp_header_info)
+  p_control_packet_offload : PROCESS(r, in_sosi, nof_crosslets, crosslets_info_rec, trigger_offload, dp_sop, dp_header_info, nof_packets)  -- in order of appearance
     VARIABLE v       : t_reg;
     VARIABLE v_index : NATURAL;
   BEGIN
@@ -376,19 +378,18 @@ BEGIN
       END IF;
     END IF;
 
-
-    -- For XST offload capture nof_crosslets and crosslets_info at in_sosi.sync,
+    -- For XST offload capture nof_crosslets and crosslets_info_rec at in_sosi.sync,
     -- to make sure they do not change during packets offload.
     -- . The sdp_crosslets_subband_select.vhd in [2] takes care that
-    --   nof_crosslets and crosslets_info are valid at the xsel_sosi.sync. The
+    --   nof_crosslets and crosslets_info_rec are valid at the xsel_sosi.sync. The
     --   mmp_dp_bsn_align_v2 in [2] then aligns the local xsel_sosi with the
     --   remote data and passes on the sync. After some latency the sync
     --   arrives at the sdp_statistics_offload. This latency is very short
-    --   compared to the sync period, so the nof_crosslets and crosslet_info
+    --   compared to the sync period, so the nof_crosslets and crosslets_info_rec
     --   are still valid at the in_sosi.sync.
     IF in_sosi.sync = '1' THEN
       v.nof_crosslets      := TO_UINT(nof_crosslets);
-      v.crosslets_info_rec := func_sdp_map_crosslets_info(crosslets_info);
+      v.crosslets_info_rec := crosslets_info_rec;
     END IF;
 
     -- The trigger_offload occurs nof_cycles_dly after the in_sosi.sync and the
@@ -570,6 +571,10 @@ BEGIN
     hdr_fields_in_arr(0) => r.dp_header_info
   );
 
+  -- Debug signal, r_dp_header_rec must be available at the r_dp_header_sop
+  r_dp_header_sop <= dp_offload_snk_in.sop;
+  r_dp_header_rec <= func_sdp_map_stat_header(r.dp_header_info);
+
   out_sosi <= udp_sosi;
 
   u_bsn_mon_udp : ENTITY dp_lib.mms_dp_bsn_monitor_v2
diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd
index d58cd1b58e..be9550e00c 100644
--- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_crosslets_subband_select.vhd
@@ -30,7 +30,7 @@
 -- Description: The tb starts the dut by writing a scheduled bsn to the bsn_scheduler
 -- via MM. The offsets and step are configured using MM. The dut makes the subband 
 -- selection based on the MM configuration and N_crosslets. The TB then verifies out_sosi 
--- and out_crosslets_info of the dut by comparing it to the expected output.
+-- and cur_crosslets_info of the dut by comparing it to the expected output.
 
 LIBRARY IEEE, common_lib, dp_lib;
 USE IEEE.std_logic_1164.ALL;
@@ -94,10 +94,10 @@ ARCHITECTURE tb OF tb_sdp_crosslets_subband_select IS
   
   SIGNAL out_sosi           : t_dp_sosi;
 
-  SIGNAL exp_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0');
-  SIGNAL out_crosslets_info_slv : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := (OTHERS => '0');
-  SIGNAL exp_crosslets_info_rec : t_sdp_crosslets_info;
-  SIGNAL out_crosslets_info_rec : t_sdp_crosslets_info;
+  SIGNAL exp_cur_crosslets_info_rec   : t_sdp_crosslets_info;
+  SIGNAL cur_crosslets_info_rec       : t_sdp_crosslets_info;
+  SIGNAL exp_prev_crosslets_info_rec  : t_sdp_crosslets_info;
+  SIGNAL prev_crosslets_info_rec      : t_sdp_crosslets_info;
 
 BEGIN
 
@@ -141,7 +141,7 @@ BEGIN
     END LOOP;
     ASSERT rd_crosslet_step = 0 REPORT "Wrong crosslet step after rst." SEVERITY ERROR;
 
-    -- b) Read crosslet_info in every sync interval
+    -- b) Read crosslets_info in every sync interval
     WHILE TRUE LOOP
       proc_common_wait_until_hi_lo(clk, out_sosi.sync);
       proc_common_wait_cross_clock_domain_latency(c_clk_period, c_mm_clk_period);
@@ -157,9 +157,9 @@ BEGIN
       proc_common_wait_some_cycles(mm_clk, 1);
       -- Verify that readback crosslet info is active crosslets_info
       FOR I IN 0 TO c_N_crosslets-1 LOOP
-        ASSERT rd_crosslet_offsets(I) = exp_crosslets_info_rec.offset_arr(I) REPORT "Wrong active crosslet offset in output sync interval." SEVERITY ERROR;
+        ASSERT rd_crosslet_offsets(I) = exp_cur_crosslets_info_rec.offset_arr(I) REPORT "Wrong active crosslet offset in output sync interval." SEVERITY ERROR;
       END LOOP;
-      ASSERT rd_crosslet_step = exp_crosslets_info_rec.step REPORT "Wrong active crosslet step in output sync interval." SEVERITY ERROR;
+      ASSERT rd_crosslet_step = exp_cur_crosslets_info_rec.step REPORT "Wrong active crosslet step in output sync interval." SEVERITY ERROR;
     END LOOP;
 
     WAIT;
@@ -216,19 +216,28 @@ BEGIN
     VARIABLE v_col : NATURAL := 0;
     VARIABLE v_row : NATURAL := 0;
     VARIABLE v_offset : NATURAL := 0; 
-    VARIABLE v_sync_ix : NATURAL := 0;
+    VARIABLE v_sync_ix : NATURAL := 0;  -- ix = index
     VARIABLE v_k : NATURAL := 0;
   BEGIN
     FOR I IN 0 TO c_nof_sync*c_nof_block_per_sync-1 LOOP
       v_sync_ix := I / c_nof_block_per_sync;
       exp_sosi <= c_dp_sosi_rst;
+
+      -- In a tb it is ok and it can be handy to use rising_edge() on a combinatorial signal
       WAIT UNTIL rising_edge(out_sosi.sop);
 
-      exp_crosslets_info_slv(c_sdp_crosslets_info_reg_w-1 DOWNTO c_sdp_crosslets_info_reg_w - c_sdp_crosslets_index_w) <= TO_UVEC(c_crosslet_step, c_sdp_crosslets_index_w);
+      -- Current sync interval crosslets_info
+      exp_cur_crosslets_info_rec.step <= c_crosslet_step;
       FOR C IN 0 TO c_nof_ch_sel_col-1 LOOP
-        exp_crosslets_info_slv((C+1)*c_sdp_crosslets_index_w-1 DOWNTO C*c_sdp_crosslets_index_w) <= TO_UVEC(c_crosslet_offsets(C) + v_sync_ix * c_crosslet_step, c_sdp_crosslets_index_w);
+        exp_cur_crosslets_info_rec.offset_arr(C) <= c_crosslet_offsets(C) + v_sync_ix * c_crosslet_step;
       END LOOP;
 
+      -- Previous sync interval crosslets_info
+      IF out_sosi.sync = '1' THEN
+        exp_prev_crosslets_info_rec <= exp_cur_crosslets_info_rec;
+      END IF;
+
+      -- Crosslet data
       FOR J IN 0 TO c_nof_ch_sel-1 LOOP
         v_offset := J / (c_nof_ch_sel_col*c_nof_ch_sel_row);
         v_col := J MOD c_nof_ch_sel_col;
@@ -241,7 +250,6 @@ BEGIN
           exp_sosi.sop <= '1';
           IF I MOD c_nof_block_per_sync = 0 THEN
             exp_sosi.sync <= '1';
-
           END IF;
         ELSIF j = c_nof_ch_sel-1 THEN 
           exp_sosi.eop <= '1';
@@ -250,8 +258,8 @@ BEGIN
         exp_sosi.re <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA(   (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_crosslet_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0));
         exp_sosi.im <= RESIZE_DP_DSP_DATA(TO_DP_DSP_DATA(1+ (I + c_nof_block_dly) * c_nof_ch_in + v_k + c_nof_ch_sel_col*c_crosslet_offsets(v_offset) + v_col + v_row*2**5)(c_sdp_W_crosslet-1 DOWNTO 0));
         proc_common_wait_some_cycles(clk, 1);
-
       END LOOP;
+
       exp_sosi <= c_dp_sosi_rst;
     END LOOP;
     WAIT;
@@ -260,14 +268,17 @@ BEGIN
   p_verify_out_data : PROCESS(clk)
   BEGIN
     IF rising_edge(clk) THEN
-      ASSERT out_sosi.valid = exp_sosi.valid      REPORT "Wrong out_sosi.valid"      SEVERITY ERROR;
-      ASSERT out_sosi.sop   = exp_sosi.sop        REPORT "Wrong out_sosi.sop"        SEVERITY ERROR;
-      ASSERT out_sosi.eop   = exp_sosi.eop        REPORT "Wrong out_sosi.eop"        SEVERITY ERROR;
-      ASSERT out_sosi.sync  = exp_sosi.sync       REPORT "Wrong out_sosi.sync"       SEVERITY ERROR;
-      ASSERT out_crosslets_info_slv = exp_crosslets_info_slv  REPORT "Wrong out_crosslets_info_slv"  SEVERITY ERROR;
+      ASSERT out_sosi.valid = exp_sosi.valid REPORT "Wrong out_sosi.valid" SEVERITY ERROR;
+      ASSERT out_sosi.sop   = exp_sosi.sop   REPORT "Wrong out_sosi.sop"   SEVERITY ERROR;
+      ASSERT out_sosi.eop   = exp_sosi.eop   REPORT "Wrong out_sosi.eop"   SEVERITY ERROR;
+      ASSERT out_sosi.sync  = exp_sosi.sync  REPORT "Wrong out_sosi.sync"  SEVERITY ERROR;
+
+      ASSERT cur_crosslets_info_rec  = exp_cur_crosslets_info_rec  REPORT "Wrong cur_crosslets_info"  SEVERITY ERROR;
+      ASSERT prev_crosslets_info_rec = exp_prev_crosslets_info_rec REPORT "Wrong prev_crosslets_info" SEVERITY ERROR;
+
       IF exp_sosi.valid = '1' THEN
-        ASSERT out_sosi.re  = exp_sosi.re    REPORT "Wrong out_sosi.re"    SEVERITY ERROR;
-        ASSERT out_sosi.im  = exp_sosi.im    REPORT "Wrong out_sosi.im"    SEVERITY ERROR;
+        ASSERT out_sosi.re  = exp_sosi.re REPORT "Wrong out_sosi.re" SEVERITY ERROR;
+        ASSERT out_sosi.im  = exp_sosi.im REPORT "Wrong out_sosi.im" SEVERITY ERROR;
       END IF;
     END IF;
   END PROCESS;
@@ -294,11 +305,8 @@ BEGIN
     in_sosi_arr => in_sosi_arr,
     out_sosi    => out_sosi,
 
-    out_crosslets_info => out_crosslets_info_slv
+    cur_crosslets_info_rec  => cur_crosslets_info_rec,
+    prev_crosslets_info_rec => prev_crosslets_info_rec
   );
  
-  -- Map crosslets_info slv to record for easier view in Wave window
-  exp_crosslets_info_rec <= func_sdp_map_crosslets_info(exp_crosslets_info_slv);
-  out_crosslets_info_rec <= func_sdp_map_crosslets_info(out_crosslets_info_slv);
-
 END tb;
diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
index 1193efc51d..d44b39a143 100644
--- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
@@ -174,7 +174,6 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
 
   SIGNAL in_sosi                 : t_dp_sosi := c_dp_sosi_rst;
   SIGNAL in_crosslets_info_rec   : t_sdp_crosslets_info;
-  SIGNAL in_crosslets_info_slv   : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0);
 
   SIGNAL sdp_offload_data        : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- 32 bit
   SIGNAL sdp_offload_sosi        : t_dp_sosi;
@@ -309,8 +308,6 @@ BEGIN
     WAIT;
   END PROCESS;
 
-  in_crosslets_info_slv <= func_sdp_map_crosslets_info(in_crosslets_info_rec);
-
   -- Enable the statistics offload when input is running
   p_enable_trigger : PROCESS
   BEGIN
@@ -660,11 +657,12 @@ BEGIN
     ring_info               => c_exp_ring_info,
     sdp_info                => c_exp_sdp_info,
     weighted_subbands_flag  => weighted_subbands_flag,
+
     nof_crosslets           => c_mm_nof_crosslets,
-    crosslets_info          => in_crosslets_info_slv
+    crosslets_info_rec      => in_crosslets_info_rec
   );
 
-  -- Check crosslet_info functions
+  -- Verify crosslets_info functions
   ASSERT c_crosslets_info_rec = func_sdp_map_crosslets_info(c_crosslets_info_slv) REPORT "Error in func_sdp_map_crosslets_info()" SEVERITY FAILURE;
 
   -- To view the 32 bit 1GbE offload data more easily in the Wave window
-- 
GitLab