diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/disturb2_unb2b_sdp_station_full_wg/tb_disturb2_unb2b_sdp_station_full_wg.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/disturb2_unb2b_sdp_station_full_wg/tb_disturb2_unb2b_sdp_station_full_wg.vhd
index 75b4e33e6fbdbfa2086688217e442a54f89d438a..e87e209540427f98bad1b4cb0a240f4b46909bef 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/disturb2_unb2b_sdp_station_full_wg/tb_disturb2_unb2b_sdp_station_full_wg.vhd
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/disturb2_unb2b_sdp_station_full_wg/tb_disturb2_unb2b_sdp_station_full_wg.vhd
@@ -27,25 +27,40 @@
 --   MM control actions:
 --
 --   1) Enable calc mode for WG via reg_diag_wg with:
---      1.
---        freq = 19.921875MHz (subband 102)
---        ampl = 0.5 * 2**13
---      2.
---        freg = 19.43359375 MHz (subband 99.5)
---        ampl = 0.5 * 2**13
+--      1. freq = 19.921875MHz (subband 102, at mid of normal beamlet)
+--      2. freg = 19.43359375 MHz (subband 99.5, at mid of shifted beamlet)
+--      Use same ampl for both WG. Use c_beamlet_scale such that beamlet output
+--      will fit in W_beamlet = 8 bits.
 --   
 --   2) Read current BSN from reg_bsn_scheduler_wg and write reg_bsn_scheduler_wg 
 --      to trigger start of WG at BSN.
 --     
---   3) Verify 10GbE output.
---   
+--   3) Verify beamlet data in 10GbE output for beamset 0 (with the normal
+--      beamlets) and beamset 1 (with the frequency shifted beamlets).
+--      . verify subband 102 in beamset 0
+--      . verify subband  99.5 in beamset 1
+--      . These subbands also appear at about half power in the other beamset
+--        but these values are not verified, because they are at the edge of
+--        the subband and will in practise not be used. Therefore choose WG
+--        c_wg_ampl_sp_2 = c_wg_ampl_sp_0 / 3 to distinghuis them.
+--        The purpose of the 2x oversampled filterbank is to only use the
+--        beamlet frequencies that are around the center of the subband, so
+--        the half of the subbands from beamset 0 and half of the subbands
+--        from beamset 1.
 --
 -- Usage:
 --   > as 7    # default
 --   > as 12   # for detailed debugging
 --   > run -a  
--- Remark: TB based on tb_lofar2_unb2b_beamformer.vhd
+--   . manually add missing beamlet_arr2_im/re to wave window, and manually
+--     copy beamlet_arr2_im[195:215] and [1170:1190] and the rx_beamlet_*
+--     index signals to have a more compact view of the relevant indices.
+--   . If c_subband_phase = 0.0 then beamlet_arr2_re entries are 0.
+--   . manually add top level generics/constants to wave window.
+--
+-- Remark: TB is based on tb_lofar2_unb2c_sdp_station_bf.
 -------------------------------------------------------------------------------
+
 LIBRARY IEEE, common_lib, unb2b_board_lib, i2c_lib, mm_lib, dp_lib, diag_lib, lofar2_sdp_lib, wpfb_lib, tech_pll_lib, tr_10GbE_lib;
 USE IEEE.std_logic_1164.ALL;
 USE IEEE.numeric_std.ALL;
@@ -89,25 +104,65 @@ ARCHITECTURE tb OF tb_disturb2_unb2b_sdp_station_full_wg IS
   CONSTANT c_wpfb_complex_sim    : t_wpfb := func_wpfb_map_real_input_wpfb_parameters_to_complex_input(c_wpfb_sim);
    
   -- WG
-  CONSTANT c_full_scale_ampl      : REAL := REAL(2**(c_sdp_W_adc-1)-1);  -- = full scale of WG
   CONSTANT c_bsn_start_wg         : NATURAL := 2;  -- start WG at this BSN to instead of some BSN, to avoid mismatches in exact expected data values
-  CONSTANT c_ampl_sp              : NATURAL := 2**(c_sdp_W_adc-1) / 2;  -- in number of lsb
-  CONSTANT c_wg_subband_freq_unit : REAL := c_diag_wg_freq_unit/REAL(c_sdp_N_fft);  -- subband freq = Fs/1024 = 200 MSps/1024 = 195312.5 Hz sinus
-  CONSTANT c_wg_freq_offset       : REAL := 0.0/11.0; -- in freq_unit
-  CONSTANT c_subband_sp_0         : REAL := 102.0;  -- Select subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz 
-  CONSTANT c_subband_sp_1         : REAL := 99.5;  -- Select subband at index 99.5 = 99.5/1024 * 200MHz = 19.43359375 MHz
-  CONSTANT c_wg_ampl_lsb          : REAL := c_diag_wg_ampl_unit / c_full_scale_ampl;  -- amplitude in number of LSbit resolution steps
-  CONSTANT c_exp_wg_power_sp      : REAL := REAL(c_ampl_sp**2)/2.0 * REAL(c_sdp_N_fft*c_nof_block_per_sync);
+  -- . ampl
+  CONSTANT c_beamlet_scale        : REAL := 1.0 / 2.0**9;
+  CONSTANT c_wg_ampl_sp_0         : NATURAL := NATURAL(7.0 / c_beamlet_scale);  -- choose < 8.0 to have no beamlet output overflow with unit weights and unit beamlet scale
+  CONSTANT c_wg_ampl_sp_2         : NATURAL := c_wg_ampl_sp_0 / 3;  -- use different ampl for sp_0 and sp_2 to distinghuis them
+  -- . phase
+  CONSTANT c_subband_phase        : REAL := 0.0;  -- wanted subband phase in degrees = WG phase at sop
+  CONSTANT c_wg_latency           : INTEGER := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  CONSTANT c_subband_sp_0         : REAL := 102.0;  -- use WG at sp-0 for subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz
+  CONSTANT c_subband_sp_2         : REAL :=  99.5;  -- use WG at sp-2 for subband at index 99.5 = 99.5/1024 * 200MHz = 19.43359375 MHz
+  CONSTANT c_subband_freq_sp_0    : REAL := REAL(c_subband_sp_0) / REAL(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz = dp_clk rate
+  CONSTANT c_subband_freq_sp_2    : REAL := REAL(c_subband_sp_2) / REAL(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz = dp_clk rate
+  CONSTANT c_wg_phase_offset_sp_0 : REAL := 360.0 * REAL(c_wg_latency) * c_subband_freq_sp_0;  -- c_diag_wg_latency is in dp_clk cycles
+  CONSTANT c_wg_phase_offset_sp_2 : REAL := 360.0 * REAL(c_wg_latency) * c_subband_freq_sp_2;  -- c_diag_wg_latency is in dp_clk cycles
+  CONSTANT c_wg_phase_sp_0        : REAL := c_subband_phase + c_wg_phase_offset_sp_0;  -- WG phase in degrees
+  CONSTANT c_wg_phase_sp_2        : REAL := c_subband_phase + c_wg_phase_offset_sp_2;  -- WG phase in degrees
+
+  -- WPFB, use default unit subband weights (= 1.0 + 0j)
+  CONSTANT c_exp_subband_ampl_sp_0 : REAL := REAL(c_wg_ampl_sp_0) * c_sdp_wpfb_subband_sp_ampl_ratio;
+  CONSTANT c_exp_subband_ampl_sp_2 : REAL := REAL(c_wg_ampl_sp_2) * c_sdp_wpfb_subband_sp_ampl_ratio;
+
+  CONSTANT c_subband_phase_offset  : REAL := -90.0;  -- WG with zero phase sinus yields subband with -90 degrees phase (negative Im, zero Re)
+  CONSTANT c_exp_subband_phase     : REAL := c_subband_phase + c_subband_phase_offset;
+
+  -- BF
+  -- . use one active WG per subband, so beamlet_sum of one subband
+  -- . use default unit BF weights (= 1.0 + 0j), so beamlet_sum = subband
+  -- . use beamlet output = beamlet_sum * c_beamlet_scale
+  CONSTANT c_exp_beamlet_scale     : NATURAL := NATURAL(c_beamlet_scale * REAL(c_sdp_unit_beamlet_scale));  -- c_sdp_unit_beamlet_scale = 2**15;
+  CONSTANT c_exp_beamlet_ampl_sp_0 : REAL := c_exp_subband_ampl_sp_0 * c_beamlet_scale;
+  CONSTANT c_exp_beamlet_ampl_sp_2 : REAL := c_exp_subband_ampl_sp_2 * c_beamlet_scale;
+  CONSTANT c_exp_beamlet_phase     : REAL := c_exp_subband_phase;
+  CONSTANT c_exp_beamlet_re_sp_0   : INTEGER := INTEGER(COMPLEX_RE(c_exp_beamlet_ampl_sp_0, c_exp_beamlet_phase));
+  CONSTANT c_exp_beamlet_re_sp_2   : INTEGER := INTEGER(COMPLEX_RE(c_exp_beamlet_ampl_sp_2, c_exp_beamlet_phase));
+  CONSTANT c_exp_beamlet_im_sp_0   : INTEGER := INTEGER(COMPLEX_IM(c_exp_beamlet_ampl_sp_0, c_exp_beamlet_phase));
+  CONSTANT c_exp_beamlet_im_sp_2   : INTEGER := INTEGER(COMPLEX_IM(c_exp_beamlet_ampl_sp_2, c_exp_beamlet_phase));
+
+  CONSTANT c_exp_beamlet_index    : NATURAL := NATURAL(c_subband_sp_0) * c_sdp_N_pol;
+  CONSTANT c_exp_beamlet_index_os : NATURAL := c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block + NATURAL(ROUND(c_subband_sp_2)) * c_sdp_N_pol;
 
   TYPE t_real_arr IS ARRAY (INTEGER RANGE <>) OF REAL; 
   TyPE t_slv_64_subbands_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_S_sub_bf);
 
-  -- MM  
+  -- MM
+  -- . Address widths of a single MM instance
+  CONSTANT c_addr_w_reg_diag_wg           : NATURAL := 2;
+  CONSTANT c_addr_w_reg_dp_xonoff         : NATURAL := 1;
+  CONSTANT c_addr_w_reg_bf_scale          : NATURAL := 1;
+  -- . Address spans of a single MM instance
+  CONSTANT c_mm_span_reg_diag_wg          : NATURAL := 2**c_addr_w_reg_diag_wg;
+  CONSTANT c_mm_span_reg_dp_xonoff        : NATURAL := 2**c_addr_w_reg_dp_xonoff;
+  CONSTANT c_mm_span_reg_bf_scale         : NATURAL := 2**c_addr_w_reg_bf_scale;
+
   CONSTANT c_mm_file_reg_ppsh             : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "PIO_PPS";
   CONSTANT c_mm_file_reg_bsn_source_v2    : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2";
   CONSTANT c_mm_file_reg_bsn_scheduler_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SCHEDULER";
   CONSTANT c_mm_file_reg_diag_wg          : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_WG";
   CONSTANT c_mm_file_reg_dp_xonoff        : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_DP_XONOFF";
+  CONSTANT c_mm_file_reg_bf_scale         : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BF_SCALE";
 
   -- Tb
   SIGNAL tb_end              : STD_LOGIC := '0';
@@ -116,16 +171,25 @@ ARCHITECTURE tb OF tb_disturb2_unb2b_sdp_station_full_wg IS
   SIGNAL rd_data             : STD_LOGIC_VECTOR(c_32-1 DOWNTO 0);
 
   -- WG
-  SIGNAL dbg_c_exp_wg_power_sp   : REAL := c_exp_wg_power_sp;
-  SIGNAL current_bsn_wg          : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
+  SIGNAL current_bsn_wg      : STD_LOGIC_VECTOR(c_dp_stream_bsn_w-1 DOWNTO 0);
+
+  -- BF
+  SIGNAL rd_beamlet_scale    : STD_LOGIC_VECTOR(15 DOWNTO 0);
 
   -- 10GbE
-  CONSTANT c_exp_beamlet_index    : NATURAL := NATURAL(c_subband_sp_0) * c_sdp_N_pol;
-  CONSTANT c_exp_beamlet_index_os : NATURAL := c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block + NATURAL(ROUND(c_subband_sp_1)) * c_sdp_N_pol;
-  CONSTANT c_exp_beamlet_re : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"7F"; --Derived from simulation
-  CONSTANT c_exp_beamlet_im : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"81"; --Derived from simulation
-  
-  SIGNAL dbg_beamlet_index_offset : NATURAL := 0;
+  -- . header fields
+  SIGNAL rx_beamlet_scale        : STD_LOGIC_VECTOR(15 DOWNTO 0);
+  SIGNAL rx_beamlet_index_offset : NATURAL := 0;
+  SIGNAL rx_blocks_per_packet    : STD_LOGIC_VECTOR(7 DOWNTO 0);
+  SIGNAL rx_beamlets_per_block   : STD_LOGIC_VECTOR(15 DOWNTO 0);
+  SIGNAL rx_block_period         : STD_LOGIC_VECTOR(15 DOWNTO 0);
+  SIGNAL rx_bsn                  : STD_LOGIC_VECTOR(63 DOWNTO 0);
+
+  -- . payload indices and data arrays
+  SIGNAL rx_beamlet_blk      : NATURAL := 0;
+  SIGNAL rx_beamlet_cnt      : NATURAL := 0;
+  SIGNAL rx_beamlet_valid    : STD_LOGIC := '0';
+  SIGNAL rx_beamlet_sop      : STD_LOGIC := '0';
 
   SIGNAL beamlet_arr2_re : t_slv_8_arr(c_sdp_R_os * c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block-1 DOWNTO 0);
   SIGNAL beamlet_arr2_im : t_slv_8_arr(c_sdp_R_os * c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block-1 DOWNTO 0);
@@ -274,7 +338,8 @@ BEGIN
   
   p_mm_stimuli : PROCESS
     VARIABLE v_bsn                   : NATURAL;
-    VARIABLE v_beamlet_index_offset  : NATURAL;  
+    VARIABLE v_offset                : NATURAL;
+    VARIABLE v_beamlet_index_offset  : NATURAL;
   BEGIN
     -- Wait for DUT power up after reset
     WAIT FOR 1 us;
@@ -282,10 +347,25 @@ BEGIN
     proc_common_wait_until_hi_lo(ext_clk, ext_pps);
 
     ----------------------------------------------------------------------------
-    -- Enable UDP offload (dp_xonoff) of beamset 0
+    -- Use both beamsets, 0 for BF with normal subbands, 1 for BF with shifted subbands
     ----------------------------------------------------------------------------
-    mmf_mm_bus_wr(c_mm_file_reg_dp_xonoff,0 , 1, tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_dp_xonoff,2 , 1, tb_clk);
+    FOR bset IN 0 TO c_sdp_N_beamsets-1 LOOP
+      -- Enable beamlet output
+      v_offset := bset * c_mm_span_reg_dp_xonoff;
+      mmf_mm_bus_wr(c_mm_file_reg_dp_xonoff, v_offset + 0, 1, tb_clk);
+
+      -- MM beamlet_scale
+      -- . write
+      v_offset := bset * c_mm_span_reg_bf_scale;
+      mmf_mm_bus_wr(c_mm_file_reg_bf_scale, v_offset + 0, c_exp_beamlet_scale, tb_clk);
+      proc_common_wait_cross_clock_domain_latency(c_tb_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency*2);
+
+      -- . readback
+      mmf_mm_bus_rd(c_mm_file_reg_bf_scale, v_offset + 0, rd_data, tb_clk);
+      rd_beamlet_scale <= rd_data(15 DOWNTO 0);
+      proc_common_wait_some_cycles(tb_clk, 1);
+      ASSERT TO_UINT(rd_beamlet_scale) = c_exp_beamlet_scale REPORT "Wrong MM read beamlet_scale for beamset " & NATURAL'IMAGE(bset) SEVERITY ERROR;
+    END LOOP;
 
     ----------------------------------------------------------------------------
     -- Enable BS
@@ -303,14 +383,18 @@ BEGIN
     --   1 : phase[15:0]
     --   2 : freq[30:0]
     --   3 : ampl[16:0]
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 0, 1024*2**16 + 1, tb_clk);  -- nof_samples, mode calc
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 1, INTEGER(  0.0 * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 2, INTEGER((c_subband_sp_0+c_wg_freq_offset) * c_wg_subband_freq_unit), tb_clk);  -- freq
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 3, INTEGER(REAL(c_ampl_sp) * c_wg_ampl_lsb), tb_clk);  -- ampl
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 8, 1024*2**16 + 1, tb_clk);  -- nof_samples, mode calc
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 9, INTEGER(  0.0 * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 10, INTEGER((c_subband_sp_1+c_wg_freq_offset) * c_wg_subband_freq_unit), tb_clk);  -- freq
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, 11, INTEGER(REAL(c_ampl_sp) * c_wg_ampl_lsb), tb_clk);  -- ampl
+    -- WG at signal input 0
+    v_offset := 0 * c_mm_span_reg_diag_wg;
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 0, 1024*2**16 + 1, tb_clk);  -- nof_samples, mode calc
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 1, INTEGER(c_wg_phase_sp_0 * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 2, INTEGER(c_subband_sp_0 * c_sdp_wg_subband_freq_unit), tb_clk);  -- freq
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 3, INTEGER(REAL(c_wg_ampl_sp_0) * c_sdp_wg_ampl_lsb), tb_clk);  -- ampl
+    -- WG at signal input 2
+    v_offset := 2 * c_mm_span_reg_diag_wg;
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 0, 1024*2**16 + 1, tb_clk);  -- nof_samples, mode calc
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 1, INTEGER(c_wg_phase_sp_2 * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 2, INTEGER(c_subband_sp_2 * c_sdp_wg_subband_freq_unit), tb_clk);  -- freq
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 3, INTEGER(REAL(c_wg_ampl_sp_2) * c_sdp_wg_ampl_lsb), tb_clk);  -- ampl
 
     -- Read current BSN
     mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO  0), tb_clk);
@@ -332,50 +416,114 @@ BEGIN
     ---------------------------------------------------------------------------
     -- Read 10GbE Stream
     ---------------------------------------------------------------------------
-    FOR BS IN 0 TO 2 LOOP -- Read 3 blocks to make sure we get 1 from each beamset. It can happen that two blocks (but not three) from the same beamset are received back to back.
-      proc_common_wait_until_high(ext_clk, tr_10GbE_src_out.sop);
+
+    -- Read 3 packets to make sure we get 1 from each beamset. It can happen that two packets
+    -- (but not three) from the same beamset are received back to back.
+    FOR packet IN 0 TO 2 LOOP
+      -- Get beamlet_index from packet header
+      proc_common_wait_until_clk_and_high(ext_clk, tr_10GbE_src_out.sop);
       FOR I IN 0 TO 8 LOOP -- Packet header is 9.25 words wide, which can be discarded
         IF I = 7 THEN
-          v_beamlet_index_offset :=  c_sdp_N_pol_bf * TO_UINT(tr_10GbE_src_out.data(39 DOWNTO 24)); -- Read beamlet index
-          dbg_beamlet_index_offset <= v_beamlet_index_offset;
+          rx_beamlet_scale <= tr_10GbE_src_out.data(55 DOWNTO 40);
+          v_beamlet_index_offset := c_sdp_N_pol_bf * TO_UINT(tr_10GbE_src_out.data(39 DOWNTO 24));  -- Read beamlet index
+          rx_beamlet_index_offset <= v_beamlet_index_offset;
+          rx_blocks_per_packet <= tr_10GbE_src_out.data(23 DOWNTO 16);
+          rx_beamlets_per_block <=tr_10GbE_src_out.data(15 DOWNTO 0);
+        END IF;
+        IF I = 8 THEN
+          rx_block_period <= tr_10GbE_src_out.data(63 DOWNTO 48);
+          rx_bsn(63 DOWNTO 16) <= tr_10GbE_src_out.data(47 DOWNTO 0);
         END IF;
-        proc_common_wait_until_high(ext_clk, tr_10GbE_src_out.valid);
-        proc_common_wait_some_cycles(ext_clk, 1);
+        proc_common_wait_until_clk_and_high(ext_clk, tr_10GbE_src_out.valid);
       END LOOP;
-  
-      -- First word contains 3 beamlets + 1 header part
-      beamlet_arr2_re(v_beamlet_index_offset + 0) <= tr_10GbE_src_out.data(7 DOWNTO 0);
-      beamlet_arr2_im(v_beamlet_index_offset + 0) <= tr_10GbE_src_out.data(15 DOWNTO 8);
-      beamlet_arr2_re(v_beamlet_index_offset + 1) <= tr_10GbE_src_out.data(23 DOWNTO 16);
-      beamlet_arr2_im(v_beamlet_index_offset + 1) <= tr_10GbE_src_out.data(31 DOWNTO 24);
-      beamlet_arr2_re(v_beamlet_index_offset + 2) <= tr_10GbE_src_out.data(39 DOWNTO 32);
-      beamlet_arr2_im(v_beamlet_index_offset + 2) <= tr_10GbE_src_out.data(47 DOWNTO 40);
-      proc_common_wait_until_high(ext_clk, tr_10GbE_src_out.valid);
-      proc_common_wait_some_cycles(ext_clk, 1);
-      FOR I IN 1 TO (c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block/4)-1 LOOP
-        beamlet_arr2_re(v_beamlet_index_offset + I*4 -1) <= tr_10GbE_src_out.data(7 DOWNTO 0);
-        beamlet_arr2_im(v_beamlet_index_offset + I*4 -1) <= tr_10GbE_src_out.data(15 DOWNTO 8);
-        beamlet_arr2_re(v_beamlet_index_offset + I*4 +0) <= tr_10GbE_src_out.data(23 DOWNTO 16);
-        beamlet_arr2_im(v_beamlet_index_offset + I*4 +0) <= tr_10GbE_src_out.data(31 DOWNTO 24);
-        beamlet_arr2_re(v_beamlet_index_offset + I*4 +1) <= tr_10GbE_src_out.data(39 DOWNTO 32);
-        beamlet_arr2_im(v_beamlet_index_offset + I*4 +1) <= tr_10GbE_src_out.data(47 DOWNTO 40);
-        beamlet_arr2_re(v_beamlet_index_offset + I*4 +2) <= tr_10GbE_src_out.data(55 DOWNTO 48);
-        beamlet_arr2_im(v_beamlet_index_offset + I*4 +2) <= tr_10GbE_src_out.data(63 DOWNTO 56);
-        proc_common_wait_until_high(ext_clk, tr_10GbE_src_out.valid);
-        proc_common_wait_some_cycles(ext_clk, 1);
+      rx_bsn(15 DOWNTO 0) <= tr_10GbE_src_out.data(63 DOWNTO 48);
+
+      -- Get all c_sdp_cep_nof_blocks_per_packet = 4 blocks from the packet
+      FOR blk IN 0 TO c_sdp_cep_nof_blocks_per_packet-1 LOOP
+        -- . First word contains 1 header part of two bytes and 3 beamlets [0:2].
+        -- . expect c_sdp_cep_nof_beamlets_per_block = c_sdp_S_sub_bf = 488 dual pol
+        --   and complex beamlets per packet, so 2 dual pol beamlets/64b data word.
+        -- . Beamlets array is stored big endian in the data, so X index 0 first in
+        --   MSByte of tr_10GbE_src_out.data.
+        rx_beamlet_blk <= blk;
+        rx_beamlet_cnt <= 0;
+        rx_beamlet_valid <= '1';
+        rx_beamlet_sop <= '1';
+        beamlet_arr2_im(v_beamlet_index_offset + 0) <= tr_10GbE_src_out.data(47 DOWNTO 40);
+        beamlet_arr2_re(v_beamlet_index_offset + 0) <= tr_10GbE_src_out.data(39 DOWNTO 32);
+        beamlet_arr2_im(v_beamlet_index_offset + 1) <= tr_10GbE_src_out.data(31 DOWNTO 24);
+        beamlet_arr2_re(v_beamlet_index_offset + 1) <= tr_10GbE_src_out.data(23 DOWNTO 16);
+        beamlet_arr2_im(v_beamlet_index_offset + 2) <= tr_10GbE_src_out.data(15 DOWNTO 8);
+        beamlet_arr2_re(v_beamlet_index_offset + 2) <= tr_10GbE_src_out.data(7 DOWNTO 0);
+        proc_common_wait_until_clk_and_high(ext_clk, tr_10GbE_src_out.valid);
+        rx_beamlet_cnt <= rx_beamlet_cnt + 1;
+        rx_beamlet_sop <= '0';
+        -- . get beamlets during block, there are 4 complex beamlets per 64b word
+        FOR I IN 1 TO (c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block/4)-1 LOOP
+          beamlet_arr2_im(v_beamlet_index_offset + I*4 -1) <= tr_10GbE_src_out.data(63 DOWNTO 56);
+          beamlet_arr2_re(v_beamlet_index_offset + I*4 -1) <= tr_10GbE_src_out.data(55 DOWNTO 48);
+          beamlet_arr2_im(v_beamlet_index_offset + I*4 +0) <= tr_10GbE_src_out.data(47 DOWNTO 40);
+          beamlet_arr2_re(v_beamlet_index_offset + I*4 +0) <= tr_10GbE_src_out.data(39 DOWNTO 32);
+          beamlet_arr2_im(v_beamlet_index_offset + I*4 +1) <= tr_10GbE_src_out.data(31 DOWNTO 24);
+          beamlet_arr2_re(v_beamlet_index_offset + I*4 +1) <= tr_10GbE_src_out.data(23 DOWNTO 16);
+          beamlet_arr2_im(v_beamlet_index_offset + I*4 +2) <= tr_10GbE_src_out.data(15 DOWNTO 8);
+          beamlet_arr2_re(v_beamlet_index_offset + I*4 +2) <= tr_10GbE_src_out.data(7 DOWNTO 0);
+          proc_common_wait_until_clk_and_high(ext_clk, tr_10GbE_src_out.valid);
+          rx_beamlet_cnt <= rx_beamlet_cnt + 1;
+        END LOOP;
+        -- . get last beamlet of block
+        beamlet_arr2_im(v_beamlet_index_offset + c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block-1) <= tr_10GbE_src_out.data(63 DOWNTO 56);
+        beamlet_arr2_re(v_beamlet_index_offset + c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block-1) <= tr_10GbE_src_out.data(55 DOWNTO 48);
+        -- Loop for next block in packet
       END LOOP;
+      -- Make rx_beamlet_valid low for next header or after loop during verify.
+      -- Cannot wait one ext_clk cycle here to include last beamlet of block,
+      -- because next packet sop may follow immediately after this packet eop.
+      rx_beamlet_valid <= '0';
 
-      beamlet_arr2_re(v_beamlet_index_offset + c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block-1) <= tr_10GbE_src_out.data(55 DOWNTO 48);
-      beamlet_arr2_im(v_beamlet_index_offset + c_sdp_N_pol_bf * c_sdp_cep_nof_beamlets_per_block-1) <= tr_10GbE_src_out.data(63 DOWNTO 56);
+      -- Loop and wait for next packet.
     END LOOP;
 
     ---------------------------------------------------------------------------
     -- Verify 10GbE UDP offload
     --------------------------------------------------------------------------- 
-    ASSERT beamlet_arr2_re(c_exp_beamlet_index) = c_exp_beamlet_re REPORT "Wrong 10GbE output (re) on beamset 0" SEVERITY ERROR;
-    ASSERT beamlet_arr2_im(c_exp_beamlet_index) = c_exp_beamlet_im REPORT "Wrong 10GbE output (im) on beamset 0" SEVERITY ERROR;
-    ASSERT beamlet_arr2_re(c_exp_beamlet_index_os) = c_exp_beamlet_re REPORT "Wrong 10GbE output (re) on beamset 1 (shifted subbands)" SEVERITY ERROR;
-    ASSERT beamlet_arr2_im(c_exp_beamlet_index_os) = c_exp_beamlet_im REPORT "Wrong 10GbE output (im) on beamset 1 (shifted subbands)" SEVERITY ERROR;
+    print_str("");
+    print_str("WG:");
+    print_str(". sp_0 at mid subband,");
+    print_str(". sp_2 at subband edge, so at mid of os subband.");
+    print_str(". c_wg_ampl_sp_0            = " & int_to_str(c_wg_ampl_sp_0));
+    print_str(". c_wg_ampl_sp_2            = " & int_to_str(c_wg_ampl_sp_2));
+    print_str(". c_subband_sp_0            = " & real_to_str(c_subband_sp_0, 20, 6));
+    print_str(". c_subband_sp_2            = " & real_to_str(c_subband_sp_2, 20, 6));
+    print_str("WPFB:");
+    print_str(". c_exp_subband_ampl_sp_0   = " & real_to_str(c_exp_subband_ampl_sp_0, 20, 6));
+    print_str(". c_exp_subband_ampl_sp_2   = " & real_to_str(c_exp_subband_ampl_sp_2, 20, 6));
+    print_str("");
+    print_str("Beamlet output: (sp_0 at mid subband, sp_2 at subband edge, so at mid of os subband):");
+    print_str(". c_exp_beamlet_index       = " & int_to_str(c_exp_beamlet_index));
+    print_str(". c_exp_beamlet_index_os    = " & int_to_str(c_exp_beamlet_index_os));
+    print_str(". c_exp_beamlet_ampl_sp_0   = " & real_to_str(c_exp_beamlet_ampl_sp_0, 20, 6));
+    print_str(". c_exp_beamlet_ampl_sp_2   = " & real_to_str(c_exp_beamlet_ampl_sp_2, 20, 6));
+    print_str(". c_exp_beamlet_phase       = " & real_to_str(c_exp_beamlet_phase, 20, 6));
+    print_str("");
+    print_str(". c_beamlet_re at index     = " & int_to_str(TO_SINT(beamlet_arr2_re(c_exp_beamlet_index))));
+    print_str(". c_beamlet_re at index_os  = " & int_to_str(TO_SINT(beamlet_arr2_re(c_exp_beamlet_index_os))));
+    print_str(". c_exp_beamlet_re_sp_0     = " & int_to_str(INTEGER(c_exp_beamlet_re_sp_0)));
+    print_str(". c_exp_beamlet_re_sp_2     = " & int_to_str(INTEGER(c_exp_beamlet_re_sp_2)));
+    print_str("");
+    print_str(". c_beamlet_im at index     = " & int_to_str(TO_SINT(beamlet_arr2_im(c_exp_beamlet_index))));
+    print_str(". c_beamlet_im at index_os  = " & int_to_str(TO_SINT(beamlet_arr2_im(c_exp_beamlet_index_os))));
+    print_str(". c_exp_beamlet_im_sp_0     = " & int_to_str(INTEGER(c_exp_beamlet_im_sp_0)));
+    print_str(". c_exp_beamlet_im_sp_2     = " & int_to_str(INTEGER(c_exp_beamlet_im_sp_2)));
+
+    -- WG at subband center will yield same subband value in every subband period
+    ASSERT SIGNED(beamlet_arr2_re(c_exp_beamlet_index)) = c_exp_beamlet_re_sp_0 REPORT "Wrong 10GbE beamlet output /= c_exp_beamlet_re_sp_0 in beamset 0" SEVERITY ERROR;
+    ASSERT SIGNED(beamlet_arr2_im(c_exp_beamlet_index)) = c_exp_beamlet_im_sp_0 REPORT "Wrong 10GbE beamlet output /= c_exp_beamlet_im_sp_0 in beamset 0" SEVERITY ERROR;
+    -- WG at subband edge will change phase 180 degrees in every subband period, so expect factor +-1
+    ASSERT SIGNED(beamlet_arr2_re(c_exp_beamlet_index_os)) = c_exp_beamlet_re_sp_2 OR
+           SIGNED(beamlet_arr2_re(c_exp_beamlet_index_os)) = -c_exp_beamlet_re_sp_2 REPORT "Wrong 10GbE beamlet output /= c_exp_beamlet_re_sp_2 in beamset 1 (shifted subbands)" SEVERITY ERROR;
+    ASSERT SIGNED(beamlet_arr2_im(c_exp_beamlet_index_os)) = c_exp_beamlet_im_sp_2 OR
+           SIGNED(beamlet_arr2_im(c_exp_beamlet_index_os)) = -c_exp_beamlet_im_sp_2 REPORT "Wrong 10GbE beamlet output /= c_exp_beamlet_im_sp_2 in beamset 1 (shifted subbands)" SEVERITY ERROR;
 
     ---------------------------------------------------------------------------
     -- End Simulation 
diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd
index a3cd031036e188413dfa5fa7bef82621b956b959..821bd58d57e44525fdbadb34bd2306ddbfa88ee7 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf/tb_lofar2_unb2c_sdp_station_bf.vhd
@@ -191,7 +191,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS
   CONSTANT c_tb_clk_period       : TIME := 100 ps; -- use fast tb_clk to speed up M&C
 
   CONSTANT c_nof_block_per_sync  : NATURAL := 16;
-  CONSTANT c_nof_clk_per_sync    : NATURAL := c_nof_block_per_sync*c_sdp_N_fft; 
+  CONSTANT c_nof_clk_per_sync    : NATURAL := c_nof_block_per_sync*c_sdp_N_fft;
   CONSTANT c_pps_period          : NATURAL := c_nof_clk_per_sync;
   CONSTANT c_wpfb_sim            : t_wpfb := func_wpfb_set_nof_block_per_sync(c_sdp_wpfb_subbands, c_nof_block_per_sync);
   CONSTANT c_stat_data_sz        : NATURAL := c_wpfb_sim.stat_data_sz;  -- = 2
@@ -253,7 +253,6 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS
   CONSTANT c_exp_remnant_subband_phase    : REAL := g_sp_remnant_phase + c_subband_phase_offset + c_subband_weight_phase;
   CONSTANT c_exp_remnant_subband_ampl     : REAL := REAL(c_wg_remnant_ampl) * c_sdp_wpfb_subband_sp_ampl_ratio * c_subband_weight_gain;
 
-  TYPE t_real_arr IS ARRAY (INTEGER RANGE <>) OF REAL;
   TYPE t_slv_64_subbands_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_sub-1);           -- 512
   TYPE t_slv_64_beamlets_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_beamlets_sdp-1);  -- 2*488 = 976
 
@@ -271,43 +270,22 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS
   CONSTANT c_bf_remnant_y_weight_re       : INTEGER := INTEGER(COMPLEX_RE(g_bf_remnant_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_y_phase));
   CONSTANT c_bf_remnant_y_weight_im       : INTEGER := INTEGER(COMPLEX_IM(g_bf_remnant_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_y_phase));
 
-  -- Model the SDP beamformer for one g_sp and S_pn-1 = 11 remnant signal inputs
-  FUNCTION bf_calculate_expected_beamlet(sp_subband_ampl, sp_subband_phase, sp_bf_gain, sp_bf_phase,
-                                         rem_subband_ampl, rem_subband_phase, rem_bf_gain, rem_bf_phase : REAL) RETURN t_real_arr IS  -- 0:3 = ampl, phase, re, im
-    CONSTANT c_nof_rem : REAL := REAL(c_sdp_S_pn - 1);  -- BF for one g_sp and 11 remnant signal inputs
-    VARIABLE v_sp_ampl, v_sp_phase, v_sp_re, v_sp_im     : REAL;
-    VARIABLE v_rem_ampl, v_rem_phase, v_rem_re, v_rem_im : REAL;
-    VARIABLE v_sum_ampl, v_sum_phase, v_sum_re, v_sum_im : REAL;
-    VARIABLE v_tuple                                     : t_real_arr(0 TO 3);
-  BEGIN
-    v_sp_ampl   := sp_subband_ampl * sp_bf_gain;
-    v_sp_phase  := sp_subband_phase + sp_bf_phase;
-    v_sp_re     := COMPLEX_RE(v_sp_ampl, v_sp_phase);
-    v_sp_im     := COMPLEX_IM(v_sp_ampl, v_sp_phase);
-    v_rem_ampl  := rem_subband_ampl * rem_bf_gain;
-    v_rem_phase := rem_subband_phase + rem_bf_phase;
-    v_rem_re    := COMPLEX_RE(v_rem_ampl, v_rem_phase);
-    v_rem_im    := COMPLEX_IM(v_rem_ampl, v_rem_phase);
-    v_sum_re    := v_sp_re + c_nof_rem * v_rem_re;  -- BF sum re
-    v_sum_im    := v_sp_im + c_nof_rem * v_rem_im;  -- BF sum im
-    v_sum_ampl  := COMPLEX_RADIUS(v_sum_re, v_sum_im);
-    v_sum_phase := COMPLEX_PHASE(v_sum_re, v_sum_im);
-    v_tuple     := (0 => v_sum_ampl, 1 => v_sum_phase, 2 => v_sum_re, 3 => v_sum_im);
-    RETURN v_tuple;
-  END;
-
+  -- Model the SDP local beamformer for one g_sp and S_pn - 1 remnant signal inputs
   -- . Beamlet internal
-  CONSTANT c_exp_beamlet_x_tuple          : t_real_arr(0 TO 3) := bf_calculate_expected_beamlet(
+  CONSTANT c_nof_remnant                  : NATURAL := c_sdp_S_pn - 1;
+  CONSTANT c_exp_beamlet_x_tuple          : t_real_arr(0 TO 3) := func_sdp_beamformer(
                                               c_exp_subband_ampl, c_exp_subband_phase, g_bf_x_gain, g_bf_x_phase,
-                                              c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_x_gain, g_bf_remnant_x_phase);
+                                              c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_x_gain, g_bf_remnant_x_phase,
+                                              c_nof_remnant);
   CONSTANT c_exp_beamlet_x_ampl           : REAL := c_exp_beamlet_x_tuple(0);
   CONSTANT c_exp_beamlet_x_phase          : REAL := c_exp_beamlet_x_tuple(1);
   CONSTANT c_exp_beamlet_x_re             : REAL := c_exp_beamlet_x_tuple(2);
   CONSTANT c_exp_beamlet_x_im             : REAL := c_exp_beamlet_x_tuple(3);
 
-  CONSTANT c_exp_beamlet_y_tuple          : t_real_arr(0 TO 3) := bf_calculate_expected_beamlet(
+  CONSTANT c_exp_beamlet_y_tuple          : t_real_arr(0 TO 3) := func_sdp_beamformer(
                                               c_exp_subband_ampl, c_exp_subband_phase, g_bf_y_gain, g_bf_y_phase,
-                                              c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_y_gain, g_bf_remnant_y_phase);
+                                              c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_y_gain, g_bf_remnant_y_phase,
+                                              c_nof_remnant);
   CONSTANT c_exp_beamlet_y_ampl           : REAL := c_exp_beamlet_y_tuple(0);
   CONSTANT c_exp_beamlet_y_phase          : REAL := c_exp_beamlet_y_tuple(1);
   CONSTANT c_exp_beamlet_y_re             : REAL := c_exp_beamlet_y_tuple(2);
@@ -467,7 +445,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS
 
   -- DUT
   SIGNAL ext_clk             : STD_LOGIC := '0';
-  SIGNAL ext_pps             : STD_LOGIC := '0'; 
+  SIGNAL ext_pps             : STD_LOGIC := '0';
 
   SIGNAL WDI                 : STD_LOGIC;
   SIGNAL INTA                : STD_LOGIC;
@@ -479,7 +457,7 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf IS
 
   SIGNAL SA_CLK              : STD_LOGIC := '1';
   SIGNAL si_lpbk_0           : STD_LOGIC_VECTOR(c_unb2c_board_tr_qsfp.bus_w-1 DOWNTO 0);
-   
+
   -- back transceivers
   SIGNAL JESD204B_SERIAL_DATA : STD_LOGIC_VECTOR(c_sdp_S_pn-1 downto 0);
   SIGNAL JESD204B_REFCLK      : STD_LOGIC := '1';
@@ -495,7 +473,7 @@ BEGIN
   ----------------------------------------------------------------------------
   ext_clk <= NOT ext_clk AFTER c_ext_clk_period/2;  -- External clock (200 MHz)
   eth_clk(0) <= NOT eth_clk(0) AFTER c_eth_clk_period/2;  -- Ethernet ref clock (125 MHz)
-  JESD204B_REFCLK <= NOT JESD204B_REFCLK AFTER c_bck_ref_clk_period/2;  -- JESD sample clock (200MHz) 
+  JESD204B_REFCLK <= NOT JESD204B_REFCLK AFTER c_bck_ref_clk_period/2;  -- JESD sample clock (200MHz)
   SA_CLK <= NOT SA_CLK AFTER c_sa_clk_period/2; -- Serial Gigabit IO sa clock (644 MHz)
   dest_rst <= '0' AFTER c_ext_clk_period * 10;
 
@@ -504,7 +482,7 @@ BEGIN
 
   ------------------------------------------------------------------------------
   -- External PPS
-  ------------------------------------------------------------------------------  
+  ------------------------------------------------------------------------------
   proc_common_gen_pulse(5, c_pps_period, '1', pps_rst, ext_clk, gen_pps);
   jesd204b_sysref <= gen_pps;
   ext_pps <= gen_pps;
@@ -544,8 +522,8 @@ BEGIN
     -- Transceiver clocks
     SA_CLK       => SA_CLK,
     -- front transceivers
-    QSFP_1_RX    => si_lpbk_0, 
-    QSFP_1_TX    => si_lpbk_0, 
+    QSFP_1_RX    => si_lpbk_0,
+    QSFP_1_TX    => si_lpbk_0,
 
     -- LEDs
     QSFP_LED     => open,
@@ -553,7 +531,7 @@ BEGIN
     -- back transceivers
     JESD204B_SERIAL_DATA => JESD204B_SERIAL_DATA,
     JESD204B_REFCLK      => JESD204B_REFCLK,
-  
+
     -- jesd204b syncronization signals
     JESD204B_SYSREF => jesd204b_sysref,
     JESD204B_SYNC_N => jesd204b_sync_n
@@ -633,7 +611,7 @@ BEGIN
   -- MM slave accesses via file IO
   ------------------------------------------------------------------------------
   tb_clk  <= NOT tb_clk AFTER c_tb_clk_period/2;    -- Testbench MM clock
-  
+
   p_mm_stimuli : PROCESS
     VARIABLE v_bsn                                  : NATURAL;
     VARIABLE v_data_lo, v_data_hi                   : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
@@ -845,7 +823,7 @@ BEGIN
     mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 3,                  0, tb_clk);  -- Write high part activates the init BSN
     mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 1, c_nof_clk_per_sync, tb_clk);  -- nof_block_per_sync
     mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 0,       16#00000003#, tb_clk);  -- Enable BS at PPS
-    
+
     -- Release PPS pulser, to get first PPS now and to start BSN source
     WAIT FOR 1 us;
     pps_rst <= '0';
@@ -880,14 +858,14 @@ BEGIN
     mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO  0), tb_clk);
     mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 1, current_bsn_wg(63 DOWNTO 32), tb_clk);
     proc_common_wait_some_cycles(tb_clk, 1);
-    
+
     -- Write scheduler BSN to trigger start of WG at next block
     v_bsn := TO_UINT(current_bsn_wg) + 2;
     ASSERT v_bsn <= c_bsn_start_wg REPORT "Too late to start WG: " & int_to_str(v_bsn) & " > " & int_to_str(c_bsn_start_wg) SEVERITY ERROR;
     v_bsn := c_bsn_start_wg;
     mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 0, v_bsn, tb_clk);  -- first write low then high part
     mmf_mm_bus_wr(c_mm_file_reg_bsn_scheduler_wg, 1,     0, tb_clk);  -- assume v_bsn < 2**31-1
-    
+
     ----------------------------------------------------------------------------
     -- Read weighted subband selector
     ----------------------------------------------------------------------------
@@ -1041,7 +1019,7 @@ BEGIN
 
     ---------------------------------------------------------------------------
     -- Read subband statistics
-    ---------------------------------------------------------------------------   
+    ---------------------------------------------------------------------------
     -- . the subband statistics are c_stat_data_sz = 2 word power values.
     -- . there are c_sdp_S_pn = 12 signal inputs A, B, C, D, E, F, G, H, I, J, K, L
     -- . there are c_sdp_N_sub = 512 subbands per signal input (SI, = signal path, SP)
@@ -1065,7 +1043,7 @@ BEGIN
           -- low part
           mmf_mm_bus_rd(c_mm_file_ram_st_sst, v_addr, rd_data, tb_clk);
           v_data_lo := rd_data;
-        ELSE      
+        ELSE
           -- high part
           mmf_mm_bus_rd(c_mm_file_ram_st_sst, v_addr, rd_data, tb_clk);
           v_data_hi := rd_data;
@@ -1082,7 +1060,7 @@ BEGIN
     sp_sst <= TO_UREAL(sp_ssts_arr2(c_pol_index)(g_subband));
     proc_common_wait_some_cycles(tb_clk, 1);
     proc_common_wait_some_cycles(ext_clk, 100);  -- delay for ease of view in Wave window
- 
+
     ---------------------------------------------------------------------------
     -- Read beamlet statistics
     ---------------------------------------------------------------------------
@@ -1128,17 +1106,17 @@ BEGIN
     END LOOP;
     proc_common_wait_some_cycles(tb_clk, 1);
     proc_common_wait_some_cycles(ext_clk, 100);  -- delay for ease of view in Wave window
- 
+
     ---------------------------------------------------------------------------
     -- Log WG, subband and beamlet statistics
-    --------------------------------------------------------------------------- 
-  
+    ---------------------------------------------------------------------------
+
     print_str("");
     print_str("WG:");
     print_str(". c_wg_ampl                            = " & int_to_str(c_wg_ampl));
     print_str(". c_exp_sp_power                       = " & real_to_str(c_exp_sp_power, 20, 1));
     print_str(". c_exp_sp_ast                         = " & real_to_str(c_exp_sp_ast, 20, 1));
-  
+
     print_str("");
     print_str("Subband weight:");
     print_str(". sp_subband_weight_gain               = " & real_to_str(sp_subband_weight_gain, 20, 6));
@@ -1230,8 +1208,8 @@ BEGIN
     ASSERT v_im < INTEGER(v_im_exp) + c_beamlet_output_delta REPORT "Wrong beamlet Y output (im) " & INTEGER'IMAGE(v_im) & " != " & REAL'IMAGE(v_im_exp) SEVERITY ERROR;
 
     ---------------------------------------------------------------------------
-    -- End Simulation 
-    ---------------------------------------------------------------------------   
+    -- End Simulation
+    ---------------------------------------------------------------------------
     tb_almost_end <= '1';
     proc_common_wait_some_cycles(ext_clk, 100);  -- delay for ease of view in Wave window
     proc_common_stop_simulation(TRUE, ext_clk, tb_almost_end, tb_end);
@@ -1318,24 +1296,24 @@ BEGIN
       proc_common_wait_until_high(ext_clk, rx_beamlet_sosi.valid);
       rx_beamlet_valid <= '1';
       -- Capture rx beamlets per longword in rx_beamlet_arr, for time series view in Wave window
-      rx_beamlet_arr_re(0) <= rx_beamlet_sosi.data(55 DOWNTO 48);  -- X
-      rx_beamlet_arr_im(0) <= rx_beamlet_sosi.data(63 DOWNTO 56);
-      rx_beamlet_arr_re(1) <= rx_beamlet_sosi.data(39 DOWNTO 32);  -- Y
-      rx_beamlet_arr_im(1) <= rx_beamlet_sosi.data(47 DOWNTO 40);
-      rx_beamlet_arr_re(2) <= rx_beamlet_sosi.data(23 DOWNTO 16);  -- X
-      rx_beamlet_arr_im(2) <= rx_beamlet_sosi.data(31 DOWNTO 24);
-      rx_beamlet_arr_re(3) <= rx_beamlet_sosi.data( 7 DOWNTO 0);   -- Y
-      rx_beamlet_arr_im(3) <= rx_beamlet_sosi.data(15 DOWNTO 8);
+      rx_beamlet_arr_im(0) <= rx_beamlet_sosi.data(63 DOWNTO 56);  -- X
+      rx_beamlet_arr_re(0) <= rx_beamlet_sosi.data(55 DOWNTO 48);
+      rx_beamlet_arr_im(1) <= rx_beamlet_sosi.data(47 DOWNTO 40);  -- Y
+      rx_beamlet_arr_re(1) <= rx_beamlet_sosi.data(39 DOWNTO 32);
+      rx_beamlet_arr_im(2) <= rx_beamlet_sosi.data(31 DOWNTO 24);  -- X
+      rx_beamlet_arr_re(2) <= rx_beamlet_sosi.data(23 DOWNTO 16);
+      rx_beamlet_arr_im(3) <= rx_beamlet_sosi.data(15 DOWNTO 8);   -- Y
+      rx_beamlet_arr_re(3) <= rx_beamlet_sosi.data( 7 DOWNTO 0);
       IF I < c_sdp_cep_nof_beamlets_per_block / c_nof_beamlets_per_data THEN
         -- Only capture the first beamlets block of each packet in rx_beamlet_list
-        rx_beamlet_list_re(I*4 + 0) <= rx_beamlet_sosi.data(55 DOWNTO 48);  -- X
-        rx_beamlet_list_im(I*4 + 0) <= rx_beamlet_sosi.data(63 DOWNTO 56);
-        rx_beamlet_list_re(I*4 + 1) <= rx_beamlet_sosi.data(39 DOWNTO 32);  -- Y
-        rx_beamlet_list_im(I*4 + 1) <= rx_beamlet_sosi.data(47 DOWNTO 40);
-        rx_beamlet_list_re(I*4 + 2) <= rx_beamlet_sosi.data(23 DOWNTO 16);  -- X
-        rx_beamlet_list_im(I*4 + 2) <= rx_beamlet_sosi.data(31 DOWNTO 24);
-        rx_beamlet_list_re(I*4 + 3) <= rx_beamlet_sosi.data( 7 DOWNTO 0);   -- Y
-        rx_beamlet_list_im(I*4 + 3) <= rx_beamlet_sosi.data(15 DOWNTO 8);
+        rx_beamlet_list_im(I*4 + 0) <= rx_beamlet_sosi.data(63 DOWNTO 56);  -- X
+        rx_beamlet_list_re(I*4 + 0) <= rx_beamlet_sosi.data(55 DOWNTO 48);
+        rx_beamlet_list_im(I*4 + 1) <= rx_beamlet_sosi.data(47 DOWNTO 40);  -- Y
+        rx_beamlet_list_re(I*4 + 1) <= rx_beamlet_sosi.data(39 DOWNTO 32);
+        rx_beamlet_list_im(I*4 + 2) <= rx_beamlet_sosi.data(31 DOWNTO 24);  -- X
+        rx_beamlet_list_re(I*4 + 2) <= rx_beamlet_sosi.data(23 DOWNTO 16);
+        rx_beamlet_list_im(I*4 + 3) <= rx_beamlet_sosi.data(15 DOWNTO 8);   -- Y
+        rx_beamlet_list_re(I*4 + 3) <= rx_beamlet_sosi.data( 7 DOWNTO 0);
       END IF;
       proc_common_wait_until_high(ext_clk, rx_beamlet_sosi.valid);
       -- Use at least one WAIT instead of proc_common_wait_some_cycles() to
diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd
index 0d6c1fd69a6e2b9fb53dc52eb7b877469314c054..a54b08c9df66879f11ab20630509a0d7882b724c 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_bf_ring/tb_lofar2_unb2c_sdp_station_bf_ring.vhd
@@ -265,7 +265,6 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS
   CONSTANT c_exp_remnant_subband_phase    : REAL := g_sp_remnant_phase + c_subband_phase_offset + c_subband_weight_phase;
   CONSTANT c_exp_remnant_subband_ampl     : REAL := REAL(c_wg_remnant_ampl) * c_sdp_wpfb_subband_sp_ampl_ratio * c_subband_weight_gain;
 
-  TYPE t_real_arr IS ARRAY (INTEGER RANGE <>) OF REAL;
   TYPE t_slv_64_subbands_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_sub-1);           -- 512
   TYPE t_slv_64_beamlets_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_beamlets_sdp-1);  -- 2*488 = 976
 
@@ -283,43 +282,22 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_bf_ring IS
   CONSTANT c_bf_remnant_y_weight_re       : INTEGER := INTEGER(COMPLEX_RE(g_bf_remnant_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_y_phase));
   CONSTANT c_bf_remnant_y_weight_im       : INTEGER := INTEGER(COMPLEX_IM(g_bf_remnant_y_gain * REAL(c_sdp_unit_bf_weight), g_bf_remnant_y_phase));
 
-  -- Model the SDP beamformer for one g_global_sp and g_nof_rn * S_pn - 1 remnant signal inputs
-  FUNCTION bf_calculate_expected_beamlet(sp_subband_ampl, sp_subband_phase, sp_bf_gain, sp_bf_phase,
-                                         rem_subband_ampl, rem_subband_phase, rem_bf_gain, rem_bf_phase : REAL) RETURN t_real_arr IS  -- 0:3 = ampl, phase, re, im
-    CONSTANT c_nof_rem : REAL := REAL(g_nof_rn * c_sdp_S_pn - 1);  -- BF for one g_global_sp and N_rn * S_PN - 1 remnant signal inputs
-    VARIABLE v_sp_ampl, v_sp_phase, v_sp_re, v_sp_im     : REAL;
-    VARIABLE v_rem_ampl, v_rem_phase, v_rem_re, v_rem_im : REAL;
-    VARIABLE v_sum_ampl, v_sum_phase, v_sum_re, v_sum_im : REAL;
-    VARIABLE v_tuple                                     : t_real_arr(0 TO 3);
-  BEGIN
-    v_sp_ampl   := sp_subband_ampl * sp_bf_gain;
-    v_sp_phase  := sp_subband_phase + sp_bf_phase;
-    v_sp_re     := COMPLEX_RE(v_sp_ampl, v_sp_phase);
-    v_sp_im     := COMPLEX_IM(v_sp_ampl, v_sp_phase);
-    v_rem_ampl  := rem_subband_ampl * rem_bf_gain;
-    v_rem_phase := rem_subband_phase + rem_bf_phase;
-    v_rem_re    := COMPLEX_RE(v_rem_ampl, v_rem_phase);
-    v_rem_im    := COMPLEX_IM(v_rem_ampl, v_rem_phase);
-    v_sum_re    := v_sp_re + c_nof_rem * v_rem_re;  -- BF sum re
-    v_sum_im    := v_sp_im + c_nof_rem * v_rem_im;  -- BF sum im
-    v_sum_ampl  := COMPLEX_RADIUS(v_sum_re, v_sum_im);
-    v_sum_phase := COMPLEX_PHASE(v_sum_re, v_sum_im);
-    v_tuple     := (0 => v_sum_ampl, 1 => v_sum_phase, 2 => v_sum_re, 3 => v_sum_im);
-    RETURN v_tuple;
-  END;
-
+  -- Model the SDP (remote) beamformer for one g_global_sp and g_nof_rn * S_pn - 1 remnant signal inputs
   -- . Beamlet internal
-  CONSTANT c_exp_beamlet_x_tuple          : t_real_arr(0 TO 3) := bf_calculate_expected_beamlet(
+  CONSTANT c_nof_remnant                  : NATURAL := g_nof_rn * c_sdp_S_pn - 1;
+  CONSTANT c_exp_beamlet_x_tuple          : t_real_arr(0 TO 3) := func_sdp_beamformer(
                                               c_exp_subband_ampl, c_exp_subband_phase, g_bf_x_gain, g_bf_x_phase,
-                                              c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_x_gain, g_bf_remnant_x_phase);
+                                              c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_x_gain, g_bf_remnant_x_phase,
+                                              c_nof_remnant);
   CONSTANT c_exp_beamlet_x_ampl           : REAL := c_exp_beamlet_x_tuple(0);
   CONSTANT c_exp_beamlet_x_phase          : REAL := c_exp_beamlet_x_tuple(1);
   CONSTANT c_exp_beamlet_x_re             : REAL := c_exp_beamlet_x_tuple(2);
   CONSTANT c_exp_beamlet_x_im             : REAL := c_exp_beamlet_x_tuple(3);
 
-  CONSTANT c_exp_beamlet_y_tuple          : t_real_arr(0 TO 3) := bf_calculate_expected_beamlet(
+  CONSTANT c_exp_beamlet_y_tuple          : t_real_arr(0 TO 3) := func_sdp_beamformer(
                                               c_exp_subband_ampl, c_exp_subband_phase, g_bf_y_gain, g_bf_y_phase,
-                                              c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_y_gain, g_bf_remnant_y_phase);
+                                              c_exp_remnant_subband_ampl, c_exp_remnant_subband_phase, g_bf_remnant_y_gain, g_bf_remnant_y_phase,
+                                              c_nof_remnant);
   CONSTANT c_exp_beamlet_y_ampl           : REAL := c_exp_beamlet_y_tuple(0);
   CONSTANT c_exp_beamlet_y_phase          : REAL := c_exp_beamlet_y_tuple(1);
   CONSTANT c_exp_beamlet_y_re             : REAL := c_exp_beamlet_y_tuple(2);
@@ -1436,24 +1414,24 @@ BEGIN
       proc_common_wait_until_high(ext_clk, rx_beamlet_sosi.valid);
       rx_beamlet_valid <= '1';
       -- Capture rx beamlets per longword in rx_beamlet_arr, for time series view in Wave window
-      rx_beamlet_arr_re(0) <= rx_beamlet_sosi.data(55 DOWNTO 48);  -- X
-      rx_beamlet_arr_im(0) <= rx_beamlet_sosi.data(63 DOWNTO 56);
-      rx_beamlet_arr_re(1) <= rx_beamlet_sosi.data(39 DOWNTO 32);  -- Y
-      rx_beamlet_arr_im(1) <= rx_beamlet_sosi.data(47 DOWNTO 40);
-      rx_beamlet_arr_re(2) <= rx_beamlet_sosi.data(23 DOWNTO 16);  -- X
-      rx_beamlet_arr_im(2) <= rx_beamlet_sosi.data(31 DOWNTO 24);
-      rx_beamlet_arr_re(3) <= rx_beamlet_sosi.data( 7 DOWNTO 0);   -- Y
-      rx_beamlet_arr_im(3) <= rx_beamlet_sosi.data(15 DOWNTO 8);
+      rx_beamlet_arr_im(0) <= rx_beamlet_sosi.data(63 DOWNTO 56);  -- X
+      rx_beamlet_arr_re(0) <= rx_beamlet_sosi.data(55 DOWNTO 48);
+      rx_beamlet_arr_im(1) <= rx_beamlet_sosi.data(47 DOWNTO 40);  -- Y
+      rx_beamlet_arr_re(1) <= rx_beamlet_sosi.data(39 DOWNTO 32);
+      rx_beamlet_arr_im(2) <= rx_beamlet_sosi.data(31 DOWNTO 24);  -- X
+      rx_beamlet_arr_re(2) <= rx_beamlet_sosi.data(23 DOWNTO 16);
+      rx_beamlet_arr_im(3) <= rx_beamlet_sosi.data(15 DOWNTO 8);   -- Y
+      rx_beamlet_arr_re(3) <= rx_beamlet_sosi.data( 7 DOWNTO 0);
       IF I < c_sdp_cep_nof_beamlets_per_block / c_nof_beamlets_per_data THEN
         -- Only capture the first beamlets block of each packet in rx_beamlet_list
-        rx_beamlet_list_re(I*4 + 0) <= rx_beamlet_sosi.data(55 DOWNTO 48);  -- X
-        rx_beamlet_list_im(I*4 + 0) <= rx_beamlet_sosi.data(63 DOWNTO 56);
-        rx_beamlet_list_re(I*4 + 1) <= rx_beamlet_sosi.data(39 DOWNTO 32);  -- Y
-        rx_beamlet_list_im(I*4 + 1) <= rx_beamlet_sosi.data(47 DOWNTO 40);
-        rx_beamlet_list_re(I*4 + 2) <= rx_beamlet_sosi.data(23 DOWNTO 16);  -- X
-        rx_beamlet_list_im(I*4 + 2) <= rx_beamlet_sosi.data(31 DOWNTO 24);
-        rx_beamlet_list_re(I*4 + 3) <= rx_beamlet_sosi.data( 7 DOWNTO 0);   -- Y
-        rx_beamlet_list_im(I*4 + 3) <= rx_beamlet_sosi.data(15 DOWNTO 8);
+        rx_beamlet_list_im(I*4 + 0) <= rx_beamlet_sosi.data(63 DOWNTO 56);  -- X
+        rx_beamlet_list_re(I*4 + 0) <= rx_beamlet_sosi.data(55 DOWNTO 48);
+        rx_beamlet_list_im(I*4 + 1) <= rx_beamlet_sosi.data(47 DOWNTO 40);  -- Y
+        rx_beamlet_list_re(I*4 + 1) <= rx_beamlet_sosi.data(39 DOWNTO 32);
+        rx_beamlet_list_im(I*4 + 2) <= rx_beamlet_sosi.data(31 DOWNTO 24);  -- X
+        rx_beamlet_list_re(I*4 + 2) <= rx_beamlet_sosi.data(23 DOWNTO 16);
+        rx_beamlet_list_im(I*4 + 3) <= rx_beamlet_sosi.data(15 DOWNTO 8);   -- Y
+        rx_beamlet_list_re(I*4 + 3) <= rx_beamlet_sosi.data( 7 DOWNTO 0);
       END IF;
       proc_common_wait_until_high(ext_clk, rx_beamlet_sosi.valid);
       -- Use at least one WAIT instead of proc_common_wait_some_cycles() to
diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub.vhd
index a22fd834f9ef73e68976c18c5bc16c31cb4f0cef..72d65882396fecb24585fe49f4cff215d85f03e2 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_fsub/tb_lofar2_unb2c_sdp_station_fsub.vhd
@@ -33,8 +33,11 @@
 --   2) Read current BSN from reg_bsn_scheduler_wg and write reg_bsn_scheduler_wg
 --      to trigger start of WG at BSN.
 --
---   3) Read subband statistics (SST) via MM and verify with exp_subband_sst at g_subband.
+--   3) Read subband statistics (SST) via MM and verify with exp_sp_subband_sst at g_subband.
 --      . use weighted subbands (default selected by MM)
+--      . g_use_cross_weight = TRUE, then use g_sp_cross_subband_weight_gain/phase and c_cross_sp
+--      . g_use_cross_weight = FALSE, then do not use c_cross_sp, so only use g_sp and
+--        g_co_subband_weight_gain/phase
 --
 --   4) View in wave window
 --      . in_sosi.sop and in_data in u_si_arr(g_sp) to check that:
@@ -42,10 +45,10 @@
 --        - WG amplitude = 8191 (is full scale - 1) when wg_ampl = 1.0
 --      . pfb_sosi_arr(c_pfb_index).im/re and fsub_sosi_arr(c_pfb_index).im/re
 --        in u_fsub in decimal radix and analog format to check that subband
---        phase is g_subband_weight_phase phase as set by the subband weight.
+--        phase is g_co_subband_weight_phase phase as set by the subband weight.
 --        - Raw: pfb_sosi_arr = atan2(-65195 / 0) = -90 degrees
 --        - Weighted: fsub_sosi_arr = atan2(-56457 / 32598) = -60 degrees
---          --> rotated expected g_subband_weight_phase = -60 - -90 = +30 degrees.
+--          --> rotated expected g_co_subband_weight_phase = -60 - -90 = +30 degrees.
 --
 -- Usage:
 --   > as 7    # default
@@ -71,16 +74,22 @@ USE dp_lib.dp_stream_pkg.ALL;
 USE diag_lib.diag_pkg.ALL;
 USE wpfb_lib.wpfb_pkg.ALL;
 USE lofar2_sdp_lib.sdp_pkg.ALL;
+USE lofar2_sdp_lib.tb_sdp_pkg.ALL;
 USE unb2c_board_lib.unb2c_board_pkg.ALL;
 
 ENTITY tb_lofar2_unb2c_sdp_station_fsub IS
   GENERIC (
-    g_sp                   : NATURAL := 3;    -- signal path index in range(S_pn = 12)
-    g_wg_ampl              : REAL := 1.0;     -- WG normalized amplitude
-    g_subband              : NATURAL := 102;  -- select subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz
-    g_subband_weight_gain  : REAL := 1.0;     -- subband weight normalized gain
-    g_subband_weight_phase : REAL := 30.0;    -- subband weight phase rotation in degrees
-    g_read_all_SST         : BOOLEAN := TRUE  -- when FALSE only read SST for g_subband, to save sim time
+    g_sp                            : NATURAL := 3;    -- signal path index in range(S_pn = 12) of co-polarization
+    g_co_wg_ampl                    : REAL := 0.5;     -- WG normalized amplitude, use same WG settings for both polarizations (g_sp and c_cross_sp)
+    g_cross_wg_ampl                 : REAL := 0.4;     -- WG normalized amplitude, use same WG settings for both polarizations (g_sp and c_cross_sp)
+    g_cross_wg_phase                : REAL := 90.0;    -- WG phase in degrees for cross-sp, relative to co-sp
+    g_subband                       : NATURAL := 102;  -- select subband at index 102 = 102/1024 * 200MHz = 19.921875 MHz
+    g_co_subband_weight_gain        : REAL := 1.0;     -- subband weight normalized gain, for co-polarization in g_sp
+    g_co_subband_weight_phase       : REAL := 30.0;    -- subband weight phase rotation in degrees, for co-polarization in g_sp
+    g_use_cross_weight              : BOOLEAN := TRUE;
+    g_sp_cross_subband_weight_gain  : REAL := 0.5;     -- subband weight normalized gain, for cross polarization of g_sp
+    g_sp_cross_subband_weight_phase : REAL := -10.0;    -- subband weight phase rotation in degrees, for cross polarization of g_sp
+    g_read_all_SST                  : BOOLEAN := TRUE  -- when FALSE only read SST for g_subband, to save sim time
   );
 END tb_lofar2_unb2c_sdp_station_fsub;
 
@@ -91,6 +100,9 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_fsub IS
   CONSTANT c_node_nr         : NATURAL := 0;
   CONSTANT c_init_bsn        : NATURAL := 17;  -- some recognizable value >= 0
 
+  -- signal path index of cross-polarization
+  CONSTANT c_cross_sp        : NATURAL := sel_a_b(g_sp MOD c_sdp_N_pol = 0, g_sp + 1, g_sp - 1);
+
   CONSTANT c_id              : STD_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
   CONSTANT c_version         : STD_LOGIC_VECTOR(1 DOWNTO 0) := "00";
   CONSTANT c_fw_version      : t_unb2c_board_fw_version := (1, 0);
@@ -114,38 +126,62 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_fsub IS
   -- WG
   CONSTANT c_bsn_start_wg         : NATURAL := c_init_bsn + 2;  -- start WG at this BSN to instead of some BSN, to avoid mismatches in exact expected data values
   -- .ampl
-  CONSTANT c_wg_ampl              : NATURAL := NATURAL(g_wg_ampl * REAL(c_sdp_FS_adc));  -- in number of lsb
-  CONSTANT c_exp_sp_power         : REAL := REAL(c_wg_ampl**2) / 2.0;
-  CONSTANT c_exp_sp_ast           : REAL := c_exp_sp_power * REAL(c_nof_clk_per_sync);
+  CONSTANT c_co_wg_ampl           : NATURAL := NATURAL(g_co_wg_ampl * REAL(c_sdp_FS_adc));  -- in number of lsb
+  CONSTANT c_cross_wg_ampl        : NATURAL := NATURAL(g_cross_wg_ampl * REAL(c_sdp_FS_adc));  -- in number of lsb
+  CONSTANT c_exp_co_sp_power      : REAL := REAL(c_co_wg_ampl**2) / 2.0;
+  CONSTANT c_exp_cross_sp_power   : REAL := REAL(c_cross_wg_ampl**2) / 2.0;
+  CONSTANT c_exp_co_sp_ast        : REAL := c_exp_co_sp_power * REAL(c_nof_clk_per_sync);
+  CONSTANT c_exp_cross_sp_ast     : REAL := c_exp_cross_sp_power * REAL(c_nof_clk_per_sync);
+  -- . freq
+  CONSTANT c_subband_freq         : REAL := REAL(g_subband) / REAL(c_sdp_N_fft);                   -- normalized by fs = f_adc = 200 MHz is dp_clk
   -- . phase
   CONSTANT c_subband_phase        : REAL := 0.0;  -- wanted subband phase in degrees = WG phase at sop
-  CONSTANT c_subband_freq         : REAL := REAL(g_subband) / REAL(c_sdp_N_fft);                   -- normalized by fs = f_adc = 200 MHz is dp_clk
   CONSTANT c_wg_latency           : INTEGER := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
   CONSTANT c_wg_phase_offset      : REAL := 360.0 * REAL(c_wg_latency) * c_subband_freq;  -- c_diag_wg_latency is in dp_clk cycles
   CONSTANT c_wg_phase             : REAL := c_subband_phase + c_wg_phase_offset;  -- WG phase in degrees
+  CONSTANT c_co_wg_phase          : REAL := c_wg_phase;
+  CONSTANT c_cross_wg_phase       : REAL := c_wg_phase + g_cross_wg_phase;
+  CONSTANT c_subband_phase_offset : REAL := -90.0;  -- WG with zero phase sinus yields subband with -90 degrees phase (negative Im, zero Re)
+  CONSTANT c_co_subband_phase     : REAL := c_subband_phase_offset + c_co_wg_phase;
+  CONSTANT c_cross_subband_phase  : REAL := c_subband_phase_offset + c_cross_wg_phase;
 
   -- FSUB
-  -- . WPFB
-  CONSTANT c_pol_index                      : NATURAL := g_sp MOD c_sdp_Q_fft;
-  CONSTANT c_pfb_index                      : NATURAL := g_sp / c_sdp_Q_fft;  -- only read used WPFB unit out of range(c_sdp_P_pfb = 6)
-  CONSTANT c_exp_subband_ampl_raw           : REAL := REAL(c_wg_ampl) * c_sdp_wpfb_subband_sp_ampl_ratio;
-  CONSTANT c_exp_subband_ampl_weighted      : REAL := c_exp_subband_ampl_raw * g_subband_weight_gain;
-  CONSTANT c_exp_subband_power_raw          : REAL := c_exp_subband_ampl_raw**2.0;  -- complex signal ampl, so power is A**2 (not A**2 / 2 as for real)
-  CONSTANT c_exp_subband_power_weighted     : REAL := c_exp_subband_ampl_weighted**2.0;  -- complex signal ampl, so power is A**2 (not A**2 / 2 as for real)
-  CONSTANT c_exp_subband_sst_raw            : REAL := c_exp_subband_power_raw * REAL(c_nof_block_per_sync);
-  CONSTANT c_exp_subband_sst_weighted       : REAL := c_exp_subband_power_weighted * REAL(c_nof_block_per_sync);
+  CONSTANT c_pol_index            : NATURAL := g_sp MOD c_sdp_Q_fft;
+  CONSTANT c_pfb_index            : NATURAL := g_sp / c_sdp_Q_fft;  -- only read used WPFB unit out of range(c_sdp_P_pfb = 6)
+
+  CONSTANT c_exp_co_subband_ampl_raw          : REAL := REAL(c_co_wg_ampl) * c_sdp_wpfb_subband_sp_ampl_ratio;
+  CONSTANT c_exp_cross_subband_ampl_raw       : REAL := REAL(c_cross_wg_ampl) * c_sdp_wpfb_subband_sp_ampl_ratio;
+  CONSTANT c_exp_co_subband_ampl_weighted     : REAL := c_exp_co_subband_ampl_raw * g_co_subband_weight_gain;
+  CONSTANT c_exp_cross_subband_ampl_weighted  : REAL := c_exp_cross_subband_ampl_raw * 1.0;  -- unit gain, this is co gain for cross sp
+  CONSTANT c_exp_jones_subband_tuple          : t_real_arr(0 TO 3) := func_sdp_subband_equalizer(
+                                                c_exp_co_subband_ampl_raw, c_co_subband_phase, g_co_subband_weight_gain, g_co_subband_weight_phase,
+                                                c_exp_cross_subband_ampl_raw, c_cross_subband_phase, g_sp_cross_subband_weight_gain, g_sp_cross_subband_weight_phase);
+  CONSTANT c_exp_sp_subband_ampl_weighted     : REAL := sel_a_b(g_use_cross_weight, c_exp_jones_subband_tuple(0), c_exp_co_subband_ampl_weighted);
+
+  CONSTANT c_exp_co_subband_power_raw         : REAL := c_exp_co_subband_ampl_raw**2.0;  -- complex signal ampl, so power is A**2 (not A**2 / 2 as for real)
+  CONSTANT c_exp_cross_subband_power_raw      : REAL := c_exp_cross_subband_ampl_raw**2.0;
+  CONSTANT c_exp_sp_subband_power_weighted    : REAL := c_exp_sp_subband_ampl_weighted**2.0;
+  CONSTANT c_exp_cross_subband_power_weighted : REAL := c_exp_cross_subband_ampl_weighted**2.0;
+  CONSTANT c_exp_co_subband_sst_raw           : REAL := c_exp_co_subband_power_raw * REAL(c_nof_block_per_sync);
+  CONSTANT c_exp_cross_subband_sst_raw        : REAL := c_exp_cross_subband_power_raw * REAL(c_nof_block_per_sync);
+  CONSTANT c_exp_sp_subband_sst_weighted      : REAL := c_exp_sp_subband_power_weighted * REAL(c_nof_block_per_sync);
+  CONSTANT c_exp_cross_subband_sst_weighted   : REAL := c_exp_cross_subband_power_weighted * REAL(c_nof_block_per_sync);
 
   -- . expected limit values, obtained with print_str() for g_subband = 102,
-  --   g_wg_ampl = 1.0, g_subband_weight_gain = 1.0, g_subband_weight_phase = 30.0
-  CONSTANT c_exp_subband_sst_leakage_snr_dB   : REAL := 70.0;  -- < 74.913
-  CONSTANT c_exp_subband_sst_crosstalk_snr_dB : REAL := 90.0;  -- < 96.284
+  --   g_co_wg_ampl = 1.0, g_co_subband_weight_gain = 1.0, g_co_subband_weight_phase = 30.0
+  CONSTANT c_exp_sp_subband_sst_leakage_snr_dB   : REAL := 70.0;  -- < 74.913
+  CONSTANT c_exp_sp_subband_sst_crosstalk_snr_dB : REAL := 90.0;  -- < 96.284
 
   TYPE t_real_arr IS ARRAY (INTEGER RANGE <>) OF REAL;
   TyPE t_slv_64_subbands_arr IS ARRAY (INTEGER RANGE <>) OF t_slv_64_arr(0 TO c_sdp_N_sub-1);
 
   -- . Subband weights for selected g_sp
-  CONSTANT c_subband_weight_re   : INTEGER := INTEGER(g_subband_weight_gain * REAL(c_sdp_unit_sub_weight) * COS(g_subband_weight_phase * MATH_2_PI / 360.0));
-  CONSTANT c_subband_weight_im   : INTEGER := INTEGER(g_subband_weight_gain * REAL(c_sdp_unit_sub_weight) * SIN(g_subband_weight_phase * MATH_2_PI / 360.0));
+  CONSTANT c_co_subband_weight_re : INTEGER := INTEGER(g_co_subband_weight_gain * REAL(c_sdp_unit_sub_weight) * COS(g_co_subband_weight_phase * MATH_2_PI / 360.0));
+  CONSTANT c_co_subband_weight_im : INTEGER := INTEGER(g_co_subband_weight_gain * REAL(c_sdp_unit_sub_weight) * SIN(g_co_subband_weight_phase * MATH_2_PI / 360.0));
+
+  -- . Subband weights cross for selected g_sp
+  CONSTANT c_sp_cross_subband_weight_re : INTEGER := INTEGER(g_sp_cross_subband_weight_gain * REAL(c_sdp_unit_sub_weight) * COS(g_sp_cross_subband_weight_phase * MATH_2_PI / 360.0));
+  CONSTANT c_sp_cross_subband_weight_im : INTEGER := INTEGER(g_sp_cross_subband_weight_gain * REAL(c_sdp_unit_sub_weight) * SIN(g_sp_cross_subband_weight_phase * MATH_2_PI / 360.0));
 
   -- MM
   -- . Address widths of a single MM instance
@@ -153,12 +189,13 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_fsub IS
   -- . Address spans of a single MM instance
   CONSTANT c_mm_span_reg_diag_wg          : NATURAL := 2**c_addr_w_reg_diag_wg;
 
-  CONSTANT c_mm_file_reg_bsn_source_v2    : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2";
-  CONSTANT c_mm_file_reg_bsn_scheduler_wg : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SCHEDULER";
-  CONSTANT c_mm_file_reg_diag_wg          : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_WG";
-  CONSTANT c_mm_file_ram_equalizer_gains  : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_EQUALIZER_GAINS";
-  CONSTANT c_mm_file_reg_dp_selector      : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_DP_SELECTOR";
-  CONSTANT c_mm_file_ram_st_sst           : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_SST";
+  CONSTANT c_mm_file_reg_bsn_source_v2         : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SOURCE_V2";
+  CONSTANT c_mm_file_reg_bsn_scheduler_wg      : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_BSN_SCHEDULER";
+  CONSTANT c_mm_file_reg_diag_wg               : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_WG";
+  CONSTANT c_mm_file_ram_equalizer_gains       : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_EQUALIZER_GAINS";
+  CONSTANT c_mm_file_ram_equalizer_gains_cross : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_EQUALIZER_GAINS_CROSS";
+  CONSTANT c_mm_file_reg_dp_selector           : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "REG_DP_SELECTOR";
+  CONSTANT c_mm_file_ram_st_sst                : STRING := mmf_unb_file_prefix(c_unb_nr, c_node_nr) & "RAM_ST_SST";
 
   -- Tb
   SIGNAL tb_end              : STD_LOGIC := '0';
@@ -177,24 +214,33 @@ ARCHITECTURE tb OF tb_lofar2_unb2c_sdp_station_fsub IS
   SIGNAL sp_subband_ssts_arr2            : t_slv_64_subbands_arr(c_sdp_N_pol-1 DOWNTO 0);   -- [pol][sub]
   SIGNAL sp_subband_sst_sum_arr          : t_real_arr(c_sdp_N_pol-1 DOWNTO 0) := (OTHERS => 0.0);
   SIGNAL sp_subband_sst                  : REAL := 0.0;
+  SIGNAL sp_cross_subband_sst            : REAL := 0.0;
   SIGNAL sp_subband_sst_leakage          : REAL := 0.0;
   SIGNAL sp_subband_sst_leakage_snr_dB   : REAL := 0.0;  -- signal to noise (leakage) ratio
   SIGNAL sp_subband_sst_crosstalk        : REAL := 0.0;
   SIGNAL sp_subband_sst_crosstalk_snr_dB : REAL := 0.0;  -- signal to noise (crosstalk) ration
 
-  SIGNAL exp_subband_ampl    : REAL := 0.0;
-  SIGNAL exp_subband_power   : REAL := 0.0;
-  SIGNAL exp_subband_sst     : REAL := 0.0;
-  SIGNAL stat_data           : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0);
+  SIGNAL exp_sp_subband_ampl       : REAL := 0.0;
+  SIGNAL exp_sp_subband_power      : REAL := 0.0;
+  SIGNAL exp_sp_subband_sst        : REAL := 0.0;
+  SIGNAL exp_cross_subband_sst  : REAL := 0.0;
+  SIGNAL stat_data              : STD_LOGIC_VECTOR(c_longword_w-1 DOWNTO 0);
 
   -- . Selector
   SIGNAL sst_offload_weighted_subbands     : STD_LOGIC;
 
   -- . Subband equalizer
-  SIGNAL sp_subband_weight_re    : INTEGER := 0;
-  SIGNAL sp_subband_weight_im    : INTEGER := 0;
-  SIGNAL sp_subband_weight_gain  : REAL := 0.0;
-  SIGNAL sp_subband_weight_phase : REAL := 0.0;
+  SIGNAL sp_co_subband_weight_re    : INTEGER := 0;
+  SIGNAL sp_co_subband_weight_im    : INTEGER := 0;
+  SIGNAL sp_co_subband_weight_gain  : REAL := 0.0;
+  SIGNAL sp_co_subband_weight_phase : REAL := 0.0;
+  SIGNAL sp_co_subband_weight_val   : STD_LOGIC := '0';
+
+  SIGNAL sp_cross_subband_weight_re    : INTEGER := 0;
+  SIGNAL sp_cross_subband_weight_im    : INTEGER := 0;
+  SIGNAL sp_cross_subband_weight_gain  : REAL := 0.0;
+  SIGNAL sp_cross_subband_weight_phase : REAL := 0.0;
+  SIGNAL sp_cross_subband_weight_val   : STD_LOGIC := '0';
 
   -- DUT
   SIGNAL ext_clk             : STD_LOGIC := '0';
@@ -279,9 +325,10 @@ BEGIN
   );
 
   -- Raw or weighted subbands
-  exp_subband_ampl  <= sel_a_b(sst_offload_weighted_subbands = '0', c_exp_subband_ampl_raw, c_exp_subband_ampl_weighted);
-  exp_subband_power <= sel_a_b(sst_offload_weighted_subbands = '0', c_exp_subband_power_raw, c_exp_subband_power_weighted);
-  exp_subband_sst   <= sel_a_b(sst_offload_weighted_subbands = '0', c_exp_subband_sst_raw, c_exp_subband_sst_weighted);
+  exp_sp_subband_ampl      <= sel_a_b(sst_offload_weighted_subbands = '0', c_exp_co_subband_ampl_raw, c_exp_sp_subband_ampl_weighted);
+  exp_sp_subband_power     <= sel_a_b(sst_offload_weighted_subbands = '0', c_exp_co_subband_power_raw, c_exp_sp_subband_power_weighted);
+  exp_sp_subband_sst       <= sel_a_b(sst_offload_weighted_subbands = '0', c_exp_co_subband_sst_raw, c_exp_sp_subband_sst_weighted);
+  exp_cross_subband_sst <= sel_a_b(sst_offload_weighted_subbands = '0', c_exp_cross_subband_sst_raw, c_exp_cross_subband_sst_weighted);
 
   ------------------------------------------------------------------------------
   -- MM slave accesses via file IO
@@ -327,11 +374,21 @@ BEGIN
     --   1 : phase[15:0]
     --   2 : freq[30:0]
     --   3 : ampl[16:0]
+    -- g_sp is co-polarization
     v_offset := g_sp * c_mm_span_reg_diag_wg;
     mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 0, 1024*2**16 + 1, tb_clk);  -- nof_samples, mode calc
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 1, INTEGER(c_wg_phase * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 1, INTEGER(c_co_wg_phase * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
     mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 2, INTEGER(REAL(g_subband) * c_sdp_wg_subband_freq_unit), tb_clk);  -- freq
-    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 3, INTEGER(REAL(c_wg_ampl) * c_sdp_wg_ampl_lsb), tb_clk);  -- ampl
+    mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 3, INTEGER(REAL(c_co_wg_ampl) * c_sdp_wg_ampl_lsb), tb_clk);  -- ampl
+
+    IF g_use_cross_weight THEN
+      -- c_cross_sp is cross-polarization for g_sp, use same WG settings for c_cross_sp as for g_sp
+      v_offset := c_cross_sp * c_mm_span_reg_diag_wg;
+      mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 0, 1024*2**16 + 1, tb_clk);  -- nof_samples, mode calc
+      mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 1, INTEGER(c_cross_wg_phase * c_diag_wg_phase_unit), tb_clk);  -- phase offset in degrees
+      mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 2, INTEGER(REAL(g_subband) * c_sdp_wg_subband_freq_unit), tb_clk);  -- freq
+      mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 3, INTEGER(REAL(c_cross_wg_ampl) * c_sdp_wg_ampl_lsb), tb_clk);  -- ampl
+    END IF;
 
     -- Read current BSN
     mmf_mm_bus_rd(c_mm_file_reg_bsn_scheduler_wg, 0, current_bsn_wg(31 DOWNTO  0), tb_clk);
@@ -347,27 +404,70 @@ BEGIN
     ----------------------------------------------------------------------------
     -- Write subband weight for selected g_sp and g_subband
     ----------------------------------------------------------------------------
+
+    -- Co-polarization subband weight for g_sp
     -- . MM format: (cint16)RAM_EQUALIZER_GAINS[S_pn/Q_fft]_[Q_fft][N_sub] = [S_pn][N_sub]
     v_addr := g_sp * c_sdp_N_sub + g_subband;
     -- . read
     mmf_mm_bus_rd(c_mm_file_ram_equalizer_gains, v_addr, rd_data, tb_clk);
     v_re := unpack_complex_re(rd_data, c_sdp_W_sub_weight);
     v_im := unpack_complex_im(rd_data, c_sdp_W_sub_weight);
-    sp_subband_weight_re <= v_re;
-    sp_subband_weight_im <= v_im;
-    sp_subband_weight_gain <= SQRT(REAL(v_re)**2.0 + REAL(v_im)**2.0) / REAL(c_sdp_unit_sub_weight);
-    sp_subband_weight_phase <= atan2(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI;
+    sp_co_subband_weight_re <= v_re;
+    sp_co_subband_weight_im <= v_im;
+    sp_co_subband_weight_gain <= COMPLEX_RADIUS(REAL(v_re), REAL(v_im)) / REAL(c_sdp_unit_sub_weight);
+    sp_co_subband_weight_phase <= COMPLEX_PHASE(REAL(v_re), REAL(v_im));
+    sp_co_subband_weight_val <= '1';
+    proc_common_wait_some_cycles(tb_clk, 1);
+    ASSERT sp_co_subband_weight_re = c_sdp_unit_sub_weight REPORT "Default sp_co_subband_weight_re /= c_sdp_unit_sub_weight" SEVERITY ERROR;
+    ASSERT sp_co_subband_weight_im = 0                     REPORT "Default sp_co_subband_weight_im /= 0" SEVERITY ERROR;
     -- . write
-    v_weight := pack_complex(re => c_subband_weight_re, im => c_subband_weight_im, w => c_sdp_W_sub_weight);  -- c_sdp_W_sub_weight = 16 bit
+    v_weight := pack_complex(re => c_co_subband_weight_re, im => c_co_subband_weight_im, w => c_sdp_W_sub_weight);  -- c_sdp_W_sub_weight = 16 bit
     mmf_mm_bus_wr(c_mm_file_ram_equalizer_gains, v_addr, v_weight, tb_clk);
+    proc_common_wait_cross_clock_domain_latency(c_tb_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency*2);
     -- . read back
     mmf_mm_bus_rd(c_mm_file_ram_equalizer_gains, v_addr, rd_data, tb_clk);
     v_re := unpack_complex_re(rd_data, c_sdp_W_sub_weight);
     v_im := unpack_complex_im(rd_data, c_sdp_W_sub_weight);
-    sp_subband_weight_re <= v_re;
-    sp_subband_weight_im <= v_im;
-    sp_subband_weight_gain <= SQRT(REAL(v_re)**2.0 + REAL(v_im)**2.0) / REAL(c_sdp_unit_sub_weight);
-    sp_subband_weight_phase <= atan2(Y => REAL(v_im), X => REAL(v_re)) * 360.0 / MATH_2_PI;
+    sp_co_subband_weight_re <= v_re;
+    sp_co_subband_weight_im <= v_im;
+    sp_co_subband_weight_gain <= COMPLEX_RADIUS(REAL(v_re), REAL(v_im)) / REAL(c_sdp_unit_sub_weight);
+    sp_co_subband_weight_phase <= COMPLEX_PHASE(REAL(v_re), REAL(v_im));
+      proc_common_wait_some_cycles(tb_clk, 1);
+    ASSERT sp_co_subband_weight_re = c_co_subband_weight_re REPORT "Readback sp_co_subband_weight_re /= c_co_subband_weight_re" SEVERITY ERROR;
+    ASSERT sp_co_subband_weight_im = c_co_subband_weight_im REPORT "Readback sp_co_subband_weight_im /= c_co_subband_weight_im" SEVERITY ERROR;
+
+    IF g_use_cross_weight THEN
+      -- Cross-polarization subband weight for g_sp
+      -- . MM format: (cint16)RAM_EQUALIZER_GAINS_CROSS[S_pn/Q_fft]_[Q_fft][N_sub] = [S_pn][N_sub]
+      v_addr := g_sp * c_sdp_N_sub + g_subband;
+      -- . read
+      mmf_mm_bus_rd(c_mm_file_ram_equalizer_gains_cross, v_addr, rd_data, tb_clk);
+      v_re := unpack_complex_re(rd_data, c_sdp_W_sub_weight);
+      v_im := unpack_complex_im(rd_data, c_sdp_W_sub_weight);
+      sp_cross_subband_weight_re <= v_re;
+      sp_cross_subband_weight_im <= v_im;
+      sp_cross_subband_weight_gain <= COMPLEX_RADIUS(REAL(v_re), REAL(v_im)) / REAL(c_sdp_unit_sub_weight);
+      sp_cross_subband_weight_phase <= COMPLEX_PHASE(REAL(v_re), REAL(v_im));
+      sp_cross_subband_weight_val <= '1';
+      proc_common_wait_some_cycles(tb_clk, 1);
+      ASSERT sp_cross_subband_weight_re = 0 REPORT "Default sp_cross_subband_weight_re /= 0" SEVERITY ERROR;
+      ASSERT sp_cross_subband_weight_im = 0 REPORT "Default sp_cross_subband_weight_im /= 0" SEVERITY ERROR;
+      -- . write
+      v_weight := pack_complex(re => c_sp_cross_subband_weight_re, im => c_sp_cross_subband_weight_im, w => c_sdp_W_sub_weight);  -- c_sdp_W_sub_weight = 16 bit
+      mmf_mm_bus_wr(c_mm_file_ram_equalizer_gains_cross, v_addr, v_weight, tb_clk);
+      proc_common_wait_cross_clock_domain_latency(c_tb_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency*2);
+      -- . read back
+      mmf_mm_bus_rd(c_mm_file_ram_equalizer_gains_cross, v_addr, rd_data, tb_clk);
+      v_re := unpack_complex_re(rd_data, c_sdp_W_sub_weight);
+      v_im := unpack_complex_im(rd_data, c_sdp_W_sub_weight);
+      sp_cross_subband_weight_re <= v_re;
+      sp_cross_subband_weight_im <= v_im;
+      sp_cross_subband_weight_gain <= COMPLEX_RADIUS(REAL(v_re), REAL(v_im)) / REAL(c_sdp_unit_sub_weight);
+      sp_cross_subband_weight_phase <= COMPLEX_PHASE(REAL(v_re), REAL(v_im));
+      proc_common_wait_some_cycles(tb_clk, 1);
+      ASSERT sp_cross_subband_weight_re = c_sp_cross_subband_weight_re REPORT "Readback sp_cross_subband_weight_re /= c_sp_cross_subband_weight_re" SEVERITY ERROR;
+      ASSERT sp_cross_subband_weight_im = c_sp_cross_subband_weight_im REPORT "Readback sp_cross_subband_weight_im /= c_sp_cross_subband_weight_im" SEVERITY ERROR;
+    END IF;
 
     ----------------------------------------------------------------------------
     -- Wait for enough WG data and start of sync interval
@@ -423,6 +523,8 @@ BEGIN
     --   to sp_subband_sst_sum_arr(c_pol_index), because the input is a
     --   sinus, so most power will be in 1 subband.
     sp_subband_sst <= TO_UREAL(sp_subband_ssts_arr2(c_pol_index)(g_subband));
+    -- Subband power of g_subband in c_cross_sp
+    sp_cross_subband_sst <= TO_UREAL(sp_subband_ssts_arr2(not_int(c_pol_index))(g_subband));
     proc_common_wait_some_cycles(tb_clk, 1);
 
     -- The sp_subband_sst_leakage shows how much power from the input sinus at a specific
@@ -436,15 +538,18 @@ BEGIN
       REPORT "Wrong, zero leakage is unexpected for SP-" & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
     END IF;
 
-    -- The sp_subband_sst_crosstalk shows how much power from one WPFB input cross talks
-    -- into the other output, due to quantization cross talk in the complex FFT. The power
-    -- ration indicates the suppression, provided that the other input was zero.
-    v_power := sp_subband_sst_sum_arr(not_int(c_pol_index));
-    sp_subband_sst_crosstalk <= v_power;
-    IF sp_subband_sst > c_eps AND v_power > c_eps THEN
-      sp_subband_sst_crosstalk_snr_dB <= 10.0 * LOG10(sp_subband_sst / v_power);
-    ELSIF g_read_all_SST THEN
-      REPORT "Zero crosstalk for SP-" & NATURAL'IMAGE(g_sp) SEVERITY NOTE;
+    IF NOT g_use_cross_weight THEN
+      -- The other WPFB input WG at c_cross_sp is not used, so it should have ~ zero power.
+      -- The sp_subband_sst_crosstalk shows how much power from one WPFB input cross talks
+      -- into the other output, due to quantization cross talk in the complex FFT. The power
+      -- ration indicates the suppression, provided that the other input was zero.
+      v_power := sp_subband_sst_sum_arr(not_int(c_pol_index));  -- not_int(0) = 1, not_int(/= 0) = 0
+      sp_subband_sst_crosstalk <= v_power;
+      IF sp_subband_sst > c_eps AND v_power > c_eps THEN
+        sp_subband_sst_crosstalk_snr_dB <= 10.0 * LOG10(sp_subband_sst / v_power);
+      ELSIF g_read_all_SST THEN
+        REPORT "Zero crosstalk for SP-" & NATURAL'IMAGE(g_sp) SEVERITY NOTE;
+      END IF;
     END IF;
 
     proc_common_wait_some_cycles(tb_clk, 10);
@@ -454,50 +559,67 @@ BEGIN
     ---------------------------------------------------------------------------
     print_str("");
     print_str("WG:");
-    print_str(". c_wg_ampl                            = " & int_to_str(c_wg_ampl));
-    print_str(". c_exp_sp_power                       = " & real_to_str(c_exp_sp_power, 20, 1));
-    print_str(". c_exp_sp_ast                         = " & real_to_str(c_exp_sp_ast, 20, 1));
+    print_str(". c_co_wg_ampl for g_sp                        = " & int_to_str(c_co_wg_ampl));
+    print_str(". c_cross_wg_ampl for c_cross_sp               = " & int_to_str(c_cross_wg_ampl));
 
     print_str("");
     print_str("Subband selector:");
-    print_str(". sst_offload_weighted_subbands        = " & sl_to_str(sst_offload_weighted_subbands));
+    print_str(". sst_offload_weighted_subbands                = " & sl_to_str(sst_offload_weighted_subbands));
 
     print_str("");
-    print_str("Subband weight:");
-    print_str(". sp_subband_weight_gain               = " & real_to_str(sp_subband_weight_gain, 20, 6));
-    print_str(". sp_subband_weight_phase              = " & real_to_str(sp_subband_weight_phase, 20, 6));
+    print_str("Subband weights for g_sp:");
+    print_str(". sp_co_subband_weight_gain                    = " & real_to_str(sp_co_subband_weight_gain, 20, 6));
+    print_str(". sp_co_subband_weight_phase                   = " & real_to_str(sp_co_subband_weight_phase, 20, 6));
+    IF g_use_cross_weight THEN
+      print_str(". sp_cross_subband_weight_gain                 = " & real_to_str(sp_cross_subband_weight_gain, 20, 6));
+      print_str(". sp_cross_subband_weight_phase                = " & real_to_str(sp_cross_subband_weight_phase, 20, 6));
+    END IF;
 
     print_str("");
     print_str("SST results:");
-    print_str(". exp_subband_ampl                     = " & int_to_str(NATURAL(exp_subband_ampl)));
-    print_str(". exp_subband_power                    = " & real_to_str(exp_subband_power, 20, 1));
-    print_str(". exp_subband_sst                      = " & real_to_str(exp_subband_sst, 20, 1));
+    print_str(". exp_sp_subband_ampl                          = " & int_to_str(NATURAL(exp_sp_subband_ampl)));
+    print_str(". exp_sp_subband_power                         = " & real_to_str(exp_sp_subband_power, 20, 1));
+    print_str(". exp_sp_subband_sst                           = " & real_to_str(exp_sp_subband_sst, 20, 1));
+    print_str(". exp_cross_subband_sst                        = " & real_to_str(exp_cross_subband_sst, 20, 1));
     print_str("");
-    print_str(". sp_subband_sst                       = " & real_to_str(sp_subband_sst, 20, 1));
-    print_str(". sp_subband_sst / exp_subband_sst     = " & real_to_str(sp_subband_sst / exp_subband_sst, 20, 6));
+    print_str(". sp_subband_sst                               = " & real_to_str(sp_subband_sst, 20, 1));
+    print_str(". sp_subband_sst / exp_sp_subband_sst          = " & real_to_str(sp_subband_sst / exp_sp_subband_sst, 20, 6));
+    print_str(". sp_cross_subband_sst                         = " & real_to_str(sp_cross_subband_sst, 20, 1));
+    print_str(". sp_cross_subband_sst / exp_cross_subband_sst = " & real_to_str(sp_cross_subband_sst / exp_cross_subband_sst, 20, 6));
 
     IF g_read_all_SST THEN
       -- Log WPFB details, these are allready verified in tb of wpfb_unit_dev.vhd, so here
       -- quality indicators like leakage and crosstalk are also reported out of interest.
       print_str("");
       print_str("SST quality indicators");
-      print_str(". sp_subband_sst_leakage               = " & real_to_str(sp_subband_sst_leakage, 20, 0));
-      print_str(". sp_subband_sst_leakage_snr_dB        = " & real_to_str(sp_subband_sst_leakage_snr_dB, 20, 3));
-      print_str(". sp_subband_sst_crosstalk             = " & real_to_str(sp_subband_sst_crosstalk, 20, 0));
-      print_str(". sp_subband_sst_crosstalk_snr_db      = " & real_to_str(sp_subband_sst_crosstalk_snr_db, 20, 3));
+      print_str(". sp_subband_sst_leakage                       = " & real_to_str(sp_subband_sst_leakage, 20, 0));
+      print_str(". sp_subband_sst_leakage_snr_dB                = " & real_to_str(sp_subband_sst_leakage_snr_dB, 20, 3));
+      IF NOT g_use_cross_weight THEN
+        print_str(". sp_subband_sst_crosstalk                     = " & real_to_str(sp_subband_sst_crosstalk, 20, 0));
+        print_str(". sp_subband_sst_crosstalk_snr_db              = " & real_to_str(sp_subband_sst_crosstalk_snr_db, 20, 3));
+      END IF;
     END IF;
 
     ---------------------------------------------------------------------------
     -- Verify SST
     ---------------------------------------------------------------------------
-    -- verify expected subband power based on WG power
-    ASSERT sp_subband_sst > c_lo_factor * exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
-    ASSERT sp_subband_sst < c_hi_factor * exp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
+    -- Verify expected subband power based on WG power for g_sp
+    ASSERT sp_subband_sst > c_lo_factor * exp_sp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
+    ASSERT sp_subband_sst < c_hi_factor * exp_sp_subband_sst REPORT "Wrong subband power for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
+    IF g_use_cross_weight THEN
+      -- Verify expected subband power based on WG power for c_cross_sp
+      -- The other WPFB input WG at c_cross_sp is used as cross polarization input, with default
+      -- unit co-polarization subband weight and zero cross-polarization subband weight.
+      ASSERT sp_cross_subband_sst > c_lo_factor * exp_cross_subband_sst REPORT "Wrong subband power for cross SP " & NATURAL'IMAGE(c_cross_sp) SEVERITY ERROR;
+      ASSERT sp_cross_subband_sst < c_hi_factor * exp_cross_subband_sst REPORT "Wrong subband power for cross SP " & NATURAL'IMAGE(c_cross_sp) SEVERITY ERROR;
+    END IF;
 
     IF g_read_all_SST THEN
       -- Verify expected SNR quality measures
-      ASSERT sp_subband_sst_leakage = 0.0 OR sp_subband_sst_leakage_snr_dB > c_exp_subband_sst_leakage_snr_dB REPORT "Wrong too much leakage for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
-      ASSERT sp_subband_sst_crosstalk = 0.0 OR sp_subband_sst_crosstalk_snr_dB > c_exp_subband_sst_crosstalk_snr_dB REPORT "Wrong too much crosstalk for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
+      ASSERT sp_subband_sst_leakage = 0.0 OR sp_subband_sst_leakage_snr_dB > c_exp_sp_subband_sst_leakage_snr_dB REPORT "Wrong too much leakage for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
+      IF NOT g_use_cross_weight THEN
+        ASSERT sp_subband_sst_crosstalk = 0.0 OR sp_subband_sst_crosstalk_snr_dB > c_exp_sp_subband_sst_crosstalk_snr_dB REPORT "Wrong too much crosstalk for SP " & NATURAL'IMAGE(g_sp) SEVERITY ERROR;
+      END IF;
     END IF;
 
     ---------------------------------------------------------------------------
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 c5e3babf49bcb77568dc796923ab222233061423..bec60072a6ac16140d3fcd74bb33d0a8cdfc6a99 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
@@ -107,7 +107,10 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS
                                          NATURAL'IMAGE(c_sdp_W_sub_weight) & "b" &
                                          NATURAL'IMAGE(c_sdp_W_sub_weight_fraction) & "f_unit";
 
-  -- Use quantized subbands
+  -- Use quantized subbands, so c_subband_raw_dat_w = 18b.
+  -- . Maybe later use raw subbands like in node_sdp_filterbank, but for now
+  --   appling subband weights and bf weights at c_sdp_W_subband = 18b subbands
+  --   is acceptable.
   CONSTANT c_subband_raw_dat_w      : NATURAL := c_sdp_W_subband;
   CONSTANT c_subband_raw_fraction_w : NATURAL := 0;
 
@@ -118,11 +121,11 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS
   CONSTANT c_complex_pfb_pipeline  : NATURAL := 2;
 
   -- Use WG as local oscillator, buf contains 16b sin and 16b cos
-  -- . c_sdp_W_local_oscillator = c_halfword_w = 16b
+  -- . c_sdp_W_local_oscillator = 16b
   -- . c_sdp_W_local_oscillator_fraction = 16b - 1 sign bit = 15b
   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,      
+                                          dat_w    => c_nof_complex * c_sdp_W_local_oscillator,
                                           nof_dat  => c_sdp_R_os * c_sdp_N_fft,  
                                           init_sl  => '0');
 
@@ -171,18 +174,22 @@ ARCHITECTURE str OF node_sdp_oversampled_filterbank IS
   SIGNAL wpfb_unit_out_sosi_arr_piped   : t_dp_sosi_arr(c_sdp_P_pfb-1 DOWNTO 0)  := (OTHERS => c_dp_sosi_rst);
 
   -- Mixer to shift f_sub/2
-  SIGNAL complex_mult_src_out_arr       : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_sosi_rst);
-  SIGNAL requantize_src_out_arr         : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_sosi_rst);
+  SIGNAL mixer_complex_mult_src_out_arr       : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL mixer_complex_requantize_src_out_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
 
+  -- Complex input FFT (from LO mixer)
   SIGNAL wpfb_unit_complex_in_sosi_arr  : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_sosi_rst);
   SIGNAL wpfb_unit_complex_fil_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_sosi_rst);
   SIGNAL wpfb_unit_complex_out_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_sosi_rst);
-  SIGNAL wpfb_unit_out_resized_sosi_arr : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_sosi_rst);
 
-  SIGNAL wpfb_fifo_sosi_arr             : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_sosi_rst);
-  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));
+  -- Remove negative frequencies
+  SIGNAL wpfb_complex_out_resized_sosi_arr  : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_sosi_rst);
+
+  -- Interleave positive frequencies per factor Q_fft = 2, like with output of real input FFT
+  SIGNAL wpfb_complex_out_fifo_sosi_arr     : t_dp_sosi_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_sosi_rst);
+  SIGNAL wpfb_complex_out_fifo_siso_arr     : t_dp_siso_arr(c_sdp_S_pn-1 DOWNTO 0)   := (OTHERS => c_dp_siso_rst);
+  SIGNAL wpfb_complex_out_resized_sosi_2arr : t_dp_sosi_2arr_2(c_sdp_P_pfb-1 DOWNTO 0) := (OTHERS => (OTHERS => c_dp_sosi_rst));
+  SIGNAL wpfb_complex_out_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_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);
@@ -342,23 +349,23 @@ BEGIN
   gen_complex_mult: FOR I IN 0 TO c_sdp_S_pn-1 GENERATE
     u_common_complex_mult : ENTITY common_mult_lib.common_complex_mult
     GENERIC MAP (
-      g_in_a_w           => c_halfword_w,  -- = c_sdp_W_local_oscillator = 16
-      g_in_b_w           => c_sdp_W_adc,
-      g_out_p_w          => c_halfword_w + c_sdp_W_adc,
+      g_in_a_w           => c_sdp_W_local_oscillator,  -- = 16
+      g_in_b_w           => c_sdp_W_adc,  -- = 14
+      g_out_p_w          => c_sdp_W_local_oscillator + c_sdp_W_adc,  -- = 16 + 14 = 30
       g_conjugate_b      => FALSE
     )
     PORT MAP (
       clk        => dp_clk,
       clken      => '1',
       rst        => dp_rst,
-      in_ar      => wg_out_dat(c_halfword_w-1 DOWNTO 0),
-      in_ai      => wg_out_dat(2 * c_halfword_w-1 DOWNTO c_halfword_w),
+      in_ar      => wg_out_dat(c_sdp_W_local_oscillator-1 DOWNTO 0),
+      in_ai      => wg_out_dat(2 * c_sdp_W_local_oscillator-1 DOWNTO c_sdp_W_local_oscillator),
       in_br      => si_sosi_arr(I).data(c_sdp_W_adc-1 DOWNTO 0),
       in_bi      => (OTHERS => '0'),
       in_val     => si_sosi_arr(I).valid,
-      out_pr     => complex_mult_src_out_arr(I).re(c_halfword_w + c_sdp_W_adc-1 DOWNTO 0),
-      out_pi     => complex_mult_src_out_arr(I).im(c_halfword_w + c_sdp_W_adc-1 DOWNTO 0),
-      out_val    => complex_mult_src_out_arr(I).valid
+      out_pr     => mixer_complex_mult_src_out_arr(I).re(c_sdp_W_local_oscillator + c_sdp_W_adc-1 DOWNTO 0),
+      out_pi     => mixer_complex_mult_src_out_arr(I).im(c_sdp_W_local_oscillator + c_sdp_W_adc-1 DOWNTO 0),
+      out_val    => mixer_complex_mult_src_out_arr(I).valid
     );    
     
     --requantize
@@ -373,16 +380,16 @@ BEGIN
       g_msb_clip_symmetric  => FALSE,      
       g_pipeline_remove_lsb => 0,
       g_pipeline_remove_msb => 0,
-      g_in_dat_w            => c_halfword_w + c_sdp_W_adc,
+      g_in_dat_w            => c_sdp_W_local_oscillator + c_sdp_W_adc,
       g_out_dat_w           => c_sdp_W_adc                                                                                              
     )
     PORT MAP (
       rst          => dp_rst, 
       clk          => dp_clk,
       -- ST sink
-      snk_in       => complex_mult_src_out_arr(I),
+      snk_in       => mixer_complex_mult_src_out_arr(I),
       -- ST source
-      src_out      => requantize_src_out_arr(I)
+      src_out      => mixer_complex_requantize_src_out_arr(I)
     );
   END GENERATE;
 
@@ -411,12 +418,12 @@ BEGIN
     in_dat     => dp_bsn_source_restart_pipe,
     out_dat    => dp_bsn_source_restart_pipe_complex
   ); 
-  PROCESS(requantize_src_out_arr, si_sosi_0_piped)
+  PROCESS(mixer_complex_requantize_src_out_arr, si_sosi_0_piped)
   BEGIN
     FOR I IN 0 TO c_sdp_S_pn-1 LOOP
       wpfb_unit_complex_in_sosi_arr(I) <= si_sosi_0_piped;
-      wpfb_unit_complex_in_sosi_arr(I).re <= requantize_src_out_arr(I).re;
-      wpfb_unit_complex_in_sosi_arr(I).im <= requantize_src_out_arr(I).im;
+      wpfb_unit_complex_in_sosi_arr(I).re <= mixer_complex_requantize_src_out_arr(I).re;
+      wpfb_unit_complex_in_sosi_arr(I).im <= mixer_complex_requantize_src_out_arr(I).im;
     END LOOP;
   END PROCESS;
 
@@ -461,7 +468,7 @@ BEGIN
         rst          => dp_rst,
         clk          => dp_clk,
         snk_in       => wpfb_unit_complex_out_sosi_arr(I),
-        src_out      => wpfb_unit_out_resized_sosi_arr(I)
+        src_out      => wpfb_complex_out_resized_sosi_arr(I)
       );
   END GENERATE;
 
@@ -479,18 +486,18 @@ BEGIN
       PORT MAP (
         rst          => dp_rst,
         clk          => dp_clk,
-        snk_in       => wpfb_unit_out_resized_sosi_arr(I),
-        src_out      => wpfb_fifo_sosi_arr(I),
-        src_in       => wpfb_fifo_siso_arr(I)
+        snk_in       => wpfb_complex_out_resized_sosi_arr(I),
+        src_out      => wpfb_complex_out_fifo_sosi_arr(I),
+        src_in       => wpfb_complex_out_fifo_siso_arr(I)
     );
   END GENERATE;
 
   -- rewire 1d array of 1 X S_pn to 2d array of 2 X P_pfb
   gen_rewire: FOR I IN 0 TO c_sdp_P_pfb-1 GENERATE
-    wpfb_resized_sosi_2arr(I)(0) <= wpfb_fifo_sosi_arr(2*I);
-    wpfb_resized_sosi_2arr(I)(1) <= wpfb_fifo_sosi_arr(2*I + 1);
-    wpfb_fifo_siso_arr(2*I)      <= wpfb_resized_siso_2arr(I)(0);
-    wpfb_fifo_siso_arr(2*I + 1)  <= wpfb_resized_siso_2arr(I)(1);
+    wpfb_complex_out_resized_sosi_2arr(I)(0) <= wpfb_complex_out_fifo_sosi_arr(2*I);
+    wpfb_complex_out_resized_sosi_2arr(I)(1) <= wpfb_complex_out_fifo_sosi_arr(2*I + 1);
+    wpfb_complex_out_fifo_siso_arr(2*I)      <= wpfb_complex_out_resized_siso_2arr(I)(0);
+    wpfb_complex_out_fifo_siso_arr(2*I + 1)  <= wpfb_complex_out_resized_siso_2arr(I)(1);
   END GENERATE;
 
   -- Interleave 2 to 1 for all S_pn signals.
@@ -502,8 +509,8 @@ BEGIN
       PORT MAP (
         rst          => dp_rst,
         clk          => dp_clk,
-        snk_in_arr   => wpfb_resized_sosi_2arr(I),
-        snk_out_arr  => wpfb_resized_siso_2arr(I),
+        snk_in_arr   => wpfb_complex_out_resized_sosi_2arr(I),
+        snk_out_arr  => wpfb_complex_out_resized_siso_2arr(I),
         src_out      => subband_equalizer_in_sosi_arr(c_sdp_P_pfb + I)
     );
   END GENERATE;
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd
index c2d73ece5a14d2129c3dc68483eabee5d979d3ca..80f954b2be49c1090be1d61b742033664b1726ed 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_subband_equalizer.vhd
@@ -141,7 +141,8 @@ BEGIN
       g_pipeline_mux_in    => 0,  -- parallel to serial section
       g_pipeline_mux_out   => 1,
       g_reverse_len        => c_sdp_N_pol,  -- = 2
-      g_data_w             => 16,
+      g_data_w             => g_raw_dat_w * c_nof_complex,
+      g_use_complex        => TRUE,
       g_signed             => TRUE
     )
     PORT MAP (
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 762d2e704f509e7df83aa29ce4d8c0a85382368e..c3f0bc73f755b154ea2f7b8e2f2ae37128371df8 100644
--- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_pkg.vhd
@@ -77,6 +77,31 @@ PACKAGE tb_sdp_pkg is
 
   FUNCTION func_sdp_verify_cep_header(in_hdr, exp_hdr : t_sdp_cep_header) RETURN BOOLEAN;
 
+  -----------------------------------------------------------------------------
+  -- Subband equalizer (ESub)
+  -----------------------------------------------------------------------------
+  -- - ESub is like a two input beamformer
+  -- - Esub function calculates the expected subband level for signal input sp:
+  --   sp phasor * sp_weight + cross_phasor * cross weigth, where
+  --   . sp phasor = (sp_subband_ampl, sp_subband_phase)
+  --   . sp_weight = (sp_esub_gain, sp_esub_phase)
+  --   . cross_phasor = (cross_subband_ampl, cross_subband_phase)
+  --   . cross_weight = (cross_esub_gain, cross_esub_phase)
+  FUNCTION func_sdp_subband_equalizer(sp_subband_ampl, sp_subband_phase, sp_esub_gain, sp_esub_phase,
+                                      cross_subband_ampl, cross_subband_phase, cross_esub_gain, cross_esub_phase : REAL)
+                                      RETURN t_real_arr;  -- 0:3 = ampl, phase, re, im
+
+
+  -----------------------------------------------------------------------------
+  -- Beamformer (BF)
+  -----------------------------------------------------------------------------
+  -- Model the SDP beamformer for one signal input (sp) and nof_rem remnant signal inputs (rem)
+  -- . for local beamformer on one node use nof_rem = S_pn - 1
+  -- . for remote beamformer with nof_rn ring nodes use nof_rem = nof_rn * S_pn - 1
+  FUNCTION func_sdp_beamformer(sp_subband_ampl, sp_subband_phase, sp_bf_gain, sp_bf_phase,
+                               rem_subband_ampl, rem_subband_phase, rem_bf_gain, rem_bf_phase : REAL;
+                               nof_rem : NATURAL)
+                               RETURN t_real_arr;  -- 0:3 = ampl, phase, re, im
 
 END PACKAGE tb_sdp_pkg;
 
@@ -393,4 +418,56 @@ PACKAGE BODY tb_sdp_pkg IS
     RETURN TRUE;
   END func_sdp_verify_cep_header;
 
+
+  FUNCTION func_sdp_subband_equalizer(sp_subband_ampl, sp_subband_phase, sp_esub_gain, sp_esub_phase,
+                                      cross_subband_ampl, cross_subband_phase, cross_esub_gain, cross_esub_phase : REAL)
+                                      RETURN t_real_arr IS  -- 0:3 = ampl, phase, re, im
+    VARIABLE v_sp_ampl, v_sp_phase, v_sp_re, v_sp_im : REAL;
+    VARIABLE v_cross_ampl, v_cross_phase, v_cross_re, v_cross_im : REAL;
+    VARIABLE v_sum_ampl, v_sum_phase, v_sum_re, v_sum_im : REAL;
+    VARIABLE v_tuple : t_real_arr(0 TO 3);
+  BEGIN
+    v_sp_ampl   := sp_subband_ampl * sp_esub_gain;
+    v_sp_phase  := sp_subband_phase + sp_esub_phase;
+    v_sp_re     := COMPLEX_RE(v_sp_ampl, v_sp_phase);
+    v_sp_im     := COMPLEX_IM(v_sp_ampl, v_sp_phase);
+    v_cross_ampl  := cross_subband_ampl * cross_esub_gain;
+    v_cross_phase := cross_subband_phase + cross_esub_phase;
+    v_cross_re    := COMPLEX_RE(v_cross_ampl, v_cross_phase);
+    v_cross_im    := COMPLEX_IM(v_cross_ampl, v_cross_phase);
+    v_sum_re    := v_sp_re + v_cross_re;  -- ESub sum re
+    v_sum_im    := v_sp_im + v_cross_im;  -- ESub sum im
+    v_sum_ampl  := COMPLEX_RADIUS(v_sum_re, v_sum_im);
+    v_sum_phase := COMPLEX_PHASE(v_sum_re, v_sum_im);
+    v_tuple     := (0 => v_sum_ampl, 1 => v_sum_phase, 2 => v_sum_re, 3 => v_sum_im);
+    RETURN v_tuple;
+  END;
+
+
+  FUNCTION func_sdp_beamformer(sp_subband_ampl, sp_subband_phase, sp_bf_gain, sp_bf_phase,
+                               rem_subband_ampl, rem_subband_phase, rem_bf_gain, rem_bf_phase : REAL;
+                               nof_rem : NATURAL)
+                               RETURN t_real_arr IS  -- 0:3 = ampl, phase, re, im
+    VARIABLE v_nof_rem : REAL := REAL(nof_rem);  -- BF for one sp and nof_rem remnant signal inputs
+    VARIABLE v_sp_ampl, v_sp_phase, v_sp_re, v_sp_im     : REAL;
+    VARIABLE v_rem_ampl, v_rem_phase, v_rem_re, v_rem_im : REAL;
+    VARIABLE v_sum_ampl, v_sum_phase, v_sum_re, v_sum_im : REAL;
+    VARIABLE v_tuple                                     : t_real_arr(0 TO 3);
+  BEGIN
+    v_sp_ampl   := sp_subband_ampl * sp_bf_gain;
+    v_sp_phase  := sp_subband_phase + sp_bf_phase;
+    v_sp_re     := COMPLEX_RE(v_sp_ampl, v_sp_phase);
+    v_sp_im     := COMPLEX_IM(v_sp_ampl, v_sp_phase);
+    v_rem_ampl  := rem_subband_ampl * rem_bf_gain;
+    v_rem_phase := rem_subband_phase + rem_bf_phase;
+    v_rem_re    := COMPLEX_RE(v_rem_ampl, v_rem_phase);
+    v_rem_im    := COMPLEX_IM(v_rem_ampl, v_rem_phase);
+    v_sum_re    := v_sp_re + v_nof_rem * v_rem_re;  -- BF sum re
+    v_sum_im    := v_sp_im + v_nof_rem * v_rem_im;  -- BF sum im
+    v_sum_ampl  := COMPLEX_RADIUS(v_sum_re, v_sum_im);
+    v_sum_phase := COMPLEX_PHASE(v_sum_re, v_sum_im);
+    v_tuple     := (0 => v_sum_ampl, 1 => v_sum_phase, 2 => v_sum_re, 3 => v_sum_im);
+    RETURN v_tuple;
+  END;
+
 END tb_sdp_pkg;
diff --git a/libraries/base/common/tb/vhdl/tb_common_pkg.vhd b/libraries/base/common/tb/vhdl/tb_common_pkg.vhd
index ab0bd1f18a76bb607f39acc01ad3853516467afc..ee15dbe99cb195289f17e350388b2c02d0484564 100644
--- a/libraries/base/common/tb/vhdl/tb_common_pkg.vhd
+++ b/libraries/base/common/tb/vhdl/tb_common_pkg.vhd
@@ -81,6 +81,9 @@ PACKAGE tb_common_pkg IS
   PROCEDURE proc_common_wait_until_high(SIGNAL clk    : IN  STD_LOGIC;
                                         SIGNAL level  : IN  STD_LOGIC);
                                                 
+  PROCEDURE proc_common_wait_until_clk_and_high(SIGNAL clk    : IN  STD_LOGIC;
+                                                SIGNAL level  : IN  STD_LOGIC);
+
   PROCEDURE proc_common_wait_until_low(CONSTANT c_timeout : IN  NATURAL;
                                        SIGNAL   clk       : IN  STD_LOGIC;
                                        SIGNAL   level     : IN  STD_LOGIC);
@@ -88,6 +91,9 @@ PACKAGE tb_common_pkg IS
   PROCEDURE proc_common_wait_until_low(SIGNAL clk    : IN  STD_LOGIC;
                                        SIGNAL level  : IN  STD_LOGIC);
                                          
+  PROCEDURE proc_common_wait_until_clk_and_low(SIGNAL clk    : IN  STD_LOGIC;
+                                               SIGNAL level  : IN  STD_LOGIC);
+
   PROCEDURE proc_common_wait_until_hi_lo(CONSTANT c_timeout : IN  NATURAL;
                                          SIGNAL   clk       : IN  STD_LOGIC;
                                          SIGNAL   level     : IN  STD_LOGIC);
@@ -427,6 +433,12 @@ PACKAGE BODY tb_common_pkg IS
       WAIT UNTIL rising_edge(clk) AND level='1';
     END IF;
   END proc_common_wait_until_high;
+
+  PROCEDURE proc_common_wait_until_clk_and_high(SIGNAL clk    : IN  STD_LOGIC;
+                                                SIGNAL level  : IN  STD_LOGIC) IS
+  BEGIN
+    WAIT UNTIL rising_edge(clk) AND level='1';
+  END proc_common_wait_until_clk_and_high;
   
   PROCEDURE proc_common_wait_until_high(CONSTANT c_timeout : IN  NATURAL;
                                         SIGNAL   clk       : IN  STD_LOGIC;
@@ -452,6 +464,12 @@ PACKAGE BODY tb_common_pkg IS
     END IF;
   END proc_common_wait_until_low;
   
+  PROCEDURE proc_common_wait_until_clk_and_low(SIGNAL clk    : IN  STD_LOGIC;
+                                              SIGNAL level  : IN  STD_LOGIC) IS
+  BEGIN
+    WAIT UNTIL rising_edge(clk) AND level='0';
+  END proc_common_wait_until_clk_and_low;
+
   PROCEDURE proc_common_wait_until_low(CONSTANT c_timeout : IN  NATURAL;
                                        SIGNAL   clk       : IN  STD_LOGIC;
                                        SIGNAL   level     : IN  STD_LOGIC) IS
diff --git a/libraries/base/dp/src/vhdl/dp_reverse_n_data.vhd b/libraries/base/dp/src/vhdl/dp_reverse_n_data.vhd
index 0b310e901eb493cab9ecfd2358c179e7ab0e3698..3ce1d4545d1a6c06353ced19e22ac43e474348ba 100644
--- a/libraries/base/dp/src/vhdl/dp_reverse_n_data.vhd
+++ b/libraries/base/dp/src/vhdl/dp_reverse_n_data.vhd
@@ -51,7 +51,8 @@ ENTITY dp_reverse_n_data IS
     g_pipeline_mux_in    : NATURAL := 0;  -- parallel to serial section
     g_pipeline_mux_out   : NATURAL := 1;
     g_reverse_len        : NATURAL := 2;
-    g_data_w             : NATURAL := 16;
+    g_data_w             : NATURAL := 16;  -- should be 2 times the c_complex_w if g_use_complex = TRUE
+    g_use_complex        : BOOLEAN := FALSE;
     g_signed             : BOOLEAN := TRUE
   );
   PORT (
@@ -69,6 +70,7 @@ ARCHITECTURE str OF dp_reverse_n_data IS
   CONSTANT c_pipeline_total : NATURAL := g_pipeline_demux_in + g_pipeline_demux_out +
                                          g_reverse_len-1 +
                                          g_pipeline_mux_in + g_pipeline_mux_out;
+  CONSTANT c_complex_w      : NATURAL := g_data_w / 2;
 
   SIGNAL in_data            : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
 
@@ -79,7 +81,14 @@ ARCHITECTURE str OF dp_reverse_n_data IS
 
 BEGIN
 
-  in_data <= snk_in.data(g_data_w-1 DOWNTO 0);
+  p_in_data : PROCESS(snk_in)
+  BEGIN
+    IF g_use_complex = FALSE THEN
+      in_data <= snk_in.data(g_data_w-1 DOWNTO 0);
+    ELSE
+      in_data <= snk_in.im(c_complex_w-1 DOWNTO 0) & snk_in.re(c_complex_w-1 DOWNTO 0);
+    END IF;
+  END PROCESS;
 
   u_common_reverse_n : ENTITY common_lib.common_reverse_n_data
   GENERIC MAP (
@@ -119,10 +128,15 @@ BEGIN
   p_src_out : PROCESS(snk_in_delayed, reversed_data)
   BEGIN
     src_out <= snk_in_delayed;
-    IF g_signed = TRUE THEN
-      src_out.data <= RESIZE_DP_SDATA(reversed_data);
+    IF g_use_complex = FALSE THEN
+      IF g_signed = TRUE THEN
+        src_out.data <= RESIZE_DP_SDATA(reversed_data);
+      ELSE
+        src_out.data <= RESIZE_DP_DATA(reversed_data);
+      END IF;
     ELSE
-      src_out.data <= RESIZE_DP_DATA(reversed_data);
+      src_out.im <= RESIZE_DP_DSP_DATA(reversed_data(g_data_w-1 DOWNTO c_complex_w));
+      src_out.re <= RESIZE_DP_DSP_DATA(reversed_data(c_complex_w-1 DOWNTO 0));
     END IF;
   END PROCESS;