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
index e0142064f95af09ef719c1a87acb57668575ce90..fe1be5239c92c47f865fa2c6ed271ec2790d7db7 100644
--- 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
@@ -24,10 +24,31 @@
 -- 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
+-- . 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.
 --
+-- . Block diagram:
+--
+--   ring lane serial links for ring nodes RN = 0 to c_last_rn:
+--
+--     tr_10gbe_ring_serial_tx_arr --> tr_10gbe_ring_serial_rx_arr
+--
+--         /<-------------------------------------------------------------\
+--         \---> 0 ---> RN - 1  --->  RN  --->  RN + 1 ---> c_last_rn --->/
+--                                    | ^
+--    tr_10gbe_ring_serial_tx_arr(RN) | | tr_10gbe_ring_serial_tx_arr(RN)
+--                                    v |
+--                                  tr10Gbe
+--                                    | ^
+--      tr_10gbe_ring_rx_sosi_arr(RN) | | tr_10gbe_ring_tx_sosi_arr(RN)
+--                                    v |
+--                                 ring_lane
+--                                    | ^
+--               from_ri_sosi_arr(RN) | | to_ri_sosi_arr(RN)
+--                                    v |
+--        local_bf_sosi --> sdp_beamformer_remote --> bf_sum_sosi_arr(RN)
+--                                                    bf_sum_sosi
 -- Usage:
 -- > as 8
 -- > run -a
@@ -39,6 +60,7 @@ 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 common_lib.common_str_pkg.all;
 use dp_lib.dp_stream_pkg.all;
 use ring_lib.ring_pkg.all;
 use tech_pll_lib.tech_pll_component_pkg.all;
@@ -47,7 +69,7 @@ use work.tb_sdp_pkg.all;
 
 entity tb_sdp_beamformer_remote_ring is
   generic (
-    g_nof_rn  : natural := 4  -- number of nodes in the ring
+    g_nof_rn  : natural := 16  -- number of nodes in the ring
   );
 end tb_sdp_beamformer_remote_ring;
 
@@ -63,6 +85,8 @@ architecture tb of tb_sdp_beamformer_remote_ring is
   -- choose sync interval somewhat longer than maximum BF ring latency
   constant c_nof_blocks_per_sync       : natural := largest(10, (g_nof_rn + 1) * 2);
   constant c_nof_sync                  : natural := 2;
+  constant c_local_bf_re               : integer := 1;
+  constant c_local_bf_im               : integer := 2;
 
   -- Ring lane packets
   constant c_last_rn                   : natural := g_nof_rn - 1;  -- first ring node has index RN = 0 by definition.
@@ -83,6 +107,9 @@ architecture tb of tb_sdp_beamformer_remote_ring is
   constant c_validate_channel_mode     : string  := "=";
   constant c_sync_timeout              : natural := c_block_period * (c_nof_blocks_per_sync + 1);
 
+  -- Address widths of a single MM instance
+  constant c_addr_w_reg_ring_lane_info_bf          : natural := 1;
+
   signal mm_init                : std_logic := '1';
   signal tb_end                 : std_logic := '0';
   signal dp_clk                 : std_logic := '1';
@@ -97,40 +124,56 @@ architecture tb of tb_sdp_beamformer_remote_ring is
   signal stimuli_rst            : std_logic;
   signal stimuli_end            : std_logic;
 
+  signal stimuli_sosi           : t_dp_sosi;
   signal local_bf_sosi          : t_dp_sosi;
   signal bf_bs_sosi             : t_dp_sosi;
-  signal from_ri_sosi_arr       : t_dp_sosi_arr(0 to c_last_rn);
-  signal to_ri_sosi_arr         : t_dp_sosi_arr(0 to c_last_rn);
-  signal bf_sum_sosi_arr        : t_dp_sosi_arr(0 to c_last_rn);
+  signal from_ri_sosi_arr       : t_dp_sosi_arr(c_last_rn downto 0);
+  signal to_ri_sosi_arr         : t_dp_sosi_arr(c_last_rn downto 0);
+  signal bf_sum_sosi_arr        : t_dp_sosi_arr(c_last_rn downto 0);
   signal bf_sum_sosi            : t_dp_sosi;
 
   -- 10GbE ring
-  signal tr_10gbe_ring_rx_sosi_arr    : t_dp_sosi_arr(0 to c_last_rn) := (others => c_dp_sosi_rst);
-  signal tr_10gbe_ring_tx_sosi_arr    : t_dp_sosi_arr(0 to c_last_rn) := (others => c_dp_sosi_rst);
-  signal tr_10gbe_ring_serial_rx_arr  : std_logic_vector(0 to c_last_rn) := (others => '0');
-  signal tr_10gbe_ring_serial_tx_arr  : std_logic_vector(0 to c_last_rn) := (others => '0');
+  signal tr_10gbe_ring_rx_sosi_arr    : t_dp_sosi_arr(c_last_rn downto 0) := (others => c_dp_sosi_rst);
+  signal tr_10gbe_ring_tx_sosi_arr    : t_dp_sosi_arr(c_last_rn downto 0) := (others => c_dp_sosi_rst);
+  signal tr_10gbe_ring_serial_rx_arr  : std_logic_vector(c_last_rn downto 0) := (others => '0');
+  signal tr_10gbe_ring_serial_tx_arr  : std_logic_vector(c_last_rn downto 0) := (others => '0');
 
   -- BF ring MM points
-  signal reg_ring_lane_info_bf_copi_arr         : t_mem_copi_arr(0 to c_last_rn) := (others => c_mem_copi_rst);
-  signal reg_ring_lane_info_bf_cipo_arr         : t_mem_cipo_arr(0 to c_last_rn) := (others => c_mem_cipo_rst);
-  signal reg_bsn_monitor_v2_ring_rx_bf_copi_arr : t_mem_copi_arr(0 to c_last_rn) := (others => c_mem_copi_rst);
-  signal reg_bsn_monitor_v2_ring_rx_bf_cipo_arr : t_mem_cipo_arr(0 to c_last_rn) := (others => c_mem_cipo_rst);
-  signal reg_bsn_monitor_v2_ring_tx_bf_copi_arr : t_mem_copi_arr(0 to c_last_rn) := (others => c_mem_copi_rst);
-  signal reg_bsn_monitor_v2_ring_tx_bf_cipo_arr : t_mem_cipo_arr(0 to c_last_rn) := (others => c_mem_cipo_rst);
-  signal reg_dp_block_validate_err_bf_copi_arr  : t_mem_copi_arr(0 to c_last_rn) := (others => c_mem_copi_rst);
-  signal reg_dp_block_validate_err_bf_cipo_arr  : t_mem_cipo_arr(0 to c_last_rn) := (others => c_mem_cipo_rst);
-  signal reg_dp_block_validate_bsn_at_sync_bf_copi_arr : t_mem_copi_arr(0 to c_last_rn) :=
+  signal reg_ring_lane_info_bf_copi_arr         : t_mem_copi_arr(c_last_rn downto 0) := (others => c_mem_copi_rst);
+  signal reg_ring_lane_info_bf_cipo_arr         : t_mem_cipo_arr(c_last_rn downto 0) := (others => c_mem_cipo_rst);
+  signal reg_ring_lane_info_bf_copi             : t_mem_copi := c_mem_copi_rst;
+  signal reg_ring_lane_info_bf_cipo             : t_mem_cipo := c_mem_cipo_rst;
+  signal reg_bsn_monitor_v2_ring_rx_bf_copi_arr : t_mem_copi_arr(c_last_rn downto 0) := (others => c_mem_copi_rst);
+  signal reg_bsn_monitor_v2_ring_rx_bf_cipo_arr : t_mem_cipo_arr(c_last_rn downto 0) := (others => c_mem_cipo_rst);
+  signal reg_bsn_monitor_v2_ring_rx_bf_copi     : t_mem_copi := c_mem_copi_rst;
+  signal reg_bsn_monitor_v2_ring_rx_bf_cipo     : t_mem_cipo := c_mem_cipo_rst;
+  signal reg_bsn_monitor_v2_ring_tx_bf_copi_arr : t_mem_copi_arr(c_last_rn downto 0) := (others => c_mem_copi_rst);
+  signal reg_bsn_monitor_v2_ring_tx_bf_cipo_arr : t_mem_cipo_arr(c_last_rn downto 0) := (others => c_mem_cipo_rst);
+  signal reg_bsn_monitor_v2_ring_tx_bf_copi     : t_mem_copi := c_mem_copi_rst;
+  signal reg_bsn_monitor_v2_ring_tx_bf_cipo     : t_mem_cipo := c_mem_cipo_rst;
+  signal reg_dp_block_validate_err_bf_copi_arr  : t_mem_copi_arr(c_last_rn downto 0) := (others => c_mem_copi_rst);
+  signal reg_dp_block_validate_err_bf_cipo_arr  : t_mem_cipo_arr(c_last_rn downto 0) := (others => c_mem_cipo_rst);
+  signal reg_dp_block_validate_err_bf_copi      : t_mem_copi := c_mem_copi_rst;
+  signal reg_dp_block_validate_err_bf_cipo      : t_mem_cipo := c_mem_cipo_rst;
+  signal reg_dp_block_validate_bsn_at_sync_bf_copi_arr : t_mem_copi_arr(c_last_rn downto 0) :=
                                                          (others => c_mem_copi_rst);
-  signal reg_dp_block_validate_bsn_at_sync_bf_cipo_arr : t_mem_cipo_arr(0 to c_last_rn) :=
+  signal reg_dp_block_validate_bsn_at_sync_bf_cipo_arr : t_mem_cipo_arr(c_last_rn downto 0) :=
                                                          (others => c_mem_cipo_rst);
+  signal reg_dp_block_validate_bsn_at_sync_bf_copi     : t_mem_copi := c_mem_copi_rst;
+  signal reg_dp_block_validate_bsn_at_sync_bf_cipo     : t_mem_cipo := c_mem_cipo_rst;
+
+  signal FPGA_bf_ring_nof_transport_hops_R       : t_natural_arr(c_last_rn downto 0);
+  signal FPGA_bf_ring_rx_latency_R               : t_integer_arr(c_last_rn downto 0);
 
   -- BSN aligner MM points
-  signal reg_bsn_align_v2_bf_copi_arr            : t_mem_copi_arr(0 to c_last_rn) := (others => c_mem_copi_rst);
-  signal reg_bsn_align_v2_bf_cipo_arr            : t_mem_cipo_arr(0 to c_last_rn) := (others => c_mem_cipo_rst);
-  signal reg_bsn_monitor_v2_rx_align_bf_copi_arr : t_mem_copi_arr(0 to c_last_rn) := (others => c_mem_copi_rst);
-  signal reg_bsn_monitor_v2_rx_align_bf_cipo_arr : t_mem_cipo_arr(0 to c_last_rn) := (others => c_mem_cipo_rst);
-  signal reg_bsn_monitor_v2_aligned_bf_copi_arr  : t_mem_copi_arr(0 to c_last_rn) := (others => c_mem_copi_rst);
-  signal reg_bsn_monitor_v2_aligned_bf_cipo_arr  : t_mem_cipo_arr(0 to c_last_rn) := (others => c_mem_cipo_rst);
+  signal reg_bsn_align_v2_bf_copi_arr            : t_mem_copi_arr(c_last_rn downto 0) := (others => c_mem_copi_rst);
+  signal reg_bsn_align_v2_bf_cipo_arr            : t_mem_cipo_arr(c_last_rn downto 0) := (others => c_mem_cipo_rst);
+  signal reg_bsn_align_v2_bf_copi                : t_mem_copi := c_mem_copi_rst;
+  signal reg_bsn_align_v2_bf_cipo                : t_mem_cipo := c_mem_cipo_rst;
+  signal reg_bsn_monitor_v2_rx_align_bf_copi_arr : t_mem_copi_arr(c_last_rn downto 0) := (others => c_mem_copi_rst);
+  signal reg_bsn_monitor_v2_rx_align_bf_cipo_arr : t_mem_cipo_arr(c_last_rn downto 0) := (others => c_mem_cipo_rst);
+  signal reg_bsn_monitor_v2_aligned_bf_copi_arr  : t_mem_copi_arr(c_last_rn downto 0) := (others => c_mem_copi_rst);
+  signal reg_bsn_monitor_v2_aligned_bf_cipo_arr  : t_mem_cipo_arr(c_last_rn downto 0) := (others => c_mem_cipo_rst);
 
 begin
   dp_rst <= '1', '0' after c_dp_clk_period * 7;
@@ -156,27 +199,78 @@ begin
     rst               => stimuli_rst,
     clk               => dp_clk,
     -- Generate stimuli
-    src_out           => local_bf_sosi,
+    src_out           => stimuli_sosi,
     -- End of stimuli
     tb_end            => stimuli_end
   );
 
+  -- Use constant beamlet data to ease verification of (intermediate) beamlet sums at each node
+  p_local_bf_sosi : process(stimuli_sosi)
+  begin
+    local_bf_sosi <= stimuli_sosi;
+    local_bf_sosi.data <= TO_DP_SDATA(0);
+    local_bf_sosi.re <= TO_DP_DSP_DATA(c_local_bf_re);
+    local_bf_sosi.im <= TO_DP_DSP_DATA(c_local_bf_im);
+  end process;
+
   bf_bs_sosi <= local_bf_sosi;
   bf_sum_sosi <= bf_sum_sosi_arr(c_last_rn);
 
   p_mm : process
-    variable v_offset : natural;
+    variable v_span               : natural;
+    variable v_offset             : natural;
+    variable v_transport_nof_hops : 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);
+    -- Write FPGA_bf_ring_nof_transport_hops_RW = ring_lane_info.transport_nof_hops
+    v_span := 2**c_addr_w_reg_ring_lane_info_bf;
+    for RN in 0 to c_last_rn LOOP
+      v_offset := 1 + RN * v_span;
+      v_transport_nof_hops := 1;
+      if RN = c_last_rn then
+        v_transport_nof_hops := 0;
+      end if;
+      proc_mem_mm_bus_wr(v_offset, v_transport_nof_hops, mm_clk,
+                         reg_ring_lane_info_bf_cipo, reg_ring_lane_info_bf_copi);
+    end loop;
+    proc_common_wait_cross_clock_domain_latency(c_mm_clk_period, c_dp_clk_period,
+                                                c_common_cross_clock_domain_latency * 2);
+    -- Readback FPGA_bf_ring_nof_transport_hops_R
+    for RN in 0 to c_last_rn LOOP
+      v_offset := 1 + RN * v_span;
+      proc_mem_mm_bus_rd(v_offset, mm_clk, reg_ring_lane_info_bf_cipo, reg_ring_lane_info_bf_copi);
+      proc_mem_mm_bus_rd_latency(1, mm_clk);
+      FPGA_bf_ring_nof_transport_hops_R(RN) <= TO_UINT(reg_ring_lane_info_bf_cipo.rddata(c_word_w - 1 downto 0));
+    end loop;
+
+    -- Wait until second bf_sum_sosi.sync
+    proc_common_wait_until_hi_lo(dp_clk, bf_sum_sosi.sync);
+    proc_common_wait_until_hi_lo(dp_clk, bf_sum_sosi.sync);
+    -- Read FPGA_bf_ring_rx_latency_R
+    v_span := 2**c_sdp_reg_bsn_monitor_v2_addr_w;
+    for RN in 0 to c_last_rn LOOP
+      v_offset := 6 + RN * v_span;
+      proc_mem_mm_bus_rd(v_offset, mm_clk, reg_bsn_monitor_v2_ring_rx_bf_cipo, reg_bsn_monitor_v2_ring_rx_bf_copi);
+      proc_mem_mm_bus_rd_latency(1, mm_clk);
+      FPGA_bf_ring_rx_latency_R(RN) <= TO_UINT(reg_bsn_monitor_v2_ring_rx_bf_cipo.rddata(c_word_w - 1 downto 0));
+    end loop;
+
     mm_init <= '0';
 
     -- Wait to stop simulation
     proc_common_wait_until_high(dp_clk, stimuli_end);
     proc_common_wait_some_cycles(dp_clk, 1000);
+
+    -- Print results
+    print_str("FPGA_bf_ring_rx_latency_R");
+    for RN in 0 to c_last_rn loop
+       print_str("  RN " & int_to_str(RN) & ": " & int_to_str(FPGA_bf_ring_rx_latency_R(RN)));
+    end Loop;
+
     tb_end <= '1';
     wait;
   end process;
@@ -225,12 +319,12 @@ begin
       dp_rst                => dp_rst,
       dp_clk                => dp_clk,
 
-      src_out_arr           => tr_10gbe_ring_rx_sosi_arr(RN to RN),
-      snk_in_arr            => tr_10gbe_ring_tx_sosi_arr(RN to RN),
+      src_out_arr           => tr_10gbe_ring_rx_sosi_arr(RN downto RN),
+      snk_in_arr            => tr_10gbe_ring_tx_sosi_arr(RN downto RN),
 
       -- Serial IO
-      serial_tx_arr         => tr_10gbe_ring_serial_tx_arr(RN to RN),
-      serial_rx_arr         => tr_10gbe_ring_serial_rx_arr(RN to RN)
+      serial_tx_arr         => tr_10gbe_ring_serial_tx_arr(RN downto RN),
+      serial_rx_arr         => tr_10gbe_ring_serial_rx_arr(RN downto RN)
     );
 
     -- Ring lane access at each node
@@ -306,7 +400,22 @@ begin
       );
   end generate;  -- gen_dut
 
+  ------------------------------------------------------------------------------
+  -- Verify bf_sum_sosi_arr at every node, to check that no packets were lost
+  ------------------------------------------------------------------------------
+  p_verify_bf_sum : process(dp_clk)
+  begin
+    for RN in 0 to c_last_rn Loop
+      if bf_sum_sosi_arr(RN).valid = '1' then
+        assert TO_SINT(bf_sum_sosi_arr(RN).re) = (RN + 1) * c_local_bf_re report "Wrong BF re sum at node " & int_to_str(RN) severity error;
+        assert TO_SINT(bf_sum_sosi_arr(RN).im) = (RN + 1) * c_local_bf_im report "Wrong BF im sum at node " & int_to_str(RN) severity error;
+      end if;
+    end loop;
+  end process;
+
+  ------------------------------------------------------------------------------
   -- 10GbE clocks
+  ------------------------------------------------------------------------------
   u_tech_pll_xgmii_mac_clocks : entity tech_pll_lib.tech_pll_xgmii_mac_clocks
   port map (
     refclk_644 => SA_CLK,
@@ -316,4 +425,45 @@ begin
     rst_156    => tr_ref_rst_156,
     rst_312    => open
   );
+
+  ------------------------------------------------------------------------------
+  -- MM bus multiplexers
+  ------------------------------------------------------------------------------
+  -- Use common_mem_mux to avoid (vcom-1450) Actual (indexed name) for formal "mm_miso" is not a static signal name.
+  -- Use downto range for _arr, to match downto range of mosi_arr.
+  u_mem_mux_reg_ring_lane_info_bf : entity common_lib.common_mem_mux
+  generic map (
+    g_nof_mosi    => g_nof_rn,
+    g_mult_addr_w => c_addr_w_reg_ring_lane_info_bf
+  )
+  port map (
+    mosi     => reg_ring_lane_info_bf_copi,
+    miso     => reg_ring_lane_info_bf_cipo,
+    mosi_arr => reg_ring_lane_info_bf_copi_arr,
+    miso_arr => reg_ring_lane_info_bf_cipo_arr
+  );
+
+  u_mem_mux_reg_bsn_monitor_v2_ring_rx_bf : entity common_lib.common_mem_mux
+  generic map (
+    g_nof_mosi    => g_nof_rn,
+    g_mult_addr_w => c_sdp_reg_bsn_monitor_v2_addr_w
+  )
+  port map (
+    mosi     => reg_bsn_monitor_v2_ring_rx_bf_copi,
+    miso     => reg_bsn_monitor_v2_ring_rx_bf_cipo,
+    mosi_arr => reg_bsn_monitor_v2_ring_rx_bf_copi_arr,
+    miso_arr => reg_bsn_monitor_v2_ring_rx_bf_cipo_arr
+  );
+
+  u_mem_mux_reg_bsn_align_v2_bf : entity common_lib.common_mem_mux
+  generic map (
+    g_nof_mosi    => g_nof_rn,
+    g_mult_addr_w => c_sdp_reg_bsn_align_v2_addr_w
+  )
+  port map (
+    mosi     => reg_bsn_align_v2_bf_copi,
+    miso     => reg_bsn_align_v2_bf_cipo,
+    mosi_arr => reg_bsn_align_v2_bf_copi_arr,
+    miso_arr => reg_bsn_align_v2_bf_cipo_arr
+  );
 end tb;