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 4a1080e7605e740d0ba02b7b772795396a5a6d44..b84d16cc0e02f705d589aa3df1b6be450f3ff466 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
@@ -111,7 +111,7 @@ architecture tb of tb_disturb2_unb2b_sdp_station_full_wg is
   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_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_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
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_bf/tb_lofar2_unb2b_sdp_station_bf.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_bf/tb_lofar2_unb2b_sdp_station_bf.vhd
index fc88e90a4a3bb1d561ce39a0571146b0799a99ec..3eb4663984c590f6d5ad8c05d233f30490d33afe 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_bf/tb_lofar2_unb2b_sdp_station_bf.vhd
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_bf/tb_lofar2_unb2b_sdp_station_bf.vhd
@@ -164,7 +164,7 @@ architecture tb of tb_lofar2_unb2b_sdp_station_bf is
   -- . 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 = dp_clk rate
-  constant c_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_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
 
diff --git a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd
index ae4d83d08ea97fa788ff42172351ba2766e67b31..01b7d1a62acb959ef016362c6999b5ba55c82bbf 100644
--- a/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd
+++ b/applications/lofar2/designs/lofar2_unb2b_sdp_station/revisions/lofar2_unb2b_sdp_station_fsub/tb_lofar2_unb2b_sdp_station_fsub.vhd
@@ -119,7 +119,7 @@ architecture tb of tb_lofar2_unb2b_sdp_station_fsub is
   -- . 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_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_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
 
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 e1121127b6c8ce995c9ee29cae088f497193767d..5961e34066a72b5aaacee15a2182a6667c3dc45a 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
@@ -277,7 +277,7 @@ architecture tb of tb_lofar2_unb2c_sdp_station_bf is
   constant c_exp_sp_ast           : real := c_exp_sp_power * real(c_nof_clk_per_sync);
   -- . phase
   constant c_subband_freq         : real := real(g_subband) / real(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz = dp_clk rate
-  constant c_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_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 := g_sp_phase + c_wg_phase_offset;  -- WG phase in degrees
   constant c_wg_remnant_phase     : real := g_sp_remnant_phase + c_wg_phase_offset;  -- WG phase in degrees
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 18702afb27646b839fa7bcb523075e7799bd1366..3abd033083ff66f9773461d0c105567d78d07c0f 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
@@ -277,7 +277,7 @@ architecture tb of tb_lofar2_unb2c_sdp_station_bf_ring is
   constant c_exp_sp_ast           : real := c_exp_sp_power * real(c_nof_clk_per_sync);
   -- . phase
   constant c_subband_freq         : real := real(g_subband) / real(c_sdp_N_fft);  -- normalized by fs = f_adc = 200 MHz = dp_clk rate
-  constant c_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_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 := g_sp_phase + c_wg_phase_offset;  -- WG phase in degrees
   constant c_wg_remnant_phase     : real := g_sp_remnant_phase + c_wg_phase_offset;  -- WG phase in degrees
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 7d739b0f82e19e68cee96ffde59911ff0b4aa33e..cf06a7e71344fe6a522391112bb98930c494dae9 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
@@ -135,7 +135,7 @@ architecture tb of tb_lofar2_unb2c_sdp_station_fsub is
   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_wg_latency           : integer := c_diag_wg_latency - 0;  -- -0 to account for BSN scheduler start trigger latency
+  constant c_wg_latency           : integer := c_diag_wg_latency + c_sdp_shiftram_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;
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd
index ba5ace7994c52065b2c62316717a2e6230e93370..edb98df15980958c38a4fc3d011ce1bee1d98a67 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/node_sdp_adc_input_and_timing.vhd
@@ -286,7 +286,6 @@ begin
   gen_rx_ait : if g_no_jesd = false and g_use_tech_jesd204b_v2 = false generate
     u_rx_ait : entity work.sdp_adc_input_and_timing
     generic map (
-      g_no_rx                   => g_no_jesd,  -- when false use Rx and WG, else only use WG
       g_no_st_histogram         => g_no_st_histogram,
       g_buf_nof_data            => g_buf_nof_data,
       g_bsn_nof_clk_per_sync    => g_bsn_nof_clk_per_sync,  -- Default 200M, overide for short simulation
@@ -401,11 +400,10 @@ begin
     );
   end generate;  -- gen_rx_ait
 
-  -- Wire dp_clk to AIT when jesd is not used or when jesd IP tech_jesd204b_v2 is used
-  gen_dp_ait : if g_no_jesd = true or (g_no_jesd = false and g_use_tech_jesd204b_v2 = true) generate
+  -- Wire dp_clk to AIT when jesd IP tech_jesd204b_v2 is used, or when only the WG is used (so no jesd)
+  gen_dp_ait : if (g_no_jesd = false and g_use_tech_jesd204b_v2 = true) or g_no_jesd = true generate
     u_dp_ait : entity work.sdp_adc_input_and_timing
     generic map (
-      g_no_rx                   => g_no_jesd,  -- when false use Rx and WG, else only use WG
       g_no_st_histogram         => g_no_st_histogram,
       g_buf_nof_data            => g_buf_nof_data,
       g_bsn_nof_clk_per_sync    => g_bsn_nof_clk_per_sync,  -- Default 200M, overide for short simulation
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_adc_input_and_timing.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_adc_input_and_timing.vhd
index a821ed5603536208ae8e9b3bb253d0af90390e9b..8a53a0d6a035b87573d2570ea14250748e2af77a 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_adc_input_and_timing.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_adc_input_and_timing.vhd
@@ -36,7 +36,6 @@ use work.sdp_pkg.all;
 
 entity sdp_adc_input_and_timing is
   generic (
-    g_no_rx                   : boolean := false;  -- when false use Rx and WG, else use only WG
     g_no_st_histogram         : boolean := true;  -- when false use input histogram, else not to save block RAM
     g_buf_nof_data            : natural := c_sdp_V_si_db;
     g_bsn_nof_clk_per_sync    : natural := c_sdp_N_clk_per_sync;  -- Default 200M, overide for short simulation
@@ -115,60 +114,17 @@ architecture str of sdp_adc_input_and_timing is
   constant c_bs_block_size          : natural := c_sdp_N_fft;  -- =1024;
   constant c_dp_fifo_dc_size        : natural := 64;
 
-  -- Sosis and sosi arrays
-  signal dp_shiftram_snk_in_arr     : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst);
-  signal ant_sosi_arr               : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst);
+  -- Timestamp and streaming data arrays
   signal bs_sosi                    : t_dp_sosi := c_dp_sosi_rst;
   signal wg_sosi_arr                : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst);
+  signal ant_sosi_arr               : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst);
   signal mux_sosi_arr               : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst);
   signal nxt_mux_sosi_arr           : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst);
+  signal inp_sosi_arr               : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst);
   signal st_sosi_arr                : t_dp_sosi_arr(c_sdp_S_pn - 1 downto 0) := (others => c_dp_sosi_rst);
 begin
   out_sosi_arr <= st_sosi_arr;
 
-  gen_rx : if g_no_rx = false generate
-     -----------------------------------------------------------------------------
-    -- Time delay: dp_shiftram
-    -- . copied from unb1_bn_capture_input (apertif)
-    --   Array range reversal is not done because everything is DOWNTO
-    -- . the input valid is always '1', even when there is no data
-    -----------------------------------------------------------------------------
-    p_dp_shiftram_snk_in_arr : process(rx_sosi_arr)
-    begin
-      dp_shiftram_snk_in_arr <= rx_sosi_arr;
-      for I in 0 to c_sdp_S_pn - 1 loop
-        -- ADC data is stored in the upper 14 bits of the jesd rx_sosi.
-        dp_shiftram_snk_in_arr(I).data <= RESIZE_DP_SDATA(rx_sosi_arr(I).data(c_sdp_W_adc_jesd - 1 downto (c_sdp_W_adc_jesd - c_sdp_W_adc) ));
-        -- Force valid.
-        dp_shiftram_snk_in_arr(I).valid <= '1';
-      end loop;
-    end process;
-
-    u_dp_shiftram : entity dp_lib.dp_shiftram
-    generic map (
-      g_nof_streams => c_sdp_S_pn,
-      g_nof_words   => c_sdp_V_sample_delay,
-      g_data_w      => c_sdp_W_adc,
-      g_use_sync_in => true
-    )
-    port map (
-      dp_rst   => rx_rst,
-      dp_clk   => rx_clk,
-
-      mm_rst   => mm_rst,
-      mm_clk   => mm_clk,
-
-      sync_in  => bs_sosi.sync,
-
-      reg_mosi => reg_dp_shiftram_mosi,
-      reg_miso => reg_dp_shiftram_miso,
-
-      snk_in_arr => dp_shiftram_snk_in_arr,
-
-      src_out_arr => ant_sosi_arr
-    );
-  end generate;
-
   -----------------------------------------------------------------------------
   -- Timestamp
   -----------------------------------------------------------------------------
@@ -223,9 +179,8 @@ begin
   );
 
   -----------------------------------------------------------------------------
-  -- WG (Test Signal Generator)
+  -- WG (Waveworm Generator)
   -----------------------------------------------------------------------------
-
   u_wg_arr : entity diag_lib.mms_diag_wg_wideband_arr
   generic map (
     g_nof_streams        => c_sdp_S_pn,
@@ -262,44 +217,86 @@ begin
   );
 
   -----------------------------------------------------------------------------
-  -- ADC/WG Mux (Input Select)
+  -- ADC data
   -----------------------------------------------------------------------------
+  p_rx_rewire_data : process(rx_sosi_arr)
+  begin
+    ant_sosi_arr <= rx_sosi_arr;
+    for I in 0 to c_sdp_S_pn - 1 loop
+      -- ADC data is stored in the upper 14 bits of the jesd rx_sosi.
+      ant_sosi_arr(I).data <= RESIZE_DP_SDATA(rx_sosi_arr(I).data(c_sdp_W_adc_jesd - 1 downto (c_sdp_W_adc_jesd - c_sdp_W_adc) ));
+      ant_sosi_arr(I).valid <= rx_sosi_arr(I).valid;  -- connect, but not used
+    end loop;
+  end process;
 
+  -----------------------------------------------------------------------------
+  -- ADC/WG Mux (Input Select)
+  -----------------------------------------------------------------------------
   gen_mux : for I in 0 to c_sdp_S_pn - 1 generate
-    p_sosi : process(ant_sosi_arr(I), wg_sosi_arr(I))
+    p_mux : process(ant_sosi_arr(I), wg_sosi_arr(I))
     begin
       -- Default use the ADC data
-      nxt_mux_sosi_arr(I).data  <= ant_sosi_arr(I).data;
+      nxt_mux_sosi_arr(I).data <= ant_sosi_arr(I).data;
       if wg_sosi_arr(I).valid = '1' then
         -- Valid WG data overrules ADC data
         nxt_mux_sosi_arr(I).data <= wg_sosi_arr(I).data;
       end if;
+      -- Force valid = '1' to maintain synchronous processing, independent of
+      -- whether the ADC/WG data values are valid
+      nxt_mux_sosi_arr(I).valid <= '1';
     end process;
   end generate;
 
-  mux_sosi_arr  <= nxt_mux_sosi_arr when rising_edge(rx_clk);
+  mux_sosi_arr <= nxt_mux_sosi_arr when rising_edge(rx_clk);
 
   -----------------------------------------------------------------------------
-  -- Concatenate muxed data streams with bsn framing
+  -- Time delay: dp_shiftram
+  -- . copied from unb1_bn_capture_input (apertif)
+  --   Array range reversal is not done because everything is DOWNTO
+  -- . the input valid is always '1', even when there is no data, to avoid
+  --   shift misalignment between different signal inputs on different nodes
+  -- . the sync_in ensures that a new shift setting takes effect at the
+  --   bs_sosi.sync
   -----------------------------------------------------------------------------
+  u_dp_shiftram : entity dp_lib.dp_shiftram
+  generic map (
+    g_nof_streams => c_sdp_S_pn,
+    g_nof_words   => c_sdp_V_sample_delay,
+    g_data_w      => c_sdp_W_adc,
+    g_use_sync_in => true
+  )
+  port map (
+    dp_rst   => rx_rst,
+    dp_clk   => rx_clk,
+    mm_rst   => mm_rst,
+    mm_clk   => mm_clk,
 
+    sync_in  => bs_sosi.sync,
+
+    reg_mosi => reg_dp_shiftram_mosi,
+    reg_miso => reg_dp_shiftram_miso,
+
+    snk_in_arr => mux_sosi_arr,
+    src_out_arr => inp_sosi_arr
+  );
+
+  -----------------------------------------------------------------------------
+  -- Concatenate input data streams with BSN framing
+  -----------------------------------------------------------------------------
   gen_concat : for I in 0 to c_sdp_S_pn - 1 generate
-    p_sosi : process(mux_sosi_arr(I), bs_sosi)
+    p_concat : process(mux_sosi_arr(I), bs_sosi)
     begin
-      st_sosi_arr(I)       <= bs_sosi;
-      st_sosi_arr(I).data  <= mux_sosi_arr(I).data;
+      st_sosi_arr(I)       <= bs_sosi;  -- timestamp
+      st_sosi_arr(I).data  <= inp_sosi_arr(I).data;
     end process;
   end generate;
 
   ---------------------------------------------------------------------------------------
-  -- Diagnostics on the bsn-framed data
-  --   . BSN Monitor (ToDo: can be removed as not part of the spec)
-  --   . Aduh monitor
-  --   . Data Buffer (variable depth from 1k-128k)
+  -- Diagnostics on the BSN-framed data
   ---------------------------------------------------------------------------------------
 
   ---------------------------------------------------------------------------------------
-  -- BSN monitor (Block Checker)
+  -- BSN monitor, for sync, BSN and nof samples per sync
   ---------------------------------------------------------------------------------------
   u_bsn_monitor : entity dp_lib.mms_dp_bsn_monitor
   generic map (
@@ -322,7 +319,7 @@ begin
   );
 
   -----------------------------------------------------------------------------
-  -- Monitor ADU/WG output
+  -- Monitor ADU/WG output, for mean sum and power sum
   -----------------------------------------------------------------------------
   u_aduh_monitor : entity aduh_lib.mms_aduh_monitor_arr
   generic map (
@@ -337,7 +334,7 @@ begin
     mm_rst         => mm_rst,
     mm_clk         => mm_clk,
 
-    reg_mosi       => reg_aduh_monitor_mosi,  -- read only access to the signal path data mean sum and power sum registers
+    reg_mosi       => reg_aduh_monitor_mosi,
     reg_miso       => reg_aduh_monitor_miso,
     buf_mosi       => c_mem_mosi_rst,  -- Unused
     buf_miso       => OPEN,
@@ -350,9 +347,8 @@ begin
   );
 
   -----------------------------------------------------------------------------
-  -- Diagnostic Data Buffer
+  -- Diagnostic Data Buffer, for capturing raw time series data
   -----------------------------------------------------------------------------
-
   u_diag_data_buffer_bsn : entity diag_lib.mms_diag_data_buffer
   generic map (
     g_nof_streams  => c_sdp_S_pn,
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
index 0d029deee5d363a8e1c703dd7712f237de227266..aeef6fc98fcdcc4de0812b884fbc61a0ebb4e662 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
@@ -86,7 +86,7 @@ package sdp_pkg is
   constant c_sdp_S_sub_bf                  : natural := 488;
   constant c_sdp_R_os                      : natural := 2;  -- Oversampling factor of 2 for PFB.
   constant c_sdp_V_ring_pkt_len_max        : natural := 48;  -- for 16 nodes
-  constant c_sdp_V_sample_delay            : natural := 4096;
+  constant c_sdp_V_sample_delay            : natural := 1024;  -- 1024 uses 12 M20K, 2048 24 M20K and 4096 36 M20K
   constant c_sdp_V_si_db                   : natural := 1024;
   constant c_sdp_V_si_db_large             : natural := 131072;
   constant c_sdp_V_si_histogram            : natural := 512;
@@ -157,6 +157,12 @@ package sdp_pkg is
   -- c_sdp_nof_beamlets_per_longword * c_sdp_N_pol_bf * c_nof_complex = 2 * 2 * 2 = 8 octets
   subtype t_sdp_dual_pol_beamlet_in_longword is t_slv_8_arr(0 to 7);
 
+  -----------------------------------------------------------------------------
+  -- Signal input delay buffer (dp_shiftram)
+  -----------------------------------------------------------------------------
+  constant c_sdp_input_mux_latency : natural := 1;
+  constant c_sdp_shiftram_latency  : natural := c_shiftram_latency + c_sdp_input_mux_latency;
+
   -----------------------------------------------------------------------------
   -- PFB
   -----------------------------------------------------------------------------
diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_remote_ring.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_remote_ring.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..421f4496540b32e8393235abbc0d4a23388d1b55
--- /dev/null
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_beamformer_remote_ring.vhd
@@ -0,0 +1,165 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2023
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+--
+-- Author: E. Kooistra
+-- Purpose:
+-- . Test bench for multiple sdp_beamformer_output.vhd + ring_lane.vhd in a ring
+-- Description:
+-- . https://support.astron.nl/confluence/display/L2M/L5+SDPFW+Design+Document%3A+Beamformer
+--
+--   This tb is inspired by tb_lofar2_unb2c_sdp_station_bf_ring.vhd, however
+--   here the purpose is to simulate the memory usage of the circular buffer
+--   in the bsn_aligner_v2 at each node.
+--
+-- Usage:
+-- > as 8
+-- > run -a
+-------------------------------------------------------------------------------
+
+library IEEE, common_lib, dp_lib, reorder_lib;
+use IEEE.std_logic_1164.all;
+use common_lib.common_pkg.all;
+use common_lib.common_mem_pkg.all;
+use common_lib.tb_common_pkg.all;
+use common_lib.tb_common_mem_pkg.all;
+use dp_lib.dp_stream_pkg.all;
+use work.sdp_pkg.all;
+use work.tb_sdp_pkg.all;
+
+entity tb_sdp_beamformer_remote_ring is
+  generic (
+    g_nof_rn             : natural := 16  -- number of nodes in the ring
+  );
+end tb_sdp_beamformer_remote_ring;
+
+architecture tb of tb_sdp_beamformer_remote_ring is
+  constant c_dp_clk_period : time := 5 ns;  -- 200 MHz
+  constant c_mm_clk_period : time := 1 ns;  -- fast MM clk to speed up simulation
+
+  constant c_last_rn             : natural := g_nof_rn - 1;  -- first ring node has index RN = 0 by definition.
+
+  signal mm_init      : std_logic := '1';
+  signal tb_end       : std_logic := '0';
+  signal dp_clk       : std_logic := '1';
+  signal dp_rst       : std_logic;
+  signal mm_clk       : std_logic := '1';
+  signal mm_rst       : std_logic;
+
+  signal rn_index     : natural range 0 to c_sdp_N_pn_max - 1 := 0;
+
+begin
+  dp_rst <= '1', '0' after c_dp_clk_period * 7;
+  dp_clk <= (not dp_clk) or tb_end after c_dp_clk_period / 2;
+
+  mm_rst <= '1', '0' after c_mm_clk_period * 7;
+  mm_clk <= (not mm_clk) or tb_end after c_mm_clk_period / 2;
+
+  p_mm : process
+    variable v_offset : natural;
+  begin
+    proc_common_wait_until_low(dp_clk, mm_rst);
+    proc_common_wait_some_cycles(mm_clk, 10);
+
+    proc_common_wait_cross_clock_domain_latency(c_mm_clk_period, c_dp_clk_period, c_common_cross_clock_domain_latency * 2);
+    mm_init <= '0';
+    wait;
+  end process;
+
+
+  ------------------------------------------------------------------------------
+  -- DUT
+  ------------------------------------------------------------------------------
+  gen_dut : for RN in 0 to c_last_rn generate
+    -- Ring connections between nodes 0:c_last_rn,0
+    u_ring_lane_bf : entity ring_lib.ring_lane
+      generic map (
+        g_lane_direction            => 1,  -- transport in positive RN direction.
+        g_lane_data_w               => c_longword_w,
+        g_lane_packet_length        => c_lane_payload_nof_longwords_bf,
+        g_lane_total_nof_packets_w  => c_lane_total_nof_packets_w,
+        g_use_dp_layer              => true,
+        g_nof_rx_monitors           => 1,
+        g_nof_tx_monitors           => 1,
+        g_err_bi                    => c_err_bi,
+        g_nof_err_counts            => c_nof_err_counts,
+        g_bsn_at_sync_check_channel => c_bsn_at_sync_check_channel,
+        g_validate_channel          => c_validate_channel,
+        g_validate_channel_mode     => c_validate_channel_mode,
+        g_sync_timeout              => c_sync_timeout
+      )
+      port map (
+        mm_rst => mm_rst,
+        mm_clk => mm_clk,
+        dp_clk => dp_clk,
+        dp_rst => dp_rst,
+
+        from_lane_sosi     => bf_from_ri_sosi_arr(beamset_id),
+        to_lane_sosi       => bf_to_ri_sosi_arr(beamset_id),
+        lane_rx_cable_sosi => lane_rx_cable_sosi_arr(1 + beamset_id),
+        lane_rx_board_sosi => lane_rx_board_sosi_arr(1 + beamset_id),
+        lane_tx_cable_sosi => lane_tx_cable_sosi_arr(1 + beamset_id),
+        lane_tx_board_sosi => lane_tx_board_sosi_arr(1 + beamset_id),
+        bs_sosi            => bf_bs_sosi,  -- used for bsn and sync
+
+        reg_ring_lane_info_copi                => reg_ring_lane_info_bf_copi_arr(beamset_id),
+        reg_ring_lane_info_cipo                => reg_ring_lane_info_bf_cipo_arr(beamset_id),
+        reg_bsn_monitor_v2_ring_rx_copi        => reg_bsn_monitor_v2_ring_rx_bf_copi_arr(beamset_id),
+        reg_bsn_monitor_v2_ring_rx_cipo        => reg_bsn_monitor_v2_ring_rx_bf_cipo_arr(beamset_id),
+        reg_bsn_monitor_v2_ring_tx_copi        => reg_bsn_monitor_v2_ring_tx_bf_copi_arr(beamset_id),
+        reg_bsn_monitor_v2_ring_tx_cipo        => reg_bsn_monitor_v2_ring_tx_bf_cipo_arr(beamset_id),
+        reg_dp_block_validate_err_copi         => reg_dp_block_validate_err_bf_copi_arr(beamset_id),
+        reg_dp_block_validate_err_cipo         => reg_dp_block_validate_err_bf_cipo_arr(beamset_id),
+        reg_dp_block_validate_bsn_at_sync_copi => reg_dp_block_validate_bsn_at_sync_bf_copi_arr(beamset_id),
+        reg_dp_block_validate_bsn_at_sync_cipo => reg_dp_block_validate_bsn_at_sync_bf_cipo_arr(beamset_id),
+
+        this_rn   => this_rn,
+        N_rn      => ring_info.N_rn,
+        rx_select => ring_info.use_cable_to_previous_rn,
+        tx_select => ring_info.use_cable_to_next_rn
+      );
+
+    -- Intermediate BF alignment and summation at each node
+    u_sdp_beamformer_remote : entity work.sdp_beamformer_remote
+      port map (
+        dp_clk        => dp_clk,
+        dp_rst        => dp_rst,
+
+        rn_index      => rn_index,
+
+        local_bf_sosi : in  t_dp_sosi;
+        from_ri_sosi  : in  t_dp_sosi;
+        to_ri_sosi    : out t_dp_sosi;
+        bf_sum_sosi   : out t_dp_sosi;
+
+        mm_rst        : in  std_logic;
+        mm_clk        : in  std_logic;
+
+        reg_bsn_align_copi : in  t_mem_copi := c_mem_copi_rst;
+        reg_bsn_align_cipo : out t_mem_cipo;
+
+        reg_bsn_monitor_v2_bsn_align_input_copi  : in  t_mem_copi := c_mem_copi_rst;
+        reg_bsn_monitor_v2_bsn_align_input_cipo  : out t_mem_cipo;
+
+        reg_bsn_monitor_v2_bsn_align_output_copi : in  t_mem_copi := c_mem_copi_rst;
+        reg_bsn_monitor_v2_bsn_align_output_cipo : out t_mem_cipo
+      );
+end generate;  -- gen_dut
+
+end tb;
diff --git a/doc/erko_howto_tools.txt b/doc/erko_howto_tools.txt
index b934aa032f9cdd312019fbcfb9cb881371db0d12..2ed1a047c7a79fb283c2d64f6099130986d150e8 100755
--- a/doc/erko_howto_tools.txt
+++ b/doc/erko_howto_tools.txt
@@ -287,6 +287,26 @@ Last SDPFW version used in 2022:
 *******************************************************************************
 * Flash and reboot on L2TS using tunnel to SDPTR
 *******************************************************************************
+22 feb 2024
+
+# Vanaf machine in ASTRON netwerk
+cd git/sdptr
+. ./init_sdptr.sh
+# even kijken of de sdp translator te bereiken is:
+sdp_rw.py --host cs001c.control.lofar --port 4840 -r firmware_version
+
+# als dat lukte:
+sdp_firmware.py --host cs001c.control.lofar --port 4840 --write --image USER --file ~/images/*.rbf   # juiste rbf opgeven
+
+# eventueel, om te controleren
+sdp_firmware.py --host cs001c.control.lofar --port 4840 --read --verify --image USER --file ~/images/*.rbf   # juiste rbf opgeven
+
+# om image aktief te maken
+sdp_rw.py --host cs001c.control.lofar --port 4840 -w boot_image [1]*16
+
+# checken of het gebeurt is:
+sdp_rw.py --host cs001c.control.lofar --port 4840 -r firmware_version
+
 
 4 sept 2023
 How to reach the SDP Translators on LCU2 in CS001? I got this from Reinier and Pieter to tunnel to the SDPTR, so that I can run the flash commands:
diff --git a/libraries/base/common/src/vhdl/common_pkg.vhd b/libraries/base/common/src/vhdl/common_pkg.vhd
index 9fdebec8751b6b80700e888d8d71b31456b45b13..90462168dac8c42962557e50a1786a50b946b256 100644
--- a/libraries/base/common/src/vhdl/common_pkg.vhd
+++ b/libraries/base/common/src/vhdl/common_pkg.vhd
@@ -95,6 +95,8 @@ package common_pkg is
 
   constant c_fifo_afull_margin    : natural := 4;  -- default or minimal FIFO almost full margin
 
+  constant c_shiftram_latency     : natural := 3;  -- minimal latency of common_shiftram when data_in_shift = 0
+
   -- DSP
   constant c_dsp_mult_w           : natural := 18;  -- Width of the embedded multipliers in Stratix IV (and Arria 10 for 2 multipliers per DSP block)
   constant c_dsp_mult_18_w        : natural := 18;  -- Width of the embedded multipliers in Stratix IV (and Arria 10 for 2 multipliers per DSP block)
diff --git a/libraries/base/common/src/vhdl/common_shiftram.vhd b/libraries/base/common/src/vhdl/common_shiftram.vhd
index 382a87a482c9a6c1d4976ea96cbbb0fa2357cdf5..7770e46a34b7345415fa6f016d77b1f4964f214a 100644
--- a/libraries/base/common/src/vhdl/common_shiftram.vhd
+++ b/libraries/base/common/src/vhdl/common_shiftram.vhd
@@ -30,6 +30,8 @@
 --   interpreted as the maximum value.
 -- . data_out_shift will always indicate the shift as applied to the
 --   corresponding data_out.
+-- . The common_shiftram has a latency of c_shiftram_latency = 3, so the
+--   actual shift is c_shiftram_latency + data_in_shift.
 --
 --
 --    Cycle 0              Cycle 1             Cycle 2           Cycle 3
diff --git a/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b_v2.vhd b/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b_v2.vhd
index 1c0d8ec310a410658266cf2f48a8c9ab18e41c86..06e7aa982415c438d910995dff7c8e2841fcba25 100644
--- a/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b_v2.vhd
+++ b/libraries/technology/ip_arria10_e1sg/jesd204b/ip_arria10_e1sg_jesd204b_v2.vhd
@@ -497,6 +497,10 @@ begin
     -- JESD204B IP is synchronized.
     wr_rst <= not wr_core_pll_locked;
 
+    -- The FIFO g_data_w = c_jesd204b_rx_data_w = 32b does not have to be optimized
+    -- for the fact that the actual ADC data width is 14b instead of 16b. It appears
+    -- that Quartus synthesis will automatically optimize away the unused bits from
+    -- the FIFO data width.
     u_dp_fifo_dc_arr : entity dp_lib.dp_fifo_dc_arr
       generic map (
         g_nof_streams    => g_nof_streams,
@@ -533,13 +537,22 @@ begin
     -- dp_index. This is because reading ab, cd, ef, ... is equivalent to reading
     -- bc, de, fg, ... However the phase of dp_ready with respect to dp_index is
     -- important for reading the sync, because if dp_ready has the wrong phase,
-    -- then the sync is missed at the FIFO output.
+    -- then the sync is missed at the FIFO output. The reason that the sync can be
+    -- missed is that it is passed on via the sosi.sync, which means that it is
+    -- forced to '0' when sosi.valid = '0' due to dp_ready = '0'. If the sync would
+    -- be passed on as a sosi.data bit, then it would hold its '1' value also during
+    -- sosi.valid = '0'.
     -- . If dp_index = '0' or '1' initialy, then in both cases use dp_ready <= not
     --   dp_index, and then in both cases the latency dp_sosi.sync and data = 1000 is
     --   then 340 ns
-    -- . Do not use dp_ready <= dp_index, because then the dp_sosi.sync gets missed.
+    -- . Do not use dp_ready <= dp_index, because then they have opposite phase
+    --   and then dp_sosi.sync gets missed.
     -- Therefore choose to use dp_index = '0' initially, because then dp_ready =
-    -- dp_index always.
+    -- dp_index always. Then in the dp_clk cycle after dp_ready = '1' the high part
+    -- data is read (because dp_index = '0') and the sync is available (because
+    -- then valid = '1'). In the next dp_clk cycle the low part is read (because
+    -- dp_index = '1') and the dp_ready = '1', to prepare for the next data word
+    -- read from the FIFO.
     p_fsm_dp_index : process(dp_rst, dp_clk)
     begin
       if dp_rst = '1' then
diff --git a/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd b/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd
index 79501ebef68c71773c63068d39457489e14adaf6..a21f86e148b37736da66616bc94b730692369e22 100644
--- a/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd
+++ b/libraries/technology/ip_arria10_e2sg/jesd204b/ip_arria10_e2sg_jesd204b_v2.vhd
@@ -497,6 +497,10 @@ begin
     -- JESD204B IP is synchronized.
     wr_rst <= not wr_core_pll_locked;
 
+    -- The FIFO g_data_w = c_jesd204b_rx_data_w = 32b does not have to be optimized
+    -- for the fact that the actual ADC data width is 14b instead of 16b. It appears
+    -- that Quartus synthesis will automatically optimize away the unused bits from
+    -- the FIFO data width.
     u_dp_fifo_dc_arr : entity dp_lib.dp_fifo_dc_arr
       generic map (
         g_nof_streams    => g_nof_streams,
@@ -533,13 +537,22 @@ begin
     -- dp_index. This is because reading ab, cd, ef, ... is equivalent to reading
     -- bc, de, fg, ... However the phase of dp_ready with respect to dp_index is
     -- important for reading the sync, because if dp_ready has the wrong phase,
-    -- then the sync is missed at the FIFO output.
+    -- then the sync is missed at the FIFO output. The reason that the sync can be
+    -- missed is that it is passed on via the sosi.sync, which means that it is
+    -- forced to '0' when sosi.valid = '0' due to dp_ready = '0'. If the sync would
+    -- be passed on as a sosi.data bit, then it would hold its '1' value also during
+    -- sosi.valid = '0'.
     -- . If dp_index = '0' or '1' initialy, then in both cases use dp_ready <= not
     --   dp_index, and then in both cases the latency dp_sosi.sync and data = 1000 is
     --   then 340 ns
-    -- . Do not use dp_ready <= dp_index, because then the dp_sosi.sync gets missed.
+    -- . Do not use dp_ready <= dp_index, because then they have opposite phase
+    --   and then dp_sosi.sync gets missed.
     -- Therefore choose to use dp_index = '0' initially, because then dp_ready =
-    -- dp_index always.
+    -- dp_index always. Then in the dp_clk cycle after dp_ready = '1' the high part
+    -- data is read (because dp_index = '0') and the sync is available (because
+    -- then valid = '1'). In the next dp_clk cycle the low part is read (because
+    -- dp_index = '1') and the dp_ready = '1', to prepare for the next data word
+    -- read from the FIFO.
     p_fsm_dp_index : process(dp_rst, dp_clk)
     begin
       if dp_rst = '1' then