diff --git a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_ring/tb_lofar2_unb2c_sdp_station_tbuf_ring.vhd b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_ring/tb_lofar2_unb2c_sdp_station_tbuf_ring.vhd
index 43237d9eac9bb89abaa23e5f12beffe81889c79c..f81e1df40a46955dae801868debc9ad840f282d1 100644
--- a/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_ring/tb_lofar2_unb2c_sdp_station_tbuf_ring.vhd
+++ b/applications/lofar2/designs/lofar2_unb2c_sdp_station/revisions/lofar2_unb2c_sdp_station_tbuf_ring/tb_lofar2_unb2c_sdp_station_tbuf_ring.vhd
@@ -21,29 +21,30 @@
 -------------------------------------------------------------------------------
 --
 -- Author: E. Kooistra
--- Purpose: Self-checking testbench for lofar2_unb2c_sdp_station_tbuf_ring
---   using WG data.
---
+-- Purpose: Self-checking testbench for lofar2_unb2c_sdp_station_tbuf_ring using WG data.
 -- Description:
---   MM control actions:
+--   Record, freeze and dump TBuf [2] from multiple nodes in the ring [3]. Focus is on the ring. The TBuf functionality
+--   itself is verified in tb_lofar2_unb2c_sdp_station_tbuf_one.
+--
+--   E.g. for g_nof_rn = 4:
+--   . the WG data is DC with level equal to RN
+--   . ring lane in negative direction so from RN-3 to RN-0 via PCB connections and from RN-0 to RN-4 via cable
+--   . dump output via 10GbE on last node RN-4
 --
---   A) Set up WG and verify sp_power_sum as in tb_lofar2_unb2c_sdp_station_adc / bf.vhd
---      . use DC level (= sp index) signal at the signal inputs, so all SP carry DC.
---   B) Record, freeze and dump TBuf [2]: TODO
---      . g_rs_block_size, g_ddr_buffer_size to verify recording beyond buffer full.
---      . g_dump_page_offset, g_dump_nof_pages to verify dumping across begin and end of buffer
---      . g_dump_enables to verify dumping one or more antenna inputs
---      . g_dump_inter_packet_gap to vary dump rate.
---      . log, verify: state, total counts
+--     RN-3 --> PCB --> RN-2 --> PCB --> RN-1 --> PCB --> RN-0 --> cable --> RN-4 is last node
+--     WG               WG               WG               WG                 WG
+--     DDR4             DDR4             DDR4             DDR4               DDR4
+--                                                                           10GbE
 --
---   . g_ddr_buffer_size:
---     Use Use g_ddr_buffer_size with e.g. 256 words to have smaller circular buffer independend of fixed
---     c_tech_ddr4_sim_4k_64 with size 4096 words, to speed up simulation of wrap around of circular buffer full.
+-- TODO:
+-- . test parallel dump and serial dump
+-- . read ring MP
 --
 -- References:
 -- [1] https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L5+SDPFW+Design+Document%3A+Transient+buffer+raw+data
 -- [2] https://support.astron.nl/confluence/display/L2M/L2+STAT+Decision%3A+SC+-+SDP+OPC-UA+interface with dynamic
 --     behaviour recipe for record, freeze, dump
+-- [3] https://support.astron.nl/confluence/display/L2M/L5+SDPFW+Design+Document%3A+Ring
 --
 -- Usage:
 --   > as 12   # for detailed debugging
@@ -88,6 +89,8 @@ entity tb_lofar2_unb2c_sdp_station_tbuf_ring is
     g_tb_end                   : boolean := true;  -- when true then tb_end ends this simulation, else a higher
                                                    -- multi-testbench will end the simulation
     g_tb_index                 : natural := 0;
+    g_first_gn                 : natural := 1;  -- first global node (GN) in ring
+    g_nof_rn                   : natural := 2;  -- nof ring nodes (RN) in ring
     g_ddr_buffer_size          : natural := 256;  -- <= 4096, because c_tech_ddr4_sim_4k_64 has 4k = 4096 words of
                                                    -- c_sdp_tbuf_W_word = 512b
     g_rs_block_size            : natural := 100;  -- c_sdp_tbuf_rs_block_size = 2000, must be even see sdp_tbuf_output
@@ -106,14 +109,21 @@ end tb_lofar2_unb2c_sdp_station_tbuf_ring;
 
 architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is
   constant c_sim             : boolean := true;  -- use true for sim_ddr, use false to simulate IP and external DDR4
-  constant c_unb_nr          : natural := 1;
-  constant c_node_nr         : natural := 2;
+  constant c_first_unb_nr    : natural := g_first_gn / c_quad;  -- c_quad = 4 FPGAs per UniBoard2
+  constant c_first_node_nr   : natural := g_first_gn mod c_quad;  -- first node_nr in range(c_quad) = [0:3] on
+                                                                  -- c_first_unb_nr
+  constant c_last_rn         : natural := g_nof_rn - 1;  -- first RN has index 0 by definition.
+  constant c_last_gn         : natural := g_first_gn + c_last_rn;  -- last global node (GN) in ring
+  constant c_last_unb_nr     : natural := c_last_gn / c_quad;
+  constant c_last_node_nr    : natural := c_last_gn mod c_quad;
+  constant c_first_sp        : natural := g_first_gn * c_sdp_S_pn;
+  constant c_last_sp         : natural := c_first_sp + g_nof_rn * c_sdp_S_pn - 1;
+  constant c_mmf_prefix_last : string := mmf_unb2_file_prefix(g_tb_index, c_last_unb_nr, c_last_node_nr);
+
   constant c_tb_str          : string := "TB-" & int_to_str(g_tb_index) & ": ";
-  constant c_mmf_prefix      : string := mmf_unb2_file_prefix(g_tb_index, c_unb_nr, c_node_nr);
   constant c_Gbps            : real := 10.0**9;
 
   constant c_design_name     : string := "lofar2_unb2c_sdp_station_tbuf_ring";
-  constant c_nof_dump        : natural := 1;  -- number of dumps, > 1 to repeat same dump
 
   constant c_gn_index            : natural := c_unb_nr * 4 + c_node_nr;  -- this node GN
   constant c_ai_offset           : natural := c_gn_index * c_sdp_A_pn;
@@ -217,9 +227,6 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is
   constant c_packed_empty_w      : natural := 3;  -- = ceil_log2(c_longword_sz - 1)
   constant c_rx_fifo_size        : natural := g_rs_block_size;
 
-  -- DDR4
-  constant c_exp_ddr_ctlr_nof_bytes_per_word : natural := c_sdp_tbuf_W_word / c_byte_w;
-
   -- WG
   -- . Observe WG using rs_sosi.sop and rs_data_arr() in decimal format in Wave Window.
   constant c_bsn_start_wg        : natural := c_init_bsn + 2;  -- start WG at this BSN instead of some BSN, to avoid
@@ -228,22 +235,20 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is
   -- MM
   constant c_addr_w_reg_diag_wg           : natural := 2;
   constant c_mm_span_reg_diag_wg          : natural := 2**c_addr_w_reg_diag_wg;
-  constant c_addr_w_reg_dp_xonoff         : natural := 1;
-  constant c_mm_span_reg_dp_xonoff        : natural := 2**c_addr_w_reg_dp_xonoff;
-
-  constant c_mm_file_reg_bsn_source_v2    : string := c_mmf_prefix & "REG_BSN_SOURCE_V2";
-  constant c_mm_file_reg_bsn_scheduler_wg : string := c_mmf_prefix & "REG_BSN_SCHEDULER";
-  constant c_mm_file_reg_diag_wg          : string := c_mmf_prefix & "REG_WG";
-  constant c_mm_file_reg_sdp_info         : string := c_mmf_prefix & "REG_SDP_INFO";
-  constant c_mm_file_reg_io_ddr_mb_i      : string := c_mmf_prefix & "REG_IO_DDR_MB_I";
-  constant c_mm_file_reg_tbuf             : string := c_mmf_prefix & "REG_TBUF";
-  constant c_mm_file_reg_bsn_monitor_v2_tbuf     : string := c_mmf_prefix & "REG_BSN_MONITOR_V2_TBUF";
-  constant c_mm_file_reg_strobe_total_count_tbuf : string := c_mmf_prefix & "REG_STROBE_TOTAL_COUNT_TBUF";
-  constant c_mm_file_reg_hdr_dat          : string := c_mmf_prefix & "REG_HDR_DAT";  -- BF beamlets header
-  constant c_mm_file_reg_hdr_dat_tbuf     : string := c_mmf_prefix & "REG_HDR_DAT_TBUF";  -- TBuf dump header
-  constant c_mm_file_reg_dp_xonoff        : string := c_mmf_prefix & "REG_DP_XONOFF";  -- BF beamlet output enable
-  constant c_mm_file_reg_dp_xonoff_tbuf   : string := c_mmf_prefix & "REG_DP_XONOFF_TBUF";  -- TBuf dump output enable
-  constant c_mm_file_reg_nw_10gbe_mac     : string := c_mmf_prefix & "REG_NW_10GBE_MAC";
+
+  constant c_mm_file_reg_bsn_scheduler_wg : string := c_mmf_prefix_last & "REG_BSN_SCHEDULER";
+  constant c_mm_file_reg_hdr_dat          : string := c_mmf_prefix_last & "REG_HDR_DAT";  -- BF beamlets header
+  constant c_mm_file_reg_hdr_dat_tbuf     : string := c_mmf_prefix_last & "REG_HDR_DAT_TBUF";  -- TBuf dump header
+  constant c_mm_file_reg_tbuf             : string := c_mmf_prefix_last & "REG_TBUF";
+  constant c_mm_file_reg_dp_xonoff_tbuf   : string := c_mmf_prefix_last & "REG_DP_XONOFF_TBUF";  -- TBuf dump output
+                                                                                                 -- enable
+  -- Variable mmf_prefix dependent on gn, len('TB_0_UNB2_0_PN_0') = 16
+  function mmf_prefix(gn : natural) return string is
+    constant c_unb2 : natural := gn / c_quad;
+    constant c_pn   : natural := gn mod c_quad;
+  begin
+    return mmf_unb2_file_prefix(g_tb_index, c_unb2, c_pn);
+  end;
 
   signal wg_started           : std_logic := '0';
   signal rx_done              : std_logic := '0';
@@ -272,14 +277,6 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is
   signal rd_cep_udp_src_port : std_logic_vector(15 downto 0);
   signal rd_cep_udp_dst_port : std_logic_vector(15 downto 0);
 
-  signal ddr_status                  : std_logic_vector(31 downto 0);
-  signal ddr_wr_fifo_used            : natural;
-  signal ddr_rd_fifo_used            : natural;
-  signal ddr_wr_fifo_full            : std_logic;
-  signal ddr_rd_fifo_full            : std_logic;
-  signal ddr_dvr_done                : std_logic := '0';
-  signal ddr_ctlr_nof_bytes_per_word : natural;
-
   -- WG
   signal current_bsn_wg         : std_logic_vector(c_dp_stream_bsn_w - 1 downto 0);
 
@@ -292,7 +289,7 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is
   signal recording_nof_sop_per_sync : natural;
   signal dump_index                 : natural;
   signal time_index                 : natural;
-  signal read_busy                  : std_logic := '0';
+  signal read_busy_arr              : std_logic_vector(c_last_rn downto 0) := (others => '0');
   signal dump_rate_bps              : real := 0.0;
 
   signal dbg_c_exp_read_rate_bps         : real := c_exp_read_rate_bps;
@@ -331,7 +328,6 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is
 
   -- Dump packets data
   signal rx_dump_packet_cnt      : natural := 0;
-  signal rx_stats_etherstatspkts : natural;
   signal rx_fifo_siso            : t_dp_siso;
   signal rx_fifo_sosi            : t_dp_sosi;
   signal rx_ant_sosi             : t_dp_sosi := c_dp_sosi_rst;
@@ -360,7 +356,13 @@ architecture tb of tb_lofar2_unb2c_sdp_station_tbuf_ring is
   signal eth_rxp             : std_logic_vector(c_unb2c_board_nof_eth - 1 downto 0);
 
   signal SA_CLK              : std_logic := '1';
-  signal si_lpbk_0           : std_logic_vector(c_unb2c_board_tr_qsfp.bus_w - 1 downto 0);
+  signal i_QSFP_0_TX         : t_unb2c_board_qsfp_bus_2arr(c_last_rn downto 0) := (others => (others => '0'));
+  signal i_QSFP_0_RX         : t_unb2c_board_qsfp_bus_2arr(c_last_rn downto 0) := (others => (others => '0'));
+  signal i_RING_0_TX         : t_unb2c_board_qsfp_bus_2arr(c_last_rn downto 0) := (others => (others => '0'));
+  signal i_RING_0_RX         : t_unb2c_board_qsfp_bus_2arr(c_last_rn downto 0) := (others => (others => '0'));
+  signal i_RING_1_TX         : t_unb2c_board_qsfp_bus_2arr(c_last_rn downto 0) := (others => (others => '0'));
+  signal i_RING_1_RX         : t_unb2c_board_qsfp_bus_2arr(c_last_rn downto 0) := (others => (others => '0'));
+  signal i_QSFP_1_lpbk       : t_unb2c_board_qsfp_bus_2arr(c_last_rn downto 0) := (others => (others => '0'));
 
   -- back transceivers
   signal JESD204B_SERIAL_DATA : std_logic_vector(c_sdp_S_pn - 1 downto 0);
@@ -401,58 +403,82 @@ begin
   -- . Uses lofar2_unb2c_sdp_station instead of synthesis wrapper lofar2_unb2c_sdp_station_tbuf_ring, to be able to
   --   use the JESD204B signal names instead of the unb2c pin names and to have access to all generics.
   ------------------------------------------------------------------------------
-  u_lofar_unb2c_sdp_station_tbuf_ring : entity lofar2_unb2c_sdp_station_lib.lofar2_unb2c_sdp_station
-  generic map (
-    g_design_name          => c_design_name,
-    g_design_note          => "AIT + TBuf + Ring for dump from multiple nodes",
-    g_sim                  => c_sim,
-    g_sim_tb_index         => g_tb_index,
-    g_sim_unb_nr           => c_unb_nr,
-    g_sim_node_nr          => c_node_nr,
-    g_sim_sdp_tbuf         => c_sim_sdp_tbuf,
-    g_bsn_nof_clk_per_sync => c_bs_nof_clk_per_sync,
-    g_bs_block_size        => c_bs_block_size
-  )
-  port map (
-    -- GENERAL
-    CLK          => ext_clk,
-    PPS          => ext_pps,
-    WDI          => WDI,
-    INTA         => INTA,
-    INTB         => INTB,
-
-    -- Others
-    VERSION      => c_version,
-    ID           => c_id,
-    TESTIO       => open,
-
-    -- 1GbE Control Interface
-    ETH_CLK      => eth_clk,
-    ETH_SGIN     => eth_rxp,
-    ETH_SGOUT    => eth_txp,
-
-    -- Transceiver clocks
-    SA_CLK       => SA_CLK,
-
-    -- front transceivers
-    QSFP_1_RX    => si_lpbk_0,
-    QSFP_1_TX    => si_lpbk_0,
-
-    -- LEDs
-    QSFP_LED     => open,
-
-    -- 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,
-
-    -- DDR4 reference clock
-    MB_I_REF_CLK => MB_I_REF_CLK
-    -- DDR4 SO-DIMM Memory Bank I --> simulation use internal sim_ddr model in io_ddr
-  );
+  gen_dut : for RN in 0 to c_last_rn generate
+    u_lofar_unb2c_sdp_station_tbuf_ring : entity lofar2_unb2c_sdp_station_lib.lofar2_unb2c_sdp_station
+    generic map (
+      g_design_name          => c_design_name,
+      g_design_note          => "AIT + TBuf + Ring for dump from multiple nodes",
+      g_sim                  => c_sim,
+      g_sim_tb_index         => g_tb_index,
+      g_sim_unb_nr           => c_unb_nr,
+      g_sim_node_nr          => c_node_nr,
+      g_sim_sdp_tbuf         => c_sim_sdp_tbuf,
+      g_bsn_nof_clk_per_sync => c_bs_nof_clk_per_sync,
+      g_bs_block_size        => c_bs_block_size
+    )
+    port map (
+      -- GENERAL
+      CLK          => ext_clk,
+      PPS          => ext_pps,
+      WDI          => WDI,
+      INTA         => INTA,
+      INTB         => INTB,
+
+      -- Others
+      VERSION      => c_version,
+      ID           => (TO_UVEC((g_first_gn + RN) / c_quad, c_unb2c_board_nof_uniboard_w) &
+                       TO_UVEC((g_first_gn + RN) mod c_quad, c_unb2c_board_nof_chip_w)),
+      TESTIO       => open,
+
+      -- 1GbE Control Interface
+      ETH_CLK      => eth_clk,
+      ETH_SGIN     => eth_rxp,
+      ETH_SGOUT    => eth_txp,
+
+      -- Transceiver clocks
+      SA_CLK       => SA_CLK,
+
+      -- front transceivers for ring
+      QSFP_0_RX    => i_QSFP_0_RX(RN),
+      QSFP_0_TX    => i_QSFP_0_TX(RN),
+
+      -- ring transceivers
+      RING_0_RX    => i_RING_0_RX(RN),
+      RING_0_TX    => i_RING_0_TX(RN),
+      RING_1_RX    => i_RING_1_RX(RN),
+      RING_1_TX    => i_RING_1_TX(RN),
+
+      -- front transceivers for CEP
+      QSFP_1_RX    => i_QSFP_1_lpbk(RN),
+      QSFP_1_TX    => i_QSFP_1_lpbk(RN),
+
+      -- LEDs
+      QSFP_LED     => open,
+
+      -- 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,
+
+      -- DDR4 reference clock
+      MB_I_REF_CLK => MB_I_REF_CLK
+      -- DDR4 SO-DIMM Memory Bank I --> simulation use internal sim_ddr model in io_ddr
+    );
+  end generate;
+
+  -- Ring connections
+  gen_ring : for RN in 0 to c_last_rn - 1 generate
+    -- Connect consecutive nodes in ring via their PCB RING interfaces
+    i_RING_0_RX(RN + 1) <= i_RING_1_TX(RN);
+    i_RING_1_RX(RN)     <= i_RING_0_TX(RN + 1);
+  end generate;
+
+  -- Connect first and last nodes in ring via their cable QSFP interface.
+  i_QSFP_0_RX(0)         <= i_QSFP_0_TX(c_last_rn);
+  i_QSFP_0_RX(c_last_rn) <= i_QSFP_0_TX(0);
 
   ------------------------------------------------------------------------------
   -- CEP model
@@ -489,7 +515,7 @@ begin
     dp_rst              => dest_rst,
     dp_clk              => ext_clk,
 
-    serial_rx_arr(0)    => si_lpbk_0(0),
+    serial_rx_arr(0)    => i_QSFP_1_lpbk(c_last_rn)(0),  -- Last RN must be used as end node
 
     src_out_arr(0)      => tr_10GbE_src_out,
     src_in_arr(0)       => tr_10GbE_src_in
@@ -580,11 +606,10 @@ begin
   -- MM slave accesses via file IO
   ------------------------------------------------------------------------------
   p_mm_setup : process
+    variable v_gn            : natural;
     variable v_offset        : natural;
-    variable v_addr          : natural;
     variable v_norm_ampl     : real;
     variable v_bsn           : natural;
-    variable v_sp_power_sum  : real;
   begin
     -- Wait for DUT power up after reset
     wait for 200 ns;
@@ -604,15 +629,18 @@ begin
     --   0   block_period            : STD_LOGIC_VECTOR(15 DOWNTO 0);
     --     END RECORD;
     -- . Write
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  8, TO_UINT(c_exp_sdp_info.antenna_field_index), tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  7, TO_UINT(c_exp_sdp_info.station_id), tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  6, TO_UINT(slv(c_exp_sdp_info.antenna_band_index)), tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  5, TO_UINT(c_exp_sdp_info.observation_id), tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  4, TO_UINT(c_exp_sdp_info.nyquist_zone_index), tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_sdp_info,  1, TO_UINT(slv(c_exp_sdp_info.beam_repositioning_flag)), tb_clk);
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO",  8, TO_UINT(c_exp_sdp_info.antenna_field_index), tb_clk);
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO",  7, TO_UINT(c_exp_sdp_info.station_id), tb_clk);
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO",  6, TO_UINT(slv(c_exp_sdp_info.antenna_band_index)), tb_clk);
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO",  5, TO_UINT(c_exp_sdp_info.observation_id), tb_clk);
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO",  4, TO_UINT(c_exp_sdp_info.nyquist_zone_index), tb_clk);
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_SDP_INFO",  1, TO_UINT(slv(c_exp_sdp_info.beam_repositioning_flag)), tb_clk);
+    end loop;
 
     ----------------------------------------------------------------------------
-    -- Set TBuf dump output MAC,IP,UDP port
+    -- Set TBuf dump output MAC,IP,UDP port on last node
     ----------------------------------------------------------------------------
     -- TBuf dump header
     -- c_sdp_tbuf_hdr_field_arr : t_common_field_arr(c_sdp_tbuf_nof_hdr_fields - 1 downto 0) := (
@@ -714,39 +742,64 @@ begin
       report c_tb_str & "Wrong MM read rd_cep_udp_dst_port for dump"
       severity ERROR;
 
-    ----------------------------------------------------------------------------
-    -- Read DDR4 memory status
-    ----------------------------------------------------------------------------
-    mmf_mm_bus_rd(c_mm_file_reg_io_ddr_mb_i, 0, rd_data_setup, tb_clk);
-    ddr_status <= rd_data_setup;
-    proc_common_wait_some_cycles(tb_clk, 1);
-
-    -- . verify dvr_done for calibration ok
-    ddr_dvr_done <= ddr_status(0);
-    proc_common_wait_some_cycles(tb_clk, 1);
-    assert ddr_dvr_done = '1'
-      report c_tb_str & "Wrong no DDR MB_I"
-      severity ERROR;
-
-    -- . verify ddr_ctlr_nof_bytes_per_word
-    ddr_ctlr_nof_bytes_per_word <= TO_UINT(ddr_status(15 downto 8));
-    proc_common_wait_some_cycles(tb_clk, 1);
-    assert ddr_ctlr_nof_bytes_per_word = c_exp_ddr_ctlr_nof_bytes_per_word
-      report c_tb_str & "Wrong read ddr_ctlr_nof_bytes_per_word"
-      severity ERROR;
-
     ----------------------------------------------------------------------------
     -- Enable BS
     ----------------------------------------------------------------------------
-    mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 2, c_init_bsn, tb_clk);  -- Init BSN
-    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_bs_nof_clk_per_sync, tb_clk);
-    mmf_mm_bus_wr(c_mm_file_reg_bsn_source_v2, 0, 16#00000003#, tb_clk);  -- Enable BS at PPS
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_BSN_SOURCE_V2", 2, c_init_bsn, tb_clk);  -- Init BSN
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_BSN_SOURCE_V2", 3, 0, tb_clk);  -- Write high part activates the init BSN
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_BSN_SOURCE_V2", 1, c_bs_nof_clk_per_sync, tb_clk);
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_BSN_SOURCE_V2", 0, 16#00000003#, tb_clk);  -- Enable BS at PPS
+    end loop;
 
     -- Release PPS pulser, to get first PPS now and to start BSN source
     wait for 100 ns;
     pps_rst <= '0';
 
+    ----------------------------------------------------------------------------
+    -- Ring config
+    ----------------------------------------------------------------------------
+    -- Write ring configuration to all nodes.
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_INFO", 2, g_nof_rn, tb_clk);  -- N_rn
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_INFO", 3, g_first_gn, tb_clk);  -- O_rn
+    end loop;
+
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      if v_gn = g_first_gn then
+        -- Start node specific settings
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_INFO", 0, 1, tb_clk);  -- use_cable_to_previous_rn = 1
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_INFO", 1, 0, tb_clk);  -- use_cable_to_next_rn = 0
+      elsif v_gn = c_last_gn then
+        -- End node specific settings
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_INFO", 0, 0, tb_clk);  -- use_cable_to_previous_rn = 0
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_INFO", 1, 1, tb_clk);  -- use_cable_to_next_rn = 1
+      else
+        -- Use same settings for all nodes in between
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_INFO", 0, 0, tb_clk);  -- use_cable_to_previous_rn = 0
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_INFO", 1, 0, tb_clk);  -- use_cable_to_next_rn = 0
+      end if;
+    end loop;
+
+    -- Access scheme 2 = End cast for TBuf dump.
+    -- Use transport_nof_hops = 0 on last node to stop remote input for first node. Use transport_nof_hops = g_nof_rn
+    -- on all other nodes, so that they pass on their remote rx packets.
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      for I in 0 to c_nof_lanes - 1 loop
+        if RN = c_last_rn then
+          -- End RN, so set transport_nof_hops = 0.
+          mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_LANE_INFO_TBUF", I * 2 + 1, 0, tb_clk);
+        else
+          -- Set transport_nof_hops = g_nof_rn on all other nodes.
+          mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_RING_LANE_INFO_TBUF", I * 2 + 1, g_nof_rn, tb_clk);
+        end if;
+      end loop;
+    end loop;
+
     ----------------------------------------------------------------------------
     -- Enable WG
     ----------------------------------------------------------------------------
@@ -756,14 +809,17 @@ begin
     --   2 : freq[30:0]
     --   3 : ampl[16:0]
     -- Put DC signal on all SP
-    for S in 0 to c_sdp_S_pn - 1 loop
-      v_offset := S * c_mm_span_reg_diag_wg;
-      -- use WG ampl = sp index, phase = 90 and freq = 0 to have DC level = sp index
-      v_norm_ampl := real(S) / real(c_sdp_FS_adc);
-      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(90.0 * c_diag_wg_phase_unit), tb_clk);
-      mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 2, 0, tb_clk);
-      mmf_mm_bus_wr(c_mm_file_reg_diag_wg, v_offset + 3, integer(v_norm_ampl * c_diag_wg_ampl_unit), tb_clk);
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      for S in 0 to c_sdp_S_pn - 1 loop
+        v_offset := S * c_mm_span_reg_diag_wg;
+        -- use WG ampl = sp index, phase = 90 and freq = 0 to have DC level = sp index
+        v_norm_ampl := real(S) / real(c_sdp_FS_adc);
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_WG", v_offset + 0, 1024 * 2**16 + 1, tb_clk);  -- nof_samples, mode calc
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_WG", v_offset + 1, integer(90.0 * c_diag_wg_phase_unit), tb_clk);
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_WG", v_offset + 2, 0, tb_clk);
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_WG", v_offset + 3, integer(v_norm_ampl * c_diag_wg_ampl_unit), tb_clk);
+      end loop;
     end loop;
 
     -- Read current BSN
@@ -777,15 +833,19 @@ begin
       report c_tb_str & "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
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_BSN_SCHEDULER", 0, v_bsn, tb_clk);  -- first write low then high part
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_BSN_SCHEDULER", 1,     0, tb_clk);  -- assume v_bsn < 2**31-1
+    end loop;
 
     ----------------------------------------------------------------------------
     -- Wait until WG has started
     ----------------------------------------------------------------------------
+    -- read BSN low part, this is the wait until condition
     mmf_mm_wait_until_value(
-        c_mm_file_reg_bsn_scheduler_wg, 0,  -- read BSN low part
-        "UNSIGNED", rd_data_bsn, ">=", c_bsn_start_wg,  -- this is the wait until condition
+        c_mm_file_reg_bsn_scheduler_wg, 0,
+        "UNSIGNED", rd_data_bsn, ">=", c_bsn_start_wg,
         c_T_bs_period, ext_clk);
 
     -- WG started
@@ -805,6 +865,8 @@ begin
   end process;
 
   p_mm_tbuf_control : process
+    variable v_gn                 : natural;
+    variable v_rn_str             : string(1 to 6);
     variable v_bool               : boolean;
     variable v_offset             : natural;
     variable v_recorded_nof_pages : natural;
@@ -826,124 +888,59 @@ begin
 
     -- Wait for DUT power up after reset
     wait for 200 ns;
-    --v_bool := func_sdp_tbuf_print_state(c_tb_str, to_uvec(461603339, 32));
-    --v_bool := func_sdp_tbuf_print_state(c_tb_str, to_uvec(461602827, 32));
-    --v_bool := func_sdp_tbuf_print_state(c_tb_str, to_uvec(515, 32));
-    --v_bool := func_sdp_tbuf_print_state(c_tb_str, to_uvec(741, 32));
-    --v_bool := func_sdp_tbuf_print_state(c_tb_str, to_uvec(3, 32));
 
     ----------------------------------------------------------------------------
-    -- Record all antennas
-    ----------------------------------------------------------------------------
-    mmf_mm_bus_wr(c_mm_file_reg_tbuf, 2, to_int(tbuf_registers_wr.record_all), tb_clk);
-
-    ----------------------------------------------------------------------------
-    -- Enable packet dump output
+    -- Enable packet dump output only on last node
     ----------------------------------------------------------------------------
     mmf_mm_bus_wr(c_mm_file_reg_dp_xonoff_tbuf, 0, 1, tb_clk);
     mmf_mm_bus_wr(c_mm_file_reg_tbuf, 11, tbuf_registers_wr.dump_inter_packet_gap, tb_clk);
 
-    ----------------------------------------------------------------------------
-    -- Report and verify sizes
-    ----------------------------------------------------------------------------
-    mmf_mm_bus_rd(c_mm_file_reg_tbuf, 0, rd_data_control, tb_clk);
-    tbuf_registers_ro.nof_samples_per_block <= to_uint(rd_data_control);
-    mmf_mm_bus_rd(c_mm_file_reg_tbuf, 1, rd_data_control, tb_clk);
-    tbuf_registers_ro.nof_pages_in_buffer <= to_uint(rd_data_control);
-    proc_common_wait_some_cycles(tb_clk, 1);
-    assert tbuf_registers_ro.nof_samples_per_block = g_rs_block_size
-      report c_tb_str & "Wrong tbuf_registers_ro.nof_samples_per_block "
-      severity ERROR;
-    assert tbuf_registers_ro.nof_pages_in_buffer = c_nof_pages_in_buffer
-      report c_tb_str & "Wrong tbuf_registers_ro.nof_pages_in_buffer "
-      severity ERROR;
-    print_str(c_tb_str & "tbuf_registers_ro.nof_samples_per_block = " &
-                                                                   int_to_str(tbuf_registers_ro.nof_samples_per_block));
-    print_str(c_tb_str & "tbuf_registers_ro.nof_pages_in_buffer   = " &
-                                                                     int_to_str(tbuf_registers_ro.nof_pages_in_buffer));
-
     ----------------------------------------------------------------------------
     -- RECORD
     ----------------------------------------------------------------------------
     print_str(c_tb_str & "--------------------------------------------");
     print_str(c_tb_str & "-- RECORD");
     print_str(c_tb_str & "--------------------------------------------");
-    -- Enable recording
-    proc_common_wait_until_high(ext_clk, wg_started);
-    mmf_mm_bus_wr(c_mm_file_reg_tbuf, 3, to_int(tbuf_registers_wr.record_enable), tb_clk);
-    proc_common_wait_cross_clock_domain_latency(
-        c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency * 2);
-    -- Read back record_enable
-    mmf_mm_bus_rd(c_mm_file_reg_tbuf, 3, rd_data_control, tb_clk);
-    tbuf_registers_rd.record_enable <= rd_data_control(0);
-    -- Read record_busy, wait one rs_block for record_enable to take effect
-    proc_common_wait_some_cycles(ext_clk, g_rs_block_size);
-    mmf_mm_bus_rd(c_mm_file_reg_tbuf, 18, rd_data_record_busy, tb_clk);
-    tbuf_registers_ro.record_busy <= rd_data_record_busy(0);
-    proc_common_wait_some_cycles(tb_clk, 1);
-    assert tbuf_registers_rd.record_enable = '1'
-      report c_tb_str & "Wrong tbuf_registers_rd.record_enable /= '1'"
-      severity ERROR;
-    assert tbuf_registers_ro.record_busy = '1'
-      report c_tb_str & "Wrong tbuf_registers_ro.record_busy /= '1'"
-      severity ERROR;
-    print_str(c_tb_str & "tbuf_registers_rd.record_enable = " & sl_to_str(tbuf_registers_rd.record_enable));
-    print_str(c_tb_str & "tbuf_registers_ro.record_busy = " & sl_to_str(tbuf_registers_ro.record_busy));
 
-    -- Read TBuf state
-    mmf_mm_bus_rd(c_mm_file_reg_tbuf, 19, rd_data_state, tb_clk);
-    proc_common_wait_some_cycles(tb_clk, 1);
-    v_bool := func_sdp_tbuf_print_state(c_tb_str, rd_data_state);
+    -- Wait until there is WG data to record
+    proc_common_wait_until_high(ext_clk, wg_started);
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      -- Record all antennas on all nodes
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_TBUF", 2, to_int(tbuf_registers_wr.record_all), tb_clk);
+      -- Enable recording on all nodes
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_TBUF", 3, to_int(tbuf_registers_wr.record_enable), tb_clk);
+    end loop;
 
     -- Recording
     proc_common_wait_some_cycles(ext_clk, g_rs_block_size * g_rs_record_nof_block);
 
-    -- Read BSN monitor for recording data
-    mmf_mm_bus_rd(c_mm_file_reg_bsn_monitor_v2_tbuf, 1, rd_data_monitor, tb_clk);  -- bsn at sync
-    recording_rsn_at_sync <= to_uint(rd_data_monitor);
-    mmf_mm_bus_rd(c_mm_file_reg_bsn_monitor_v2_tbuf, 3, rd_data_monitor, tb_clk);  -- nof_sop
-    recording_nof_sop_per_sync <= to_uint(rd_data_monitor);
-    proc_common_wait_some_cycles(tb_clk, 1);
-    assert recording_nof_sop_per_sync = c_rs_nof_block_per_sync
-      report c_tb_str & "Wrong RSN monitor nof blocks per sync"
-      severity ERROR;
-    print_str(c_tb_str & "recording_rsn_at_sync = " & int_to_str(recording_rsn_at_sync));
-    print_str(c_tb_str & "recording_nof_sop_per_sync = " & int_to_str(recording_nof_sop_per_sync));
-
     ----------------------------------------------------------------------------
     -- FREEZE
     ----------------------------------------------------------------------------
     print_str(c_tb_str & "--------------------------------------------");
     print_str(c_tb_str & "-- FREEZE ");
     print_str(c_tb_str & "--------------------------------------------");
-    -- Disable recording
+
+    -- Disable recording on all nodes
     tbuf_registers_wr.record_enable <= '0';
     proc_common_wait_some_cycles(tb_clk, 1);
-    mmf_mm_bus_wr(c_mm_file_reg_tbuf, 3, to_int(tbuf_registers_wr.record_enable), tb_clk);
-    proc_common_wait_cross_clock_domain_latency(
-        c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency * 2);
-    -- Read disabled recording
-    mmf_mm_bus_rd(c_mm_file_reg_tbuf, 3, rd_data_control, tb_clk);
-    tbuf_registers_rd.record_enable <= rd_data_control(0);
-    proc_common_wait_some_cycles(tb_clk, 1);
-    assert tbuf_registers_rd.record_enable = '0'
-      report c_tb_str & "Wrong tbuf_registers_rd.record_enable /= '0'"
-      severity ERROR;
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_TBUF", 3, to_int(tbuf_registers_wr.record_enable), tb_clk);
+    end loop;
+
     -- Wait until recording has finished, read record_busy to account for latency in record_enable disabled
     mmf_mm_wait_until_value(
-        c_mm_file_reg_tbuf, 18,  -- read record_busy
+        c_mm_file_reg_tbuf, 18,  -- read record_busy on last node
         "UNSIGNED", rd_data_record_busy, "=", 0,  -- this is the wait until condition
         c_T_rd_interval, ext_clk);
-    tbuf_registers_ro.record_busy <= rd_data_record_busy(0);
-    proc_common_wait_some_cycles(tb_clk, 1);
-    print_str(c_tb_str & "tbuf_registers_rd.record_enable = " & sl_to_str(tbuf_registers_rd.record_enable));
-    print_str(c_tb_str & "tbuf_registers_ro.record_busy = " & sl_to_str(tbuf_registers_ro.record_busy));
 
-    -- Read number of recorded pages
+    -- Read number of recorded pages on last node
     mmf_mm_bus_rd(c_mm_file_reg_tbuf, 4, rd_data_control, tb_clk);
     tbuf_registers_ro.recorded_nof_pages <= to_uint(rd_data_control);
 
-    -- Read indices of first and last recorded page
+    -- Read indices of first and last recorded page on last node
     mmf_mm_bus_rd(c_mm_file_reg_tbuf, 5, rd_data_control, tb_clk);
     tbuf_registers_ro.recorded_first_page <= to_uint(rd_data_control);
     mmf_mm_bus_rd(c_mm_file_reg_tbuf, 6, rd_data_control, tb_clk);
@@ -962,7 +959,7 @@ begin
              "Wrong tbuf_registers_ro.recorded_nof_pages does not match recorded_first_page and recorded_last_page"
       severity ERROR;
 
-    -- Read timestamps of first and last recorded page
+    -- Read timestamps of first and last recorded page on last node
     mmf_mm_bus_rd(c_mm_file_reg_tbuf, 7, rd_data_control, tb_clk);  -- read low part
     tbuf_registers_ro.recorded_first_rsn(31 downto 0) <= rd_data_control;
     mmf_mm_bus_rd(c_mm_file_reg_tbuf, 8, rd_data_control, tb_clk);  -- read high part
@@ -1003,70 +1000,70 @@ begin
     ----------------------------------------------------------------------------
     -- DUMP
     ----------------------------------------------------------------------------
+    print_str(c_tb_str & "--------------------------------------------");
+    print_str(c_tb_str & "-- DUMP");
+    print_str(c_tb_str & "--------------------------------------------");
+
     -- Wait until nw_10GbE xon = '1'
     while NOW < 11 us loop
       wait for 100 ns;
     end loop;
 
-    for DUMP in 0 to c_nof_dump - 1 loop
-      tb_dump_cnt <= tb_dump_cnt + 1;
-      proc_common_wait_some_cycles(tb_clk, 1);
-      print_str(c_tb_str & "--------------------------------------------");
-      print_str(c_tb_str & "-- DUMP : " & int_to_str(tb_dump_cnt));
-      print_str(c_tb_str & "--------------------------------------------");
+    -- Clear dump strobe_total_counts
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      mmf_mm_bus_wr(mmf_prefix(v_gn) &
+                    "REG_STROBE_TOTAL_COUNT_TBUF", c_sdp_tbuf_nof_strobe_total_counts_clear_id, 1, tb_clk);
+    end loop;
+    proc_common_wait_cross_clock_domain_latency(
+        c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency * 2);
 
-      -- Clear dump strobe_total_counts
-      mmf_mm_bus_wr(c_mm_file_reg_strobe_total_count_tbuf, c_sdp_tbuf_nof_strobe_total_counts_clear_id, 1, tb_clk);
-      proc_common_wait_cross_clock_domain_latency(
-          c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency * 2);
+    -- Set dump interval
+    v_dump_start_page := tbuf_registers_ro.recorded_first_page + g_dump_page_offset;
+    if v_dump_start_page >= c_nof_pages_in_buffer then
+      -- Wrap from begin of buffer when v_dump_start_page is just beyond the end of buffer. Do not use modulo
+      -- c_nof_pages_in_buffer to be able to simulate effect of a much too large v_dump_start_page due to
+      -- g_dump_page_offset >= c_nof_pages_in_buffer
+      v_dump_start_page := v_dump_start_page - c_nof_pages_in_buffer;
+    end if;
+    tbuf_registers_wr.dump_start_page <= v_dump_start_page;
+    v_dump_start_rsn := incr_uvec(tbuf_registers_ro.recorded_first_rsn, g_dump_page_offset * g_rs_block_size);
+    tbuf_registers_wr.dump_start_rsn <= v_dump_start_rsn;
+    tbuf_registers_wr.dump_enables <= g_dump_enables;
+    proc_common_wait_some_cycles(tb_clk, 1);
 
-      -- Set dump interval and antenna inputs
-      v_dump_start_page := tbuf_registers_ro.recorded_first_page + g_dump_page_offset;
-      if v_dump_start_page >= c_nof_pages_in_buffer then
-        -- Wrap from begin of buffer when v_dump_start_page is just beyond the end of buffer. Do not use modulo
-        -- c_nof_pages_in_buffer to be able to simulate effect of a much too large v_dump_start_page due to
-        -- g_dump_page_offset >= c_nof_pages_in_buffer
-        v_dump_start_page := v_dump_start_page - c_nof_pages_in_buffer;
-      end if;
-      tbuf_registers_wr.dump_start_page <= v_dump_start_page;
-      v_dump_start_rsn := incr_uvec(tbuf_registers_ro.recorded_first_rsn, g_dump_page_offset * g_rs_block_size);
-      tbuf_registers_wr.dump_start_rsn <= v_dump_start_rsn;
-      tbuf_registers_wr.dump_enables <= g_dump_enables;
-      proc_common_wait_some_cycles(tb_clk, 1);
-      mmf_mm_bus_wr(c_mm_file_reg_tbuf, 12, tbuf_registers_wr.dump_start_page, tb_clk);
-      mmf_mm_bus_wr(c_mm_file_reg_tbuf, 13, tbuf_registers_wr.dump_nof_pages, tb_clk);
-      mmf_mm_bus_wr(c_mm_file_reg_tbuf, 14, to_uint(tbuf_registers_wr.dump_start_rsn), tb_clk);
-      mmf_mm_bus_wr(c_mm_file_reg_tbuf, 16, to_uint(tbuf_registers_wr.dump_enables), tb_clk);
-      proc_common_wait_cross_clock_domain_latency(
-          c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency * 2);
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_TBUF", 12, tbuf_registers_wr.dump_start_page, tb_clk);
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_TBUF", 13, tbuf_registers_wr.dump_nof_pages, tb_clk);
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_TBUF", 14, to_uint(tbuf_registers_wr.dump_start_rsn), tb_clk);
+    end loop;
+    proc_common_wait_cross_clock_domain_latency(
+        c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency * 2);
+
+    -- Enable dump for antenna inputs
+    if g_dump_nof_pages > 0 then
+      for RN in 0 to c_last_rn loop
+        v_gn := g_first_gn + RN;
+        mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_TBUF", 16, to_uint(tbuf_registers_wr.dump_enables), tb_clk);
 
-      if g_dump_nof_pages > 0 then
         -- Time dump begin
-        read_busy <= '1';
+        read_busy_arr(RN) <= '1';
         v_Begin := NOW / c_1ns;
         proc_common_wait_some_cycles(tb_clk, 1);
 
-        -- Read back enabled dump
-        mmf_mm_bus_rd(c_mm_file_reg_tbuf, 16, rd_data_control, tb_clk);
-        tbuf_registers_rd.dump_enables <= rd_data_control(c_sdp_A_pn - 1 downto 0);
-        proc_common_wait_some_cycles(tb_clk, 1);
-        assert to_uint(tbuf_registers_rd.dump_enables) = to_uint(tbuf_registers_wr.dump_enables)
-          report c_tb_str & "Wrong tbuf_registers_rd.dump_enables enabled"
-          severity ERROR;
-        print_str(c_tb_str & "tbuf_registers_rd.dump_enables = " & slv_to_str(tbuf_registers_rd.dump_enables));
-
         ----------------------------------------------------------------------------
         -- Wait until dump is done
         ----------------------------------------------------------------------------
         mmf_mm_wait_until_value(
-            c_mm_file_reg_tbuf, 17,  -- read dump_done
+            mmf_prefix(v_gn) & "REG_TBUF", 17,  -- read dump_done for this RN
             "UNSIGNED", rd_data_dump_done, "=", 1,  -- this is the wait until condition
             c_T_rd_interval, ext_clk);
         tbuf_registers_ro.dump_done <= rd_data_dump_done(0);
         proc_common_wait_some_cycles(tb_clk, 1);
 
         -- Time dump end
-        read_busy <= '0';
+        read_busy_arr(RN) <= '0';
         v_End := NOW / c_1ns;
         v_Period := real(v_End - v_Begin) * 1.0e-9;  -- dump time in s
         v_dump_rate_bps := real(c_dump_total_nof_packets * c_sdp_W_ant * g_rs_block_size) / v_Period;
@@ -1081,100 +1078,91 @@ begin
         end if;
         print_str(c_tb_str & "Dump rate = " & real_to_str(v_dump_rate_bps / c_Gbps, 4, 2) & " Gbps" &
                   " (Expected " & real_to_str(c_exp_dump_rate_bps / c_Gbps, 4, 2) & " Gbps)");
-      end if;
+      end loop;
+    end if;
 
-      -- Wait some time for latency in sdp_tbuf_output and 10GbE Tx - Rx network
-      proc_common_wait_some_cycles(ext_clk, g_rs_block_size * 4);
-      rx_done <= '1';
+    -- Wait some time for latency in sdp_tbuf_output and 10GbE Tx - Rx network
+    proc_common_wait_some_cycles(ext_clk, g_rs_block_size * 4);
+    rx_done <= '1';
 
+    for RN in 0 to c_last_rn loop
+      v_gn := g_first_gn + RN;
+      v_rn_str := "RN-" & int_to_str(RN) & ": ";
       -- Read strobe_total_counts
-      mmf_mm_bus_rd(c_mm_file_reg_strobe_total_count_tbuf, 0, rd_data_strobe, tb_clk);
+      mmf_mm_bus_rd(mmf_prefix(v_gn) & "REG_STROBE_TOTAL_COUNT_TBUF", 0, rd_data_strobe, tb_clk);
       tbuf_strobe_total_counts.memory_read_nof_packets <= to_uint(rd_data_strobe);
-      mmf_mm_bus_rd(c_mm_file_reg_strobe_total_count_tbuf, 2, rd_data_strobe, tb_clk);
+      mmf_mm_bus_rd(mmf_prefix(v_gn) & "REG_STROBE_TOTAL_COUNT_TBUF", 2, rd_data_strobe, tb_clk);
       tbuf_strobe_total_counts.memory_read_nof_crc_errors <= to_uint(rd_data_strobe);
-      mmf_mm_bus_rd(c_mm_file_reg_strobe_total_count_tbuf, 4, rd_data_strobe, tb_clk);
+      mmf_mm_bus_rd(mmf_prefix(v_gn) & "REG_STROBE_TOTAL_COUNT_TBUF", 4, rd_data_strobe, tb_clk);
       tbuf_strobe_total_counts.memory_read_nof_rsn_errors <= to_uint(rd_data_strobe);
-      mmf_mm_bus_rd(c_mm_file_reg_strobe_total_count_tbuf, 6, rd_data_strobe, tb_clk);
+      mmf_mm_bus_rd(mmf_prefix(v_gn) & "REG_STROBE_TOTAL_COUNT_TBUF", 6, rd_data_strobe, tb_clk);
       tbuf_strobe_total_counts.memory_read_dumped_nof_packets <= to_uint(rd_data_strobe);
-      mmf_mm_bus_rd(c_mm_file_reg_strobe_total_count_tbuf, 8, rd_data_strobe, tb_clk);
+      mmf_mm_bus_rd(mmf_prefix(v_gn) & "REG_STROBE_TOTAL_COUNT_TBUF", 8, rd_data_strobe, tb_clk);
       tbuf_strobe_total_counts.memory_ring_rx_nof_packets <= to_uint(rd_data_strobe);
-      mmf_mm_bus_rd(c_mm_file_reg_strobe_total_count_tbuf, 10, rd_data_strobe, tb_clk);
+      mmf_mm_bus_rd(mmf_prefix(v_gn) & "REG_STROBE_TOTAL_COUNT_TBUF", 10, rd_data_strobe, tb_clk);
       tbuf_strobe_total_counts.memory_ring_tx_nof_packets <= to_uint(rd_data_strobe);
-      mmf_mm_bus_rd(c_mm_file_reg_strobe_total_count_tbuf, 12, rd_data_strobe, tb_clk);
+      mmf_mm_bus_rd(mmf_prefix(v_gn) & "REG_STROBE_TOTAL_COUNT_TBUF", 12, rd_data_strobe, tb_clk);
       tbuf_strobe_total_counts.memory_output_nof_packets <= to_uint(rd_data_strobe);
       proc_common_wait_some_cycles(tb_clk, 1);
       assert tbuf_strobe_total_counts.memory_read_nof_packets = c_read_total_nof_packets
-        report c_tb_str & "Wrong tbuf_strobe_total_counts.memory_read_nof_packets"
+        report c_tb_str & v_rn_str & "Wrong tbuf_strobe_total_counts.memory_read_nof_packets"
         severity ERROR;
       assert tbuf_strobe_total_counts.memory_read_nof_crc_errors = c_read_nof_crc_errors
-        report c_tb_str & "Wrong tbuf_strobe_total_counts.memory_read_nof_crc_errors"
+        report c_tb_str & v_rn_str & "Wrong tbuf_strobe_total_counts.memory_read_nof_crc_errors"
         severity ERROR;
       assert tbuf_strobe_total_counts.memory_read_nof_rsn_errors = c_read_nof_rsn_errors
-        report c_tb_str & "Wrong tbuf_strobe_total_counts.memory_read_nof_rsn_errors"
+        report c_tb_str & v_rn_str & "Wrong tbuf_strobe_total_counts.memory_read_nof_rsn_errors"
         severity ERROR;
       assert tbuf_strobe_total_counts.memory_read_dumped_nof_packets = c_dump_total_nof_packets
-        report c_tb_str & "Wrong tbuf_strobe_total_counts.memory_read_dumped_nof_packets"
+        report c_tb_str & v_rn_str & "Wrong tbuf_strobe_total_counts.memory_read_dumped_nof_packets"
         severity ERROR;
       assert tbuf_strobe_total_counts.memory_ring_rx_nof_packets = 0
-        report c_tb_str & "Wrong tbuf_strobe_total_counts.memory_ring_rx_nof_packets"
+        report c_tb_str & v_rn_str & "Wrong tbuf_strobe_total_counts.memory_ring_rx_nof_packets"
         severity ERROR;
       assert tbuf_strobe_total_counts.memory_ring_tx_nof_packets = c_dump_total_nof_packets
-        report c_tb_str & "Wrong tbuf_strobe_total_counts.memory_ring_tx_nof_packets"
+        report c_tb_str & v_rn_str & "Wrong tbuf_strobe_total_counts.memory_ring_tx_nof_packets"
         severity ERROR;
       assert tbuf_strobe_total_counts.memory_output_nof_packets = c_dump_total_nof_packets
-        report c_tb_str & "Wrong tbuf_strobe_total_counts.memory_output_nof_packets"
+        report c_tb_str & v_rn_str & "Wrong tbuf_strobe_total_counts.memory_output_nof_packets"
         severity ERROR;
-      print_str(c_tb_str & "tbuf_strobe_total_counts.memory_read_nof_packets = " &
+      print_str(c_tb_str & v_rn_str & "tbuf_strobe_total_counts.memory_read_nof_packets = " &
                                                             int_to_str(tbuf_strobe_total_counts.memory_read_nof_packets));
-      print_str(c_tb_str & "tbuf_strobe_total_counts.memory_read_nof_crc_errors = " &
+      print_str(c_tb_str & v_rn_str & "tbuf_strobe_total_counts.memory_read_nof_crc_errors = " &
                                                          int_to_str(tbuf_strobe_total_counts.memory_read_nof_crc_errors));
-      print_str(c_tb_str & "tbuf_strobe_total_counts.memory_read_nof_rsn_errors = " &
+      print_str(c_tb_str & v_rn_str & "tbuf_strobe_total_counts.memory_read_nof_rsn_errors = " &
                                                          int_to_str(tbuf_strobe_total_counts.memory_read_nof_rsn_errors));
-      print_str(c_tb_str & "tbuf_strobe_total_counts.memory_read_dumped_nof_packets = " &
+      print_str(c_tb_str & v_rn_str & "tbuf_strobe_total_counts.memory_read_dumped_nof_packets = " &
                                                      int_to_str(tbuf_strobe_total_counts.memory_read_dumped_nof_packets));
-      print_str(c_tb_str & "tbuf_strobe_total_counts.memory_ring_rx_nof_packets = " &
+      print_str(c_tb_str & v_rn_str & "tbuf_strobe_total_counts.memory_ring_rx_nof_packets = " &
                                                          int_to_str(tbuf_strobe_total_counts.memory_ring_rx_nof_packets));
-      print_str(c_tb_str & "tbuf_strobe_total_counts.memory_ring_tx_nof_packets = " &
+      print_str(c_tb_str & v_rn_str & "tbuf_strobe_total_counts.memory_ring_tx_nof_packets = " &
                                                          int_to_str(tbuf_strobe_total_counts.memory_ring_tx_nof_packets));
-      print_str(c_tb_str & "tbuf_strobe_total_counts.memory_output_nof_packets = " &
+      print_str(c_tb_str & v_rn_str & "tbuf_strobe_total_counts.memory_output_nof_packets = " &
                                                           int_to_str(tbuf_strobe_total_counts.memory_output_nof_packets));
 
-      -- Read REG_NW_10GBE_MAC counts
-      -- . In sim via si_lpbk_0 loopback on own port, on HW using another node on unb2c as dump destination
-      -- . Only need to read low word part of rx_stats_etherstatspkts[35:0]
-      -- . Expect at least tbuf_strobe_total_counts.memory_output_nof_packets, there can be more when the nw_10gbe
-      --   does an ARP.
-      mmf_mm_bus_rd(c_mm_file_reg_nw_10gbe_mac, 16#C1C#, rd_data_nw_10gbe_mac, tb_clk);
-      rx_stats_etherstatspkts <= TO_UINT(rd_data_nw_10gbe_mac);
-      proc_common_wait_some_cycles(tb_clk, 1);
-      assert rx_stats_etherstatspkts >= tbuf_strobe_total_counts.memory_output_nof_packets
-        report c_tb_str & "Wrong rx_stats_etherstatspkts"
-        severity ERROR;
-      print_str(c_tb_str & "rx_stats_etherstatspkts = " & int_to_str(rx_stats_etherstatspkts));
-
       -- Disable dump
       proc_common_wait_some_cycles(ext_clk, 100);  -- delay for ease of view in Wave window
       tbuf_registers_wr.dump_enables <= (others => '0');
       proc_common_wait_some_cycles(tb_clk, 1);
-      mmf_mm_bus_wr(c_mm_file_reg_tbuf, 16, to_uint(tbuf_registers_wr.dump_enables), tb_clk);
+      mmf_mm_bus_wr(mmf_prefix(v_gn) & "REG_TBUF", 16, to_uint(tbuf_registers_wr.dump_enables), tb_clk);
       proc_common_wait_cross_clock_domain_latency(
           c_mm_clk_period, c_ext_clk_period, c_common_cross_clock_domain_latency * 2);
       -- Read back disabled dump
-      mmf_mm_bus_rd(c_mm_file_reg_tbuf, 16, rd_data_control, tb_clk);
+      mmf_mm_bus_rd(mmf_prefix(v_gn) & "REG_TBUF", 16, rd_data_control, tb_clk);
       tbuf_registers_rd.dump_enables <= rd_data_control(c_sdp_A_pn - 1 downto 0);
       proc_common_wait_some_cycles(tb_clk, 1);
       assert to_uint(tbuf_registers_rd.dump_enables) = to_uint(tbuf_registers_wr.dump_enables)
-        report c_tb_str & "Wrong tbuf_registers_rd.dump_enables disabled"
+        report c_tb_str & v_rn_str & "Wrong tbuf_registers_rd.dump_enables disabled"
         severity ERROR;
       -- Read dump_done to check that it is '0'
-      mmf_mm_bus_rd(c_mm_file_reg_tbuf, 17, rd_data_dump_done, tb_clk);
+      mmf_mm_bus_rd(mmf_prefix(v_gn) & "REG_TBUF", 17, rd_data_dump_done, tb_clk);
       tbuf_registers_ro.dump_done <= rd_data_dump_done(0);
       proc_common_wait_some_cycles(tb_clk, 1);
       assert tbuf_registers_ro.dump_done = '0'
-        report c_tb_str & "Wrong tbuf_registers_ro.dump_done"
+        report c_tb_str & v_rn_str & "Wrong tbuf_registers_ro.dump_done"
         severity ERROR;
-      print_str(c_tb_str & "tbuf_registers_rd.dump_enables = " & slv_to_str(tbuf_registers_rd.dump_enables));
-      print_str(c_tb_str & "tbuf_registers_ro.dump_done = " & sl_to_str(tbuf_registers_ro.dump_done));
+      print_str(c_tb_str & v_rn_str & "tbuf_registers_rd.dump_enables = " & slv_to_str(tbuf_registers_rd.dump_enables));
+      print_str(c_tb_str & v_rn_str & "tbuf_registers_ro.dump_done = " & sl_to_str(tbuf_registers_ro.dump_done));
     end loop;
 
     ---------------------------------------------------------------------------