From 5533e34c5cc53ad77f8151e88fa97ae428c8bb19 Mon Sep 17 00:00:00 2001
From: Reinier van der Walle <walle@astron.nl>
Date: Tue, 30 Aug 2022 14:40:50 +0200
Subject: [PATCH] processed review comments

---
 ...STURB2_2x_oversampled_filterbank_rom.ipynb |  4 +--
 .../lofar2_unb2b_sdp_station.fpga.yaml        |  8 ++---
 .../lofar2_unb2c_sdp_station.fpga.yaml        |  8 ++---
 .../vhdl/node_sdp_oversampled_filterbank.vhd  | 34 +++++++++----------
 .../lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd | 10 +++---
 .../libraries/sdp/src/vhdl/sdp_station.vhd    | 22 +++++++-----
 .../sdp/src/vhdl/sdp_statistics_offload.vhd   | 14 ++++++--
 .../libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd      |  6 ++--
 .../sdp/tb/vhdl/tb_sdp_statistics_offload.vhd | 15 +++++---
 .../tb/vhdl/tb_tb_sdp_statistics_offload.vhd  |  2 ++
 10 files changed, 71 insertions(+), 52 deletions(-)

diff --git a/applications/disturb2/model/DISTURB2_2x_oversampled_filterbank_rom.ipynb b/applications/disturb2/model/DISTURB2_2x_oversampled_filterbank_rom.ipynb
index 661929dff2..691c9f1847 100644
--- a/applications/disturb2/model/DISTURB2_2x_oversampled_filterbank_rom.ipynb
+++ b/applications/disturb2/model/DISTURB2_2x_oversampled_filterbank_rom.ipynb
@@ -14488,10 +14488,10 @@
     "N_sub        = 512\n",
     "Q_fft        = 2\n",
     "P_pfb        = 6\n",
-    "V_oversample = 2\n",
+    "R_os = 2\n",
     "unit_gain    = int(2**13)\n",
     "\n",
-    "for i in range(0,V_oversample * P_pfb):\n",
+    "for i in range(0,R_os * P_pfb):\n",
     "    f = IntelHex()    \n",
     "    for j in range(0,N_sub * Q_fft):\n",
     "        f.puts(4*j, struct.pack(\">I\", unit_gain))\n",
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml
index 1124ffd431..6e7fcd39a4 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/lofar2_unb2b_sdp_station.fpga.yaml
@@ -21,7 +21,7 @@ parameters:
   - { name: c_N_taps,               value: 16 }
   - { name: c_W_adc_jesd,           value: 16 }
   - { name: c_W_adc,                value: 14 }
-  - { name: c_V_oversample,         value: 2 }
+  - { name: c_R_os,         value: 2 }
   - { name: c_V_sample_delay,       value: 4096 }
   - { name: c_V_si_db_large,        value: 131072 }
   - { name: c_V_si_db,              value: 1024 }
@@ -203,7 +203,7 @@ peripherals:
       - REG_SI
       
   - peripheral_name: filter/fil_ppf_w
-    number_of_peripherals: c_V_oversample # Disturb uses 2x oversample
+    number_of_peripherals: c_R_os # Disturb uses 2x oversample
     peripheral_span: ceil_pow2(c_N_taps) * ceil_pow2(c_N_fft) * MM_BUS_SIZE  # number_of_ports = ceil_pow2(c_N_taps), mm_port_span = ceil_pow2(c_N_fft) words
     parameter_overrides:
       - { name: g_fil_ppf.wb_factor, value: 1 } # process at sample rate (so no parallel wideband factor)
@@ -217,7 +217,7 @@ peripherals:
       
   - peripheral_name: sdp/sdp_subband_equalizer
     parameter_overrides:
-      - { name: P_pfb, value: c_V_oversample * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
+      - { name: P_pfb, value: c_R_os * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
     mm_port_names:
       - RAM_EQUALIZER_GAINS
       
@@ -227,7 +227,7 @@ peripherals:
       
   - peripheral_name: st/st_sst_for_sdp
     parameter_overrides:
-      - { name: g_nof_instances, value: c_V_oversample * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
+      - { name: g_nof_instances, value: c_R_os * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
     mm_port_names:
       - RAM_ST_SST
       
diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/lofar2_unb2c_sdp_station.fpga.yaml b/applications/lofar2/designs/lofar2_unb2c_sdp_station/lofar2_unb2c_sdp_station.fpga.yaml
index 226536ab9f..7b65adce26 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/lofar2_unb2c_sdp_station.fpga.yaml
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/lofar2_unb2c_sdp_station.fpga.yaml
@@ -21,7 +21,7 @@ parameters:
   - { name: c_N_taps,               value: 16 }
   - { name: c_W_adc_jesd,           value: 16 }
   - { name: c_W_adc,                value: 14 }
-  - { name: c_V_oversample,         value: 2 }
+  - { name: c_R_os,                 value: 2 }
   - { name: c_V_sample_delay,       value: 4096 }
   - { name: c_V_si_db_large,        value: 131072 }
   - { name: c_V_si_db,              value: 1024 }
@@ -203,7 +203,7 @@ peripherals:
       - REG_SI
       
   - peripheral_name: filter/fil_ppf_w
-    number_of_peripherals: c_V_oversample # Disturb uses 2x oversample
+    number_of_peripherals: c_R_os # Disturb uses 2x oversample
     peripheral_span: ceil_pow2(c_N_taps) * ceil_pow2(c_N_fft) * MM_BUS_SIZE  # number_of_ports = ceil_pow2(c_N_taps), mm_port_span = ceil_pow2(c_N_fft) words
     parameter_overrides:
       - { name: g_fil_ppf.wb_factor, value: 1 } # process at sample rate (so no parallel wideband factor)
@@ -217,7 +217,7 @@ peripherals:
       
   - peripheral_name: sdp/sdp_subband_equalizer
     parameter_overrides:
-      - { name: P_pfb, value: c_V_oversample * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
+      - { name: P_pfb, value: c_R_os * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
     mm_port_names:
       - RAM_EQUALIZER_GAINS
       
@@ -227,7 +227,7 @@ peripherals:
       
   - peripheral_name: st/st_sst_for_sdp
     parameter_overrides:
-      - { name: g_nof_instances, value: c_V_oversample * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
+      - { name: g_nof_instances, value: c_R_os * c_P_pfb} # DISTURB uses 2x oversample so 2 X P_pfb
     mm_port_names:
       - RAM_ST_SST
       
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_oversampled_filterbank.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_oversampled_filterbank.vhd
index 23d6a87074..ad2e2a4f96 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_oversampled_filterbank.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_oversampled_filterbank.vhd
@@ -60,8 +60,8 @@ ENTITY node_sdp_oversampled_filterbank IS
     dp_rst        : IN  STD_LOGIC;
 
     in_sosi_arr   : IN  t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0);
-    pfb_sosi_arr  : OUT t_dp_sosi_arr(c_sdp_V_oversample * c_sdp_P_pfb-1 DOWNTO 0);
-    fsub_sosi_arr : OUT t_dp_sosi_arr(c_sdp_V_oversample * c_sdp_P_pfb-1 DOWNTO 0);
+    pfb_sosi_arr  : OUT t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0);
+    fsub_sosi_arr : OUT t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0);
     sst_udp_sosi  : OUT t_dp_sosi;
     sst_udp_siso  : IN  t_dp_siso := c_dp_siso_rst;
 
@@ -112,7 +112,7 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS
   CONSTANT c_buf            : t_c_mem := (latency  => 1,
                                           adr_w    => ceil_log2(2 * c_sdp_N_fft),
                                           dat_w    => c_nof_complex * c_halfword_w,      
-                                          nof_dat  => c_sdp_V_oversample * c_sdp_N_fft,  
+                                          nof_dat  => c_sdp_R_os * c_sdp_N_fft,  
                                           init_sl  => '0');
 
   CONSTANT c_buf_file       : STRING := "data/freq_shift_half_subband_2048x16_im_re.hex";
@@ -122,11 +122,11 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS
 
   CONSTANT c_fil_coefs_mem_addr_w : NATURAL := ceil_log2(c_sdp_N_fft * c_sdp_N_taps);
 
-  SIGNAL ram_fil_coefs_mosi_arr : t_mem_mosi_arr(c_sdp_V_oversample-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst); 
-  SIGNAL ram_fil_coefs_miso_arr : t_mem_miso_arr(c_sdp_V_oversample-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst);
+  SIGNAL ram_fil_coefs_mosi_arr : t_mem_mosi_arr(c_sdp_R_os-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst); 
+  SIGNAL ram_fil_coefs_miso_arr : t_mem_miso_arr(c_sdp_R_os-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst);
 
-  SIGNAL ram_st_sst_mosi_arr : t_mem_mosi_arr(c_sdp_V_oversample * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst);
-  SIGNAL ram_st_sst_miso_arr : t_mem_miso_arr(c_sdp_V_oversample * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst);
+  SIGNAL ram_st_sst_mosi_arr : t_mem_mosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_mem_mosi_rst);
+  SIGNAL ram_st_sst_miso_arr : t_mem_miso_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_mem_miso_rst);
 
   -- Subband statistics
   SIGNAL ram_st_offload_mosi : t_mem_mosi := c_mem_mosi_rst;
@@ -161,11 +161,11 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS
   SIGNAL wpfb_fifo_siso_arr             : t_dp_siso_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_siso_rst);
   SIGNAL wpfb_resized_sosi_2arr         : t_dp_sosi_2arr_2(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => (OTHERS => c_dp_sosi_rst));
   SIGNAL wpfb_resized_siso_2arr         : t_dp_siso_2arr_2(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => (OTHERS => c_dp_siso_rst));
-  SIGNAL subband_equalizer_in_sosi_arr  : t_dp_sosi_arr(c_sdp_V_oversample * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
-  SIGNAL subband_equalizer_out_sosi_arr : t_dp_sosi_arr(c_sdp_V_oversample * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
-  SIGNAL dp_selector_out_sosi_arr       : t_dp_sosi_arr(c_sdp_V_oversample * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL subband_equalizer_in_sosi_arr  : t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL subband_equalizer_out_sosi_arr : t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL dp_selector_out_sosi_arr       : t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
 
-  SIGNAL scope_sosi_arr                 : t_dp_sosi_integer_arr(c_sdp_V_oversample * c_sdp_S_pn-1 DOWNTO 0);
+  SIGNAL scope_sosi_arr                 : t_dp_sosi_integer_arr(c_sdp_R_os * c_sdp_S_pn-1 DOWNTO 0);
   
   SIGNAL selector_en                        : STD_LOGIC;
   SIGNAL weighted_subbands_flag             : STD_LOGIC;
@@ -504,7 +504,7 @@ BEGIN
   ---------------------------------------------------------------
   u_mem_mux_coef : ENTITY common_lib.common_mem_mux
   GENERIC MAP (    
-    g_nof_mosi    => c_sdp_V_oversample,
+    g_nof_mosi    => c_sdp_R_os,
     g_mult_addr_w => c_fil_coefs_mem_addr_w
   )
   PORT MAP (
@@ -520,7 +520,7 @@ BEGIN
   u_sdp_subband_equalizer : ENTITY work.sdp_subband_equalizer
     GENERIC MAP (
       g_gains_file_name => c_gains_file_name,
-      g_nof_streams     => c_sdp_V_oversample * c_sdp_P_pfb
+      g_nof_streams     => c_sdp_R_os * c_sdp_P_pfb
     )
     PORT MAP(
       dp_clk         => dp_clk,
@@ -544,7 +544,7 @@ BEGIN
   ---------------------------------------------------------------
   u_dp_selector_arr : ENTITY dp_lib.dp_selector_arr
     GENERIC MAP (
-      g_nof_arr => c_sdp_V_oversample * c_sdp_P_pfb,
+      g_nof_arr => c_sdp_R_os * c_sdp_P_pfb,
       g_pipeline => c_subband_equalizer_latency
     )
     PORT MAP (
@@ -566,7 +566,7 @@ BEGIN
   ---------------------------------------------------------------
   -- SUBBAND STATISTICS
   ---------------------------------------------------------------
-  gen_stats_streams: FOR I IN 0 TO c_sdp_V_oversample * c_sdp_P_pfb-1 GENERATE
+  gen_stats_streams: FOR I IN 0 TO c_sdp_R_os * c_sdp_P_pfb-1 GENERATE
     u_subband_stats : ENTITY st_lib.st_sst
       GENERIC MAP(
         g_nof_stat       => c_sdp_N_sub*c_sdp_Q_fft,
@@ -593,7 +593,7 @@ BEGIN
   -- statistics to one array. 
   u_mem_mux_sst : ENTITY common_lib.common_mem_mux
   GENERIC MAP (
-    g_nof_mosi    => c_sdp_V_oversample * c_sdp_P_pfb,
+    g_nof_mosi    => c_sdp_R_os * c_sdp_P_pfb,
     g_mult_addr_w => ceil_log2(c_sdp_N_sub*c_sdp_Q_fft*g_wpfb.stat_data_sz)
   )
   PORT MAP (
@@ -630,7 +630,7 @@ BEGIN
     GENERIC MAP (
       g_sim            => g_sim,
       g_selection      => g_scope_selected_subband,
-      g_nof_input      => c_sdp_V_oversample * c_sdp_P_pfb,
+      g_nof_input      => c_sdp_R_os * c_sdp_P_pfb,
       g_n_deinterleave => c_sdp_Q_fft,
       g_dat_w          => c_sdp_W_subband
     )
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
index 3b5d57a7f3..b08a4b80ef 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
@@ -82,7 +82,7 @@ PACKAGE sdp_pkg is
   CONSTANT c_sdp_S_pn                      : NATURAL := 12;
   CONSTANT c_sdp_S_rcu                     : NATURAL := 3;
   CONSTANT c_sdp_S_sub_bf                  : NATURAL := 488;
-  CONSTANT c_sdp_V_oversample              : NATURAL := 2; -- Oversampling factor of 2 for PFB.
+  CONSTANT c_sdp_R_os                      : NATURAL := 2; -- Oversampling factor of 2 for PFB.
   CONSTANT c_sdp_V_ring_pkt_len_max        : NATURAL := 48; -- for 16 nodes
   CONSTANT c_sdp_V_sample_delay            : NATURAL := 4096;
   CONSTANT c_sdp_V_si_db                   : NATURAL := 1024;
@@ -466,10 +466,10 @@ PACKAGE sdp_pkg is
   CONSTANT c_sdp_reg_aduh_monitor_addr_w       : NATURAL := ceil_log2(c_sdp_S_pn) + 2;
 
   -- FSUB MM address widths
-  CONSTANT c_sdp_ram_fil_coefs_addr_w                  : NATURAL := ceil_log2(c_sdp_V_oversample) + ceil_log2(c_sdp_N_fft * c_sdp_N_taps);
-  CONSTANT c_sdp_ram_st_sst_addr_w                     : NATURAL := ceil_log2(c_sdp_V_oversample * c_sdp_P_pfb) + ceil_log2(c_sdp_N_sub * c_sdp_Q_fft * c_sdp_W_statistic_sz);
+  CONSTANT c_sdp_ram_fil_coefs_addr_w                  : NATURAL := ceil_log2(c_sdp_R_os) + ceil_log2(c_sdp_N_fft * c_sdp_N_taps);
+  CONSTANT c_sdp_ram_st_sst_addr_w                     : NATURAL := ceil_log2(c_sdp_R_os * c_sdp_P_pfb) + ceil_log2(c_sdp_N_sub * c_sdp_Q_fft * c_sdp_W_statistic_sz);
   CONSTANT c_sdp_reg_si_addr_w                         : NATURAL := 1; --enable/disable
-  CONSTANT c_sdp_ram_equalizer_gains_addr_w            : NATURAL := ceil_log2(c_sdp_V_oversample * c_sdp_P_pfb) + ceil_log2(c_sdp_N_sub * c_sdp_Q_fft);
+  CONSTANT c_sdp_ram_equalizer_gains_addr_w            : NATURAL := ceil_log2(c_sdp_R_os * c_sdp_P_pfb) + ceil_log2(c_sdp_N_sub * c_sdp_Q_fft);
   CONSTANT c_sdp_reg_dp_selector_addr_w                : NATURAL := 1; --Select input 0 or 1.
   CONSTANT c_sdp_reg_bsn_monitor_v2_sst_offload_addr_w : NATURAL := c_sdp_reg_bsn_monitor_v2_addr_w;
 
@@ -735,7 +735,7 @@ PACKAGE BODY sdp_pkg IS
     RETURN sel_a_b(g_statistics_type="BST", 1,
            sel_a_b(g_statistics_type="XST", P_sq * N_crosslets,
            sel_a_b(g_statistics_type="SST", S_pn, 
-                                            c_sdp_V_oversample * S_pn)));  -- SST_OS
+                                            c_sdp_R_os * S_pn)));  -- SST_OS
   END func_sdp_get_stat_nof_packets;
 
   FUNCTION func_sdp_get_stat_nof_packets(g_statistics_type : STRING) RETURN NATURAL IS
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd
index cdb5f276b1..2fcefc6a40 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_station.vhd
@@ -24,6 +24,10 @@
 --   Core design for Lofar2 SDP station
 -- Description:
 --   Combines sdp nodes. Contains the UniBoard2 HW version independent LOFAR2 SDP application code.
+-- References:
+-- [1] LOFAR2 SDP FW: https://support.astron.nl/confluence/display/L2M/L4+SDP+Firmware+Design+Document
+-- [2] DISTURB2 revision: https://support.astron.nl/confluence/x/vIIjBQ
+-- [3] SST, SST_OS packets: https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD
 -------------------------------------------------------------------------------
 
 LIBRARY IEEE, common_lib, diag_lib, dp_lib, tech_jesd204b_lib, wpfb_lib, tech_pll_lib, tr_10GbE_lib, nw_10GbE_lib, eth_lib, ring_lib;
@@ -138,7 +142,7 @@ ENTITY sdp_station IS
     reg_aduh_monitor_cipo      : OUT t_mem_cipo := c_mem_cipo_rst;
 
     ----------------------------------------------
-    -- FSUB 
+    -- FSUB / Oversampled FSUB 
     ----------------------------------------------
     -- Subband statistics
     ram_st_sst_copi                     : IN  t_mem_copi := c_mem_copi_rst;
@@ -511,8 +515,8 @@ ARCHITECTURE str OF sdp_station IS
 
   SIGNAL ait_sosi_arr                      : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0);         
   SIGNAL fsub_sosi_arr                     : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0);  -- weighted subbands
-  SIGNAL fsub_oversampled_sosi_arr         : t_dp_sosi_arr(c_sdp_V_oversample * c_sdp_P_pfb-1 DOWNTO 0); 
-  SIGNAL bf_sosi_2arr                      : t_dp_sosi_2arr_pfb(c_sdp_N_beamsets-1 DOWNTO 0);
+  SIGNAL fsub_oversampled_sosi_arr         : t_dp_sosi_arr(c_sdp_R_os * c_sdp_P_pfb-1 DOWNTO 0); 
+  SIGNAL fsub_sosi_2arr                    : t_dp_sosi_2arr_pfb(c_sdp_N_beamsets-1 DOWNTO 0);
   SIGNAL bs_sosi                           : t_dp_sosi;        
  
   SIGNAL xst_from_ri_sosi                  : t_dp_sosi := c_dp_sosi_rst;        
@@ -681,7 +685,7 @@ BEGIN
   -- node_sdp_filterbank (FSUB)
   -----------------------------------------------------------------------------
   gen_use_fsub : IF g_use_fsub GENERATE
-    gen_use_no_oversample : IF NOT g_use_oversample GENERATE
+    gen_use_no_oversample : IF NOT g_use_oversample GENERATE -- Use normal filterbank
       u_fsub : ENTITY work.node_sdp_filterbank 
       GENERIC MAP(
         g_sim                    => g_sim,
@@ -730,14 +734,14 @@ BEGIN
       );
 
       gen_bf_sosi : FOR I IN 0 TO c_sdp_N_beamsets-1 GENERATE 
-        bf_sosi_2arr(I) <= fsub_sosi_arr;
+        fsub_sosi_2arr(I) <= fsub_sosi_arr;
       END GENERATE;
     END GENERATE;
 
     -----------------------------------------------------------------------------
     -- node_sdp_oversampled_filterbank 
     -----------------------------------------------------------------------------
-    gen_use_oversample : IF g_use_oversample GENERATE
+    gen_use_oversample : IF g_use_oversample GENERATE -- use oversampled filterbank instead of normal filterbank
       u_fsub : ENTITY work.node_sdp_oversampled_filterbank 
       GENERIC MAP(
         g_sim                    => g_sim,
@@ -788,8 +792,8 @@ BEGIN
 
       fsub_sosi_arr <= fsub_oversampled_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0); -- Lower part contains normal subbands, higher part contains shifted subbands.
 
-      bf_sosi_2arr(0) <= fsub_sosi_arr;
-      bf_sosi_2arr(1) <= fsub_oversampled_sosi_arr(2 * c_sdp_P_pfb-1 DOWNTO c_sdp_P_pfb); -- Use second beamset for oversampled subbands
+      fsub_sosi_2arr(0) <= fsub_sosi_arr;
+      fsub_sosi_2arr(1) <= fsub_oversampled_sosi_arr(2 * c_sdp_P_pfb-1 DOWNTO c_sdp_P_pfb); -- Use second beamset for oversampled subbands
     END GENERATE;
   END GENERATE;
 
@@ -871,7 +875,7 @@ BEGIN
         dp_clk                   => dp_clk,  
         dp_rst                   => dp_rst,  
       
-        in_sosi_arr              => bf_sosi_2arr(beamset_id),
+        in_sosi_arr              => fsub_sosi_2arr(beamset_id),
         from_ri_sosi             => bf_from_ri_sosi_arr(beamset_id), 
         to_ri_sosi               => bf_to_ri_sosi_arr(beamset_id),  
         bf_udp_sosi              => bf_udp_sosi_arr(beamset_id),
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 584b96d958..6e9769b6bf 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
@@ -256,6 +256,7 @@ ARCHITECTURE str OF sdp_statistics_offload IS
   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;
+  SIGNAL fsub_type                : STD_LOGIC := '0';
 
   -- Debug signals for view in Wave window
   SIGNAL dbg_c_marker                    : NATURAL := c_marker;
@@ -310,7 +311,7 @@ BEGIN
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_antenna_band_id"         ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_source_info_antenna_band_id"         )) <= SLV(sdp_info.antenna_band_index);
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_nyquist_zone_id"         ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_source_info_nyquist_zone_id"         )) <= sdp_info.nyquist_zone_index;
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_f_adc"                   ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_source_info_f_adc"                   )) <= SLV(sdp_info.f_adc);
-  dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type"               ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_source_info_fsub_type"               )) <= SLV(sdp_info.fsub_type);
+  dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_fsub_type"               ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_source_info_fsub_type"               )) <= SLV(fsub_type);
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_payload_error"           ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_source_info_payload_error"           )) <= SLV(hdr_input.payload_err);
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_beam_repositioning_flag" ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_source_info_beam_repositioning_flag" )) <= SLV(sdp_info.beam_repositioning_flag);
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_source_info_weighted_subbands_flag"  ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_source_info_weighted_subbands_flag"  )) <= SLV(weighted_subbands_flag);
@@ -323,6 +324,7 @@ BEGIN
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "sdp_block_period"                        ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "sdp_block_period"                        )) <= sdp_info.block_period;
   dp_header_info(field_hi(c_sdp_stat_hdr_field_arr, "dp_bsn"                                  ) DOWNTO field_lo(c_sdp_stat_hdr_field_arr,  "dp_bsn"                                  )) <= hdr_input.bsn_at_sync;
 
+
   p_reg : PROCESS(dp_rst, dp_clk)
   BEGIN
     IF dp_rst='1' THEN
@@ -410,7 +412,13 @@ BEGIN
     data_id_rec.sst_signal_input_index <= r.packet_count + p.local_si_offset;
   END GENERATE;
   gen_data_id_sst_os : IF g_statistics_type = "SST_OS" GENERATE
-    data_id_rec.sst_signal_input_index <= r.packet_count + c_sdp_V_oversample * p.local_si_offset;
+    -- Signal input index is repeated, first 0:11 (r.packet_count 0:11) with fsub_type = 0.
+    -- Then for r.packet_count 12:23, signal input index is again 0:11 but with fsub_type = 1.
+    fsub_type <= '0' WHEN r.packet_count < c_sdp_S_pn ELSE '1'; -- Set fsub_type = 0 for unshifted bands, '1' for shifted bands
+    data_id_rec.sst_signal_input_index <= r.packet_count + p.local_si_offset WHEN r.packet_count < c_sdp_S_pn ELSE r.packet_count - c_sdp_S_pn + p.local_si_offset;
+  END GENERATE;
+  gen_no_os : IF g_statistics_type /= "SST_OS" GENERATE -- Set fsub_type to sdp_info.fsub_type when g_statistics_type is not SST_OS.
+    fsub_type <= sdp_info.fsub_type;
   END GENERATE;
   gen_data_id_bst : IF g_statistics_type = "BST" GENERATE
     data_id_rec.bst_beamlet_index <= c_beamlet_id;
@@ -467,7 +475,7 @@ BEGIN
 
       -- Start next packets offload.
       IF r.packet_count < reg_input.nof_packets - 1 THEN
-        IF g_statistics_type = "SST" THEN
+        IF g_statistics_type = "SST" OR g_statistics_type = "SST_OS" THEN
           --                 step        step        step        step        step        step
           -- start_address :    0,    2, 2048, 2050, 4096, 4098, 6144, 6146, 8192, 8194, 10240, 10242
           v.start_address := r.start_address + c_mm_data_size;  -- default step to next packet in this step
diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd
index 529ca37306..42b3fb1b10 100644
--- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd
@@ -117,7 +117,7 @@ PACKAGE BODY tb_sdp_pkg IS
     v_hdr.ip.dst_ip_addr     :=               ip_dst_addr;  -- c_network_ip_addr_w
 
     -- udp header
-    IF g_statistics_type = "SST" THEN
+    IF g_statistics_type = "SST" OR g_statistics_type = "SST_OS" THEN
       v_hdr.udp.src_port := c_sdp_sst_udp_src_port_15_8 & TO_UVEC(gn_index, 8);
     ELSIF g_statistics_type = "BST" THEN
       v_hdr.udp.src_port := c_sdp_bst_udp_src_port_15_8 & TO_UVEC(gn_index, 8);
@@ -146,7 +146,7 @@ PACKAGE BODY tb_sdp_pkg IS
 
     v_hdr.app.sdp_reserved                            := TO_UVEC(                 0,  8);
     v_hdr.app.sdp_integration_interval                := TO_UVEC(nof_block_per_sync, 24);
-    IF g_statistics_type = "SST" THEN
+    IF g_statistics_type = "SST" OR g_statistics_type = "SST_OS" THEN
       v_hdr.app.sdp_data_id                           := TO_UVEC(sst_signal_input, 32);
       v_hdr.app.sdp_data_id_sst_signal_input_index    := TO_UVEC(sst_signal_input,  8);
     ELSIF g_statistics_type = "BST" THEN
@@ -215,7 +215,7 @@ PACKAGE BODY tb_sdp_pkg IS
 
     -- . sdp_data_id word and fields per g_statistics_type
     ASSERT in_hdr.app.sdp_data_id                             = exp_hdr.app.sdp_data_id                          REPORT "Wrong " & g_statistics_type & " app.sdp_data_id"                          SEVERITY ERROR;
-    IF g_statistics_type = "SST" THEN
+    IF g_statistics_type = "SST" OR g_statistics_type = "SST_OS" THEN
       ASSERT in_hdr.app.sdp_data_id_sst_signal_input_index    = exp_hdr.app.sdp_data_id_sst_signal_input_index   REPORT "Wrong " & g_statistics_type & " app.sdp_data_id_sst_signal_input_index"   SEVERITY ERROR;
     ELSIF g_statistics_type = "BST" THEN
       ASSERT in_hdr.app.sdp_data_id_bst_beamlet_index         = exp_hdr.app.sdp_data_id_bst_beamlet_index        REPORT "Wrong " & g_statistics_type & " app.sdp_data_id_bst_beamlet_index"        SEVERITY ERROR;
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 279c2d3243..fa06e0c1e3 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
@@ -191,6 +191,7 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
   SIGNAL rx_sdp_stat_header      : t_sdp_stat_header;
   SIGNAL exp_sdp_stat_header     : t_sdp_stat_header;
 
+  SIGNAL exp_sdp_info            : t_sdp_info := c_exp_sdp_info;
   SIGNAL cur_dp_bsn              : NATURAL;
   SIGNAL exp_dp_bsn              : NATURAL;
   SIGNAL exp_sst_signal_input    : NATURAL;
@@ -360,8 +361,11 @@ BEGIN
   -- For all statistics
   cur_dp_bsn <= c_bsn_init + 1 + rx_sync_cnt * c_nof_block_per_sync;  -- in current sync interval
   exp_dp_bsn <= cur_dp_bsn WHEN rising_edge(dp_clk) AND rx_offload_sosi.sync = '1';  -- previous sync interval
-  -- SST
-  exp_sst_signal_input <= rx_packet_cnt + c_sdp_S_pn * gn_index;
+  -- SST, SST_OS
+  exp_sst_signal_input <= (rx_packet_cnt MOD c_sdp_S_pn) + c_sdp_S_pn * gn_index; -- Using MOD c_sdp_S_pn for SST_OS.
+  gen_fsub_type : IF g_statistics_type = "SST_OS" GENERATE
+    exp_sdp_info.fsub_type <= '0' WHEN rx_packet_cnt < c_sdp_S_pn ELSE '1';
+  END GENERATE;
   -- BST
   exp_bst_beamlet_index <= c_beamlet_index;
   -- XST
@@ -378,7 +382,7 @@ BEGIN
                                                       c_eth_src_mac,
                                                       c_ip_src_addr,
                                                       c_sdp_stat_ip_dst_addr,
-                                                      c_exp_sdp_info,
+                                                      exp_sdp_info,
                                                       g_statistics_type,
                                                       weighted_subbands_flag,
                                                       gn_index,
@@ -451,7 +455,7 @@ BEGIN
       rx_val <= '0';
       v_rx_data := TO_UINT(rx_offload_sosi.data);
       IF rx_offload_sosi.valid = '1' THEN
-        IF g_statistics_type = "SST" THEN
+        IF g_statistics_type = "SST" OR g_statistics_type = "SST_OS" THEN
           --        Indices:
           --         W:    0     1      2     3      4     5 ...  1022  1023
           -- U = D = S:    0            1            2             511
@@ -484,7 +488,8 @@ BEGIN
             v_exp_data := v_exp_data + 2;  -- due to c_sdp_W_statistic_sz = 2 and c_mm_nof_step = 2 > 1
           END IF;
           v_exp_data := v_exp_data + (P/2) * 2048;  -- due to c_packet_size = 1024 and c_mm_nof_step = 2 > 1
-          ASSERT v_exp_data = v_rx_data REPORT "Wrong SST payload data Rx" SEVERITY ERROR;
+          IF g_statistics_type = "SST"    THEN ASSERT v_exp_data = v_rx_data REPORT "Wrong SST payload data Rx" SEVERITY ERROR; END IF;
+          IF g_statistics_type = "SST_OS" THEN ASSERT v_exp_data = v_rx_data REPORT "Wrong SST_OS payload data Rx" SEVERITY ERROR; END IF;
 
         ELSIF g_statistics_type = "BST" THEN
           --    Indices:
diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd
index e017be4325..05dfbfb1a1 100644
--- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd
@@ -56,6 +56,8 @@ BEGIN
 
   u_sst                     : ENTITY work.tb_sdp_statistics_offload GENERIC MAP( TRUE, "SST", 50,  TRUE, 3, 3);
   u_sst_no_reverse          : ENTITY work.tb_sdp_statistics_offload GENERIC MAP( TRUE, "SST", 50, FALSE, 3, 3);
+  u_sst_os                  : ENTITY work.tb_sdp_statistics_offload GENERIC MAP( TRUE, "SST_OS", 50,  TRUE, 3, 3);
+  u_sst_os_no_reverse       : ENTITY work.tb_sdp_statistics_offload GENERIC MAP( TRUE, "SST_OS", 50, FALSE, 3, 3);
   u_bst_0                   : ENTITY work.tb_sdp_statistics_offload GENERIC MAP( TRUE, "BST", 50,  TRUE, 1, 3);
   u_bst_0_no_reverse        : ENTITY work.tb_sdp_statistics_offload GENERIC MAP( TRUE, "BST", 50, FALSE, 1, 3, 0);
   u_bst_1                   : ENTITY work.tb_sdp_statistics_offload GENERIC MAP( TRUE, "BST", 50,  TRUE, 1, 3, 1);
-- 
GitLab