diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
index 296596eefcc58431cbbdee29cb196ebccc399782..ea3e9fd77656f795abf4c3d42bca1121b0eee892 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_pkg.vhd
@@ -505,10 +505,14 @@ PACKAGE sdp_pkg is
 
   FUNCTION func_sdp_get_stat_marker(g_statistics_type : STRING) RETURN NATURAL;
   FUNCTION func_sdp_get_stat_nof_signal_inputs(g_statistics_type : STRING) RETURN NATURAL;
+
+  -- nof_statistics_per_packet = mm_nof_data * mm_data_size / c_sdp_W_statistic_sz
+  FUNCTION func_sdp_get_stat_from_mm_user_size(g_statistics_type : STRING) RETURN NATURAL;
   FUNCTION func_sdp_get_stat_from_mm_data_size(g_statistics_type : STRING) RETURN NATURAL;
   FUNCTION func_sdp_get_stat_from_mm_step_size(g_statistics_type : STRING) RETURN NATURAL;
   FUNCTION func_sdp_get_stat_from_mm_nof_data(g_statistics_type : STRING) RETURN NATURAL;
   FUNCTION func_sdp_get_stat_nof_statistics_per_packet(g_statistics_type : STRING) RETURN NATURAL;
+
   FUNCTION func_sdp_get_stat_app_total_length(g_statistics_type : STRING) RETURN NATURAL;
   FUNCTION func_sdp_get_stat_udp_total_length(g_statistics_type : STRING) RETURN NATURAL;
   FUNCTION func_sdp_get_stat_ip_total_length(g_statistics_type : STRING) RETURN NATURAL;
@@ -575,11 +579,19 @@ PACKAGE BODY sdp_pkg IS
                                             1));  -- SST
   END func_sdp_get_stat_nof_signal_inputs;
 
-  FUNCTION func_sdp_get_stat_from_mm_data_size(g_statistics_type : STRING) RETURN NATURAL IS
+  FUNCTION func_sdp_get_stat_from_mm_user_size(g_statistics_type : STRING) RETURN NATURAL IS
+  -- see sdp_statistics_offload.vhd for description
   BEGIN
-    RETURN sel_a_b(g_statistics_type="BST", c_sdp_N_pol_bf * c_sdp_W_statistic_sz,  -- = 4
+    RETURN sel_a_b(g_statistics_type="BST",                 c_sdp_W_statistic_sz,   -- = 2
            sel_a_b(g_statistics_type="XST", c_nof_complex * c_sdp_W_statistic_sz,   -- = 4
-                                            c_sdp_W_statistic_sz));                 -- = 2, SST
+                                                            c_sdp_W_statistic_sz)); -- = 2, SST
+  END func_sdp_get_stat_from_mm_user_size;
+
+  FUNCTION func_sdp_get_stat_from_mm_data_size(g_statistics_type : STRING) RETURN NATURAL IS
+  BEGIN
+    RETURN sel_a_b(g_statistics_type="BST", c_sdp_N_pol_bf * c_sdp_W_statistic_sz,   -- = 4
+           sel_a_b(g_statistics_type="XST", c_nof_complex  * c_sdp_W_statistic_sz,   -- = 4
+                                                             c_sdp_W_statistic_sz)); -- = 2, SST
   END func_sdp_get_stat_from_mm_data_size;
 
   FUNCTION func_sdp_get_stat_from_mm_step_size(g_statistics_type : STRING) RETURN NATURAL IS
@@ -587,7 +599,7 @@ PACKAGE BODY sdp_pkg IS
   BEGIN
     RETURN sel_a_b(g_statistics_type="BST", c_data_size,                  -- = 4
            sel_a_b(g_statistics_type="XST", c_data_size,                  -- = 4
-                                            c_sdp_Q_fft * c_data_size));  -- = 4, SST
+                                            c_data_size * c_sdp_Q_fft));  -- = 4, SST
   END func_sdp_get_stat_from_mm_step_size;
 
   FUNCTION func_sdp_get_stat_from_mm_nof_data(g_statistics_type : STRING) RETURN NATURAL IS
@@ -597,6 +609,7 @@ PACKAGE BODY sdp_pkg IS
                                             c_sdp_N_sub));   -- = 512, SST
   END func_sdp_get_stat_from_mm_nof_data;
 
+  -- nof_statistics_per_packet = mm_nof_data * mm_data_size / c_sdp_W_statistic_sz
   FUNCTION func_sdp_get_stat_nof_statistics_per_packet(g_statistics_type : STRING) RETURN NATURAL IS
   BEGIN
     RETURN sel_a_b(g_statistics_type="BST", c_sdp_S_sub_bf * c_sdp_N_pol_bf,  -- = 976
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
index 56f91879bf03794f81ad23870ae24cf2e45d1b9b..c9269c6a02c302a9c92429b699d9585ad2c617eb 100644
--- a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
@@ -30,6 +30,61 @@
 -- https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD
 -- . See 2.9.4 Station Control (L3-SC) - SDP Firmware (L4-SDPFW)
 --
+-- . endianess
+--   Within a 32bit MM word the values are stored with LSByte at lowest byte
+--   address (so relative byte address 0) and MSByte at highest byte address
+--   (so relative byte address 3). Internally in the RAM the MM words are thus
+--   stored with LSByte first, which is called little endian. However,
+--   externally the MM words are send with MSByte first, so in the statistics
+--   offload header and offload payload the 32bit words are send with MSByte
+--   first, which is called big endian.
+--   The dp_offload_tx_v3 sends all multi byte header fields in big endian
+--   order, hence also the 16bit, 24bit and 64bit values are send MSByte
+--   first. The internet packet headers also use big endian, which is
+--   therefore also called network order. Hence the entire statistics offload
+--   packet is in big endian order.
+--   If values are shown with first byte received left and last byte received
+--   right, then big endian hex values can directly be interpreted when read
+--   by a human, because they are shown in the normal order.
+--
+-- . g_reverse_word_order
+--   The statistics consist of c_sdp_W_statistic_sz = 2 MM words that are
+--   with LSWord at low (even) word address and MSWord at high (odd) word
+--   address. Default the statistics offload reads the low address first, but
+--   the statistics have to be send with MSWord first. Therefore the read
+--   order needs to be reversed per statistic value, so g_reverse_word_order
+--   = TRUE. The combination of sending the MSWord first and the MSByte first
+--   results that the entire 64b statistics words are send in big endian
+--   order.
+--
+--   Stored order:
+--   word address:   0,   1,   2,   3
+--   SST            Ul,  Uh
+--   BST            Xl,  Xh,  Yl,  Yh
+--   XST            Rl,  Rh,  Il,  Ih
+--
+--   The g_reverse_word_order = TRUE is needed to achieve have MSWord first
+--   and 64bit big endian.
+--   The g_user_size defines the number of words that get reversed:
+--   . For the SST there is only one uint64 part, so g_user_size = 2.
+--   . For the BST the X and Y polarization parts are treated as and array of
+--     [N_pol_bf], so index 0 = X is send first and therefore g_user_size = 2
+--     to preserve the polarization order.
+--   . For the XST the Re and Im complex parts are treated as a cint64, so
+--     the imaginary part is send first and therefore g_user_size = 4 to also
+--     reverse the Re an Im parts. This is similar as with cint16 values that
+--     are packed as Im << 16 + Re in a 32bit word. However it differs from
+--     two diminensional arrays of [N_complex], because for arrays index 0
+--     is send first and index 0 corresponds to Re.
+--
+--   The () show the parts that are contained in g_user_size and that got
+--   reversed by g_reverse_word_order = TRUE compared to the stored order:
+--
+--   Transport order:                   (g_user_size)
+--   SST           (Uh,  Ul),                2
+--   BST           (Xh,  Xl), (Yh,  Yl),     2   keep parts order
+--   XST           (Ih,  Il,   Rh,  Rl),     4   also reverse parts order
+--
 -------------------------------------------------------------------------------
 
 LIBRARY IEEE, common_lib, mm_lib, dp_lib, ring_lib;
@@ -48,7 +103,8 @@ ENTITY sdp_statistics_offload IS
     g_offload_time        : NATURAL := c_sdp_offload_time;
     g_beamset_id          : NATURAL := 0;
     g_P_sq                : NATURAL := c_sdp_P_sq;  -- use generic to support P_sq = 1 for one node and P_sq = c_sdp_P_sq for multiple nodes (with ring)
-    g_crosslets_direction : NATURAL := 1            -- > 0 for crosslet transport in positive direction (incrementing RN), else 0 for negative direction
+    g_crosslets_direction : NATURAL := 1;           -- > 0 for crosslet transport in positive direction (incrementing RN), else 0 for negative direction
+    g_reverse_word_order  : BOOLEAN := TRUE  -- default word order is MSB after LSB, we need to stream LSB after MSB.
   );
   PORT (
     -- Clocks and reset
@@ -105,6 +161,7 @@ ARCHITECTURE str OF sdp_statistics_offload IS
   CONSTANT c_beamlet_id                : NATURAL := g_beamset_id * c_sdp_S_sub_bf;
 
   -- MM access settings per packet for u_dp_block_from_mm_dc
+  CONSTANT c_mm_user_size              : NATURAL := func_sdp_get_stat_from_mm_user_size(g_statistics_type);
   CONSTANT c_mm_data_size              : NATURAL := func_sdp_get_stat_from_mm_data_size(g_statistics_type);
   CONSTANT c_mm_step_size              : NATURAL := func_sdp_get_stat_from_mm_step_size(g_statistics_type);
   CONSTANT c_mm_nof_data               : NATURAL := func_sdp_get_stat_from_mm_nof_data(g_statistics_type);
@@ -385,10 +442,12 @@ BEGIN
   
   u_dp_block_from_mm_dc : ENTITY dp_lib.dp_block_from_mm_dc
   GENERIC MAP (
+    g_user_size          => c_mm_user_size,
     g_data_size          => c_mm_data_size,
     g_step_size          => c_mm_step_size,
     g_nof_data           => c_mm_nof_data,
-    g_reverse_word_order => TRUE -- default word order is MSB after LSB, we need to stream LSB after MSB.
+    g_word_w             => c_word_w,
+    g_reverse_word_order => g_reverse_word_order
   ) 
   PORT MAP(
     dp_rst        => dp_rst,
diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
index 33b59b65c850bef7be1f1f6503e2b333b343bac1..327fa6ce994c3b69172e97f24371010e1e5022fc 100644
--- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
@@ -32,7 +32,8 @@
 -- Usage:
 -- > as 8
 -- > run -a
--- e.g. view test_offload_sosi and the rx_sdp_stat_header.app fields
+-- . for header: view test_offload_sosi and the rx_sdp_stat_header.app fields
+-- . for payload: view rx_val, rx_data and exp_data
 -------------------------------------------------------------------------------
 
 LIBRARY IEEE, common_lib, dp_lib, ring_lib;
@@ -55,14 +56,15 @@ ENTITY tb_sdp_statistics_offload IS
     -- All
     g_statistics_type          : STRING := "SST";
     g_offload_time             : NATURAL := 50;
+    g_reverse_word_order       : BOOLEAN := TRUE;  -- when TRUE then stream LSB word after MSB word.
     g_gn_index                 : NATURAL := 5;  -- global node (GN) index, must be in range(O_rn, O_rn + N_rn), use > 0 to see effect of g_offload_time
     -- BST
     g_beamset_id               : NATURAL := 1;  -- < c_sdp_N_beamsets
     -- XST
     g_O_rn                     : NATURAL := 4;  -- GN index of first ring node (RN)
     g_N_rn                     : NATURAL := 8;  -- <= c_sdp_N_rn_max = 16, number of nodes in ring
-    g_P_sq                     : NATURAL := 1;  -- <= c_sdp_P_sq
-    g_nof_crosslets            : NATURAL := 1;  -- <= c_sdp_N_crosslets_max
+    g_P_sq                     : NATURAL := 4;  -- <= c_sdp_P_sq
+    g_nof_crosslets            : NATURAL := 3;  -- <= c_sdp_N_crosslets_max
     g_crosslets_direction      : NATURAL := 1   -- > 0 for crosslet transport in positive direction (incrementing RN), else 0 for negative direction
   );
 END tb_sdp_statistics_offload;
@@ -97,23 +99,37 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
   CONSTANT c_crosslets_info_rec        : t_sdp_crosslets_info := (offset_arr => (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15), step => 16);
   CONSTANT c_crosslets_info_slv        : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := func_sdp_map_crosslets_info(c_crosslets_info_rec);
 
+  -- Crosslets settings
+  CONSTANT c_mm_nof_crosslets          : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0) := TO_UVEC(g_nof_crosslets, c_sdp_nof_crosslets_reg_w);
+  CONSTANT c_mm_nof_packets            : NATURAL := func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, g_P_sq, g_nof_crosslets);
+
   -- payload data
-  CONSTANT c_data_size : NATURAL := c_sdp_W_statistic_sz;
-  CONSTANT c_nof_data  : NATURAL := c_nof_statistics_per_packet;
+  CONSTANT c_packet_size : NATURAL := c_nof_statistics_per_packet * c_sdp_W_statistic_sz;
 
-  -- Define SST RAM size for c_nof_packets_max.
-  CONSTANT c_ram_size  : NATURAL := c_nof_data * c_data_size * c_nof_packets_max;
+  -- Define statistics RAM size for c_nof_packets_max.
+  CONSTANT c_ram_size  : NATURAL := c_packet_size * c_nof_packets_max;
   CONSTANT c_ram_w     : NATURAL := ceil_log2(c_ram_size);
   --CONSTANT c_ram_buf   : t_c_mem := (c_mem_ram_rd_latency, c_ram_w,  32, 2**c_ram_w, 'X');
   CONSTANT c_ram_buf   : t_c_mem := (1, c_ram_w,  32, 2**c_ram_w, 'X');
 
+  -- RAM dimensions
+  -- . nof_statistics_per_packet = c_mm_nof_data * c_mm_data_size / c_sdp_W_statistic_sz
+  CONSTANT c_mm_user_size        : NATURAL := func_sdp_get_stat_from_mm_user_size(g_statistics_type);
+  CONSTANT c_mm_data_size        : NATURAL := func_sdp_get_stat_from_mm_data_size(g_statistics_type);
+  CONSTANT c_mm_step_size        : NATURAL := func_sdp_get_stat_from_mm_step_size(g_statistics_type);
+  CONSTANT c_mm_nof_data         : NATURAL := func_sdp_get_stat_from_mm_nof_data(g_statistics_type);
+  CONSTANT c_mm_ram_size         : NATURAL := c_mm_nof_data * c_mm_data_size * c_nof_packets_max;  -- = c_ram_size
+
+  CONSTANT c_mm_nof_step         : NATURAL := c_mm_step_size / c_mm_data_size;
+  CONSTANT c_mm_Xsq_span         : NATURAL := 2**ceil_log2(c_sdp_N_crosslets_max * c_packet_size);  -- XST: 2**ceil_log2(7 * 576) = 4096
+
   -- Define block timing.
   CONSTANT c_bsn_init            : NATURAL := 0;
-  CONSTANT c_nof_block_per_sync  : NATURAL := 3 + ceil_div(c_offload_time, c_nof_data) + c_nof_packets_max;  -- Sufficient to fit more than c_nof_packets_max offload packets per sync interval.
-  CONSTANT c_nof_clk_per_block   : NATURAL := c_nof_data * c_data_size;
-  CONSTANT c_nof_valid_per_block : NATURAL := c_nof_data * c_data_size;
-  CONSTANT c_nof_sync            : NATURAL := 3;
+  -- Sufficient c_nof_block_per_sync to fit more than c_nof_packets_max offload packets per sync interval.
+  CONSTANT c_nof_block_per_sync  : NATURAL := 3 + ceil_div(c_offload_time, c_packet_size) + c_nof_packets_max;
+  CONSTANT c_nof_clk_per_block   : NATURAL := c_packet_size;
   CONSTANT c_nof_clk_per_sync    : NATURAL := c_nof_block_per_sync * c_nof_clk_per_block;
+  CONSTANT c_nof_sync            : NATURAL := 3;
 
   SIGNAL tb_end : STD_LOGIC := '0';
 
@@ -143,11 +159,11 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
   SIGNAL offload_sosi            : t_dp_sosi;
   SIGNAL offload_siso            : t_dp_siso := c_dp_siso_rst;
 
+  SIGNAL test_offload_en         : STD_LOGIC := '0';
   SIGNAL test_offload_data       : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- 32 bit
   SIGNAL test_offload_sosi       : t_dp_sosi := c_dp_sosi_rst;
-  SIGNAL test_offload_en         : STD_LOGIC := '0';
-  SIGNAL test_offload_sop_cnt    : NATURAL;
-  SIGNAL test_offload_eop_cnt    : NATURAL;
+  SIGNAL test_offload_sop_cnt    : NATURAL := 0;
+  SIGNAL test_offload_eop_cnt    : NATURAL := 0;
 
   SIGNAL rx_hdr_fields_out       : STD_LOGIC_VECTOR(1023 DOWNTO 0);
   SIGNAL rx_hdr_fields_raw       : STD_LOGIC_VECTOR(1023 DOWNTO 0) := (OTHERS => '0');
@@ -163,7 +179,11 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
   SIGNAL exp_xst_signal_input_A  : NATURAL;
   SIGNAL exp_xst_signal_input_B  : NATURAL;
 
-  -- Signals used to change settings of sdp_info. 
+  SIGNAL rx_val                  : STD_LOGIC := '0';
+  SIGNAL rx_data                 : NATURAL;
+  SIGNAL exp_data                : NATURAL;
+
+  -- Signals used to change settings of sdp_info.
   SIGNAL sdp_info  :  t_sdp_info := (
                         TO_UVEC(601, 16),   -- station_id
                         '0',                -- antenna_band_index
@@ -185,8 +205,6 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
   SIGNAL source_gn : NATURAL;  -- source node GN
 
   SIGNAL subband_calibrated_flag : STD_LOGIC := '0';
-  SIGNAL nof_crosslets           : STD_LOGIC_VECTOR(c_sdp_nof_crosslets_reg_w-1 DOWNTO 0) := (OTHERS => '0');
-  SIGNAL nof_packets             : NATURAL;
 
   -- Signals used for starting processes.
   SIGNAL ram_wr_data      : STD_LOGIC_VECTOR(c_ram_buf.dat_w-1 DOWNTO 0);
@@ -194,9 +212,8 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
   SIGNAL ram_wr_en        : STD_LOGIC;
   SIGNAL init_ram_done    : STD_LOGIC := '0';
 
-  SIGNAL in_sync_hold     : STD_LOGIC := '0';
   SIGNAL in_sync_cnt      : NATURAL := 0;
-  SIGNAL test_sync_cnt    : INTEGER;
+  SIGNAL test_sync_cnt    : INTEGER := 0;
 
   SIGNAL rx_packet_cnt    : NATURAL := 0;
   SIGNAL rx_valid_cnt     : NATURAL := 0;
@@ -209,14 +226,23 @@ ARCHITECTURE tb OF tb_sdp_statistics_offload IS
   SIGNAL dbg_c_nof_signal_inputs         : NATURAL := c_nof_signal_inputs;
   SIGNAL dbg_c_nof_packets_max           : NATURAL := c_nof_packets_max;
   SIGNAL dbg_c_beamlet_index             : NATURAL := c_beamlet_index;
-  SIGNAL dbg_c_data_size                 : NATURAL := c_data_size;
-  SIGNAL dbg_c_nof_data                  : NATURAL := c_nof_data;
+  SIGNAL dbg_c_packet_size               : NATURAL := c_packet_size;
+  SIGNAL dbg_c_mm_user_size              : NATURAL := c_mm_user_size;
+  SIGNAL dbg_c_mm_data_size              : NATURAL := c_mm_data_size;
+  SIGNAL dbg_c_mm_step_size              : NATURAL := c_mm_step_size;
+  SIGNAL dbg_c_mm_nof_data               : NATURAL := c_mm_nof_data;
+  SIGNAL dbg_c_mm_ram_size               : NATURAL := c_mm_ram_size;
+  SIGNAL dbg_c_mm_nof_step               : NATURAL := c_mm_nof_step;
+  SIGNAL dbg_c_mm_Xsq_span               : NATURAL := c_mm_Xsq_span;
   SIGNAL dbg_c_ram_size                  : NATURAL := c_ram_size;
   SIGNAL dbg_c_crosslets_info_rec        : t_sdp_crosslets_info := c_crosslets_info_rec;
   SIGNAL dbg_c_crosslets_info_slv        : STD_LOGIC_VECTOR(c_sdp_crosslets_info_reg_w-1 DOWNTO 0) := c_crosslets_info_slv;
 
 BEGIN
 
+  -- Check consistency of constant value dependencies
+  ASSERT c_ram_size = c_mm_ram_size REPORT "Wrong derivation of RAM size." SEVERITY FAILURE;
+
   dp_rst <= '1', '0' AFTER c_dp_clk_period*7;
   dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2;
   
@@ -292,36 +318,23 @@ BEGIN
     WAIT;
   END PROCESS;
 
-  -- Crosslets settings
-  nof_crosslets <= TO_UVEC(g_nof_crosslets, c_sdp_nof_crosslets_reg_w);
-  nof_packets   <= func_sdp_get_stat_nof_packets(g_statistics_type, c_sdp_S_pn, g_P_sq, g_nof_crosslets);
-
   -- Counters to time expected exp_sdp_stat_header fields per offload packet
-  p_exp_counters : PROCESS(dp_clk)
+  p_test_counters : PROCESS(dp_clk)
   BEGIN
     IF rising_edge(dp_clk) THEN
-      -- Count sync intervals using in_sosi.sync, because there is no test_offload_sosi.sync
-      IF test_offload_en = '0' THEN
-        in_sync_cnt <= 0;
-        test_offload_sop_cnt <= 0;
-        test_offload_eop_cnt <= 0;
-      ELSE
-        -- Count test_offload_sosi sync integration intervals
-        IF in_sosi.sync = '1' THEN
-          in_sync_cnt <= in_sync_cnt + 1;
-        END IF;
-
-        -- Count test_offload_sosi packets
-        IF test_offload_sosi.sop = '1' THEN
-          test_offload_sop_cnt <= test_offload_sop_cnt + 1;  -- early count
-        END IF;
-        IF test_offload_sosi.eop = '1' THEN
-          test_offload_eop_cnt <= test_offload_eop_cnt + 1;  -- after count
-        END IF;
+      -- Count test_offload_sosi packets
+      IF test_offload_sosi.sop = '1' THEN
+        test_offload_sop_cnt <= test_offload_sop_cnt + 1;  -- early count
+      END IF;
+      IF test_offload_sosi.eop = '1' THEN
+        test_offload_eop_cnt <= test_offload_eop_cnt + 1;  -- after count
       END IF;
     END IF;
   END PROCESS;
-  test_sync_cnt <= in_sync_cnt + 0;  -- optionally adjust to fit test_offload_sosi
+
+  -- Count sync intervals using in_sosi.sync, because there is no test_offload_sosi.sync
+  in_sync_cnt <= in_sync_cnt + 1 WHEN rising_edge(dp_clk) AND in_sosi.sync = '1';
+  test_sync_cnt <= in_sync_cnt - 1;  -- optionally adjust to fit test_offload_sosi
 
   -- derive current X_sq correlator cell index
   cur_X_sq_cell <= (test_offload_eop_cnt / g_nof_crosslets) MOD g_P_sq;
@@ -428,21 +441,16 @@ BEGIN
   END PROCESS;
 
   -- Count number of packets in a sync interval.
-  -- There is no active test_offload_sosi.sync to restart the count. Therefore capture the in_sosi.sync in in_sync_hold, and
-  -- use in_sync_hold with test_offload_sosi.sop to start counting packets from 0, at the start of every sync interval.
+  -- There is no active test_offload_sosi.sync to restart the count, therefore
+  -- use in_sosi.sync to reset the count for the next test_offload_sosi.sync
+  -- interval
   p_rx_packet_cnt : PROCESS(dp_clk)
   BEGIN
     IF rising_edge(dp_clk) THEN
-      IF test_offload_sosi.sop = '1' THEN
-        IF in_sync_hold = '1' THEN
-          in_sync_hold <= '0';
-          rx_packet_cnt <= 0;
-        ELSE
-          rx_packet_cnt <= rx_packet_cnt + 1;
-        END IF;
-      END IF;
       IF in_sosi.sync = '1' THEN
-        in_sync_hold <= '1';
+        rx_packet_cnt <= 0;
+      ELSIF test_offload_sosi.eop = '1' THEN
+        rx_packet_cnt <= rx_packet_cnt + 1;
       END IF;
     END IF;
   END PROCESS;
@@ -451,12 +459,8 @@ BEGIN
   p_verify_nof_packets : PROCESS(dp_clk)
   BEGIN
     IF rising_edge(dp_clk) THEN
-      IF init_ram_done = '1' THEN
-
-        IF in_sosi.sync = '1' AND rx_packet_cnt > 0 THEN
-          ASSERT rx_packet_cnt = nof_packets-1 REPORT "Wrong number of packets per sync interval" SEVERITY ERROR;
-        END IF;
-
+      IF in_sosi.sync = '1' AND in_sync_cnt > 1 THEN
+        ASSERT rx_packet_cnt = c_mm_nof_packets REPORT "Wrong number of packets per sync interval" SEVERITY ERROR;
       END IF;
     END IF;
   END PROCESS;
@@ -464,12 +468,144 @@ BEGIN
   p_verify_nof_valid_per_packet : PROCESS(dp_clk)
   BEGIN
     IF rising_edge(dp_clk) THEN
-      IF test_offload_sosi.sop = '1' THEN
-        rx_valid_cnt <= 1;
-      ELSIF test_offload_sosi.eop = '1' THEN
-        ASSERT rx_valid_cnt+1 = c_nof_valid_per_block REPORT "Wrong number of valid per packet" SEVERITY ERROR;
-      ELSE
-        rx_valid_cnt <= rx_valid_cnt + 1;  -- test_offload_sosi.valid has no gaps
+      IF test_offload_sosi.eop = '1' THEN
+        rx_valid_cnt <= 0;
+        ASSERT rx_valid_cnt = c_packet_size - 1 REPORT "Wrong number of valid per packet" SEVERITY ERROR;
+      ELSIF test_offload_sosi.valid = '1' THEN
+        rx_valid_cnt <= rx_valid_cnt + 1;
+      END IF;
+    END IF;
+  END PROCESS;
+
+  p_verify_payload : PROCESS(dp_clk)
+    VARIABLE W            : NATURAL;  -- 32bit Words
+    VARIABLE D            : NATURAL;  -- Data values of c_mm_data_size
+    VARIABLE S            : NATURAL;  -- Statistic values of c_sdp_W_statistic_sz
+    VARIABLE P            : NATURAL;  -- Packet count
+    VARIABLE I, J, K, L   : NATURAL;  -- auxiliary index
+    VARIABLE U            : NATURAL;  -- real sUbband SST values
+    VARIABLE B            : NATURAL;  -- dual polarization Beamlet BST values
+    VARIABLE X            : NATURAL;  -- complex crosslet XST values
+    VARIABLE v_rx_data    : NATURAL;  -- received (rx) 32bit word
+    VARIABLE v_exp_data   : NATURAL;  -- expected (exp) 32bit word
+  BEGIN
+    IF rising_edge(dp_clk) THEN
+      rx_val <= '0';
+      v_rx_data := TO_UINT(test_offload_sosi.data);
+      IF test_offload_sosi.valid = '1' THEN
+        IF g_statistics_type = "SST" THEN
+          --        Indices:
+          --         W:    0     1      2     3      4     5 ...  1022  1023
+          -- U = D = S:    0            1            2             511
+          --         I:    0     1      0     1      0     1 ...     0     1
+          --    P: J: Words values:
+          --    0  0       0     1      4     5      8     9 ...  2044  2045
+          --    1  1       2     3      6     7     10    11 ...  2046  2047
+          --    2  0    2048  2049   2052  2053   2056  2057 ...  4092  4093
+          --    3  1    2050  2051   2054  2055   2058  2059 ...  4094  4095
+          --   ...                                           ...
+          --   11  1   10242 10243  10246 10247  10250 10251 ... 12286 12287
+          --
+          -- g_reverse_word_order = TRUE: swaps odd and even W columns, because
+          --   c_mm_user_size = c_sdp_W_statistic_sz = 2
+
+          W := rx_valid_cnt;                -- range c_packet_size = 1024 32bit Words
+          S := W / c_sdp_W_statistic_sz;    -- range c_nof_statistics_per_packet = 512 Statistic values
+          D := S;                           -- range c_mm_nof_data = 512 Data values, because
+                                            -- c_mm_data_size / c_sdp_W_statistic_sz = 1
+          U := S;                           -- range c_sdp_N_sub = 512 SST values
+          I := W MOD c_mm_user_size;        -- range c_mm_user_size = c_sdp_W_statistic_sz = 2 words
+          P := rx_packet_cnt;               -- range c_nof_packets_max = 12 = c_sdp_S_pn Packets
+          J := P MOD c_mm_nof_step;         -- range c_mm_nof_step = 2 = c_sdp_Q_fft
+
+          v_exp_data := S * 4;  -- due to c_mm_step_size = 4 = c_sdp_W_statistic_sz * c_sdp_Q_fft;
+          IF I = sel_a_b(g_reverse_word_order, 0, 1) THEN
+            v_exp_data := v_exp_data + 1;  -- due to c_mm_user_size = 2
+          END IF;
+          IF J = 1 THEN
+            v_exp_data := v_exp_data + 2;  -- due to c_sdp_W_statistic_sz = 2 and c_mm_nof_step = 2 > 1
+          END IF;
+          v_exp_data := v_exp_data + (P/2) * 2048;  -- due to c_packet_size = 1024 and c_mm_nof_step = 2 > 1
+          ASSERT v_exp_data = v_rx_data REPORT "Wrong SST payload data Rx" SEVERITY ERROR;
+
+        ELSIF g_statistics_type = "BST" THEN
+          --    Indices:
+          --     W:    0     1      2     3      4     5 ...  1948  1949   1950  1951
+          --     S:    0            1            2       ...   974          975
+          -- B = D:    0                         1       ...   487
+          --     I:    0     1      2     3      0       ...     0     1      2     3
+          --  P:  Words values:
+          --  0        0     1      2     3      4     5 ...  1948  1949   1950  1951
+          --
+          -- g_reverse_word_order = TRUE: swaps odd and even W columns, because
+          --   c_mm_user_size = c_sdp_W_statistic_sz = 2
+
+          W := rx_valid_cnt;                -- range c_packet_size = 1952
+          S := W / c_sdp_W_statistic_sz;    -- range c_nof_statistics_per_packet = 976 Statistic values
+          D := S / c_sdp_N_pol_bf;          -- range c_mm_nof_data = 488 Data values, because
+                                            -- c_mm_data_size / c_sdp_W_statistic_sz = 2 = c_sdp_N_pol_bf
+          B := D;                           -- range c_sdp_S_sub_bf = 488 dual polarization BST values
+          I := W MOD c_mm_user_size;        -- range c_mm_user_size = c_sdp_W_statistic_sz = 2 words
+          P := rx_packet_cnt;               -- range c_nof_packets_max = 1
+
+          v_exp_data := S * c_mm_user_size;  -- c_mm_user_size = 2
+          IF g_reverse_word_order = FALSE THEN
+            v_exp_data := v_exp_data + I;
+          ELSE
+            v_exp_data := v_exp_data - I + c_mm_user_size-1;
+          END IF;
+          ASSERT v_exp_data = v_rx_data REPORT "Wrong BST payload data Rx" SEVERITY ERROR;
+
+        ELSIF g_statistics_type = "XST" THEN
+          -- . g_P_sq = 4
+          -- . g_nof_crosslets = 3
+          -- . c_sdp_N_crosslets_max = 7 --> c_mm_Xsq_span = 2**ceil_log2(7 * 576) = 4096
+          --
+          --      W:        0     1      2     3      4     5 ...   572   573   574   575
+          --      S:        0            1            2       ...   286         287
+          --  X = D:        0                         1       ...   143
+          --      I:        0     1      2     3      0       ...     0     1     2     3
+          --   P: J: K: Word values:
+          --   0  0  0      0     1      2     3      4     5 ...   572   573   574   575
+          --   1  1       576                                 ...
+          --   2  2      1052                                 ...
+          --
+          --   3  0  1   4096                                 ...
+          --   4  1      4672                                 ...
+          --   5  2      5244                                 ...
+          --   ...
+          --   9  0  3  12288                                 ...
+          --  10  1     12864                                 ...
+          --  11  2     13436                                 ...
+          --
+          -- g_reverse_word_order = TRUE: swaps odd and even W columns, because
+          --   c_mm_user_size = c_sdp_W_statistic_sz = 2
+
+          W := rx_valid_cnt;                -- range c_packet_size = 576
+          S := W / c_sdp_W_statistic_sz;    -- range c_nof_statistics_per_packet = 288 Statistic values
+          D := S / c_nof_complex;           -- range c_mm_nof_data = 144 Data values, because
+                                            -- c_mm_data_size / c_sdp_W_statistic_sz = 2 = c_nof_complex
+          X := D;                           -- range c_sdp_X_sq = 144 complex XST values
+          I := W MOD c_mm_user_size;        -- range c_mm_user_size = c_nof_complex * c_sdp_W_statistic_sz = 4 words
+          P := rx_packet_cnt;               -- range c_mm_nof_packets
+          J := P MOD g_nof_crosslets;       -- range g_nof_crosslets
+          K := P / g_nof_crosslets;         -- range g_P_sq
+
+          v_exp_data := D * c_mm_user_size;
+          IF g_reverse_word_order = FALSE THEN
+            v_exp_data := v_exp_data + I;
+          ELSE
+            v_exp_data := v_exp_data - I + c_mm_user_size-1;  -- c_mm_user_size = 4
+          END IF;
+          v_exp_data := v_exp_data + J * c_packet_size;  -- c_packet_size = 576
+          v_exp_data := v_exp_data + K * c_mm_Xsq_span;  -- c_mm_Xsq_span = 4096
+          ASSERT v_exp_data = v_rx_data REPORT "Wrong XST payload data Rx" SEVERITY ERROR;
+
+        END IF;
+        -- for debug in wave window
+        rx_val <= '1';
+        rx_data <= v_rx_data;
+        exp_data <= v_exp_data;
       END IF;
     END IF;
   END PROCESS;
@@ -535,6 +671,7 @@ BEGIN
   GENERIC MAP (
     g_statistics_type     => g_statistics_type,
     g_offload_time        => g_offload_time,
+    g_reverse_word_order  => g_reverse_word_order,
     g_beamset_id          => g_beamset_id,
     g_P_sq                => g_P_sq,
     g_crosslets_direction => g_crosslets_direction
@@ -570,7 +707,7 @@ BEGIN
 
     sdp_info                => sdp_info,
     subband_calibrated_flag => subband_calibrated_flag,
-    nof_crosslets           => nof_crosslets,
+    nof_crosslets           => c_mm_nof_crosslets,
     crosslets_info          => in_crosslets_info_slv
   );
 
diff --git a/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd
index db3baf5a19b8352c9da6e203b68ddc8cdb0ad2e4..a688d26acd7d88aba8f60ca51f3409710bf0c36e 100644
--- a/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_tb_sdp_statistics_offload.vhd
@@ -40,6 +40,7 @@ BEGIN
 --    -- All
 --    g_statistics_type          : STRING := "SST";
 --    g_offload_time             : NATURAL := 500;
+--    g_reverse_word_order       : BOOLEAN := TRUE  -- when TRUE then stream LSB word after MSB word.
 --    g_gn_index                 : NATURAL := 1;  -- global node (GN) index, use > 0 to see effect of g_offload_time
 --    -- BST
 --    g_beamset_id               : NATURAL := 0;
@@ -50,14 +51,17 @@ BEGIN
 --    g_nof_crosslets            : NATURAL := 1;
 --    g_crosslets_direction      : INTEGER := 1;  -- +1 or -1
 
-  u_sst              : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("SST", 50, 3, 0, 0);
-  u_bst_0            : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("BST", 50, 1, 0, 0);
-  u_bst_1            : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("BST", 50, 1, 1, 0);
-  u_xst_P1           : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16,  1, 1, 1);
-  u_xst_P1_N3        : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16,  1, 3, 1);
-  u_xst_P9           : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16,  9, 1, 1);
-  u_xst_P9_N3        : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16,  9, 3, 1);
-  u_xst_P9_N3_neg    : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 0, 16,  9, 3, 0);
-  u_xst_P8_N7_RN1_15 : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, 1, 0, 1, 15,  8, 7, 0);
+  u_sst                  : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("SST", 50,  TRUE, 3, 0, 0);
+  u_sst_no_reverse       : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("SST", 50, FALSE, 3, 0, 0);
+  u_bst_0                : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("BST", 50,  TRUE, 1, 0, 0);
+  u_bst_0_no_reverse     : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("BST", 50, FALSE, 1, 0, 0);
+  u_bst_1                : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("BST", 50,  TRUE, 1, 1, 0);
+  u_xst_P1               : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50,  TRUE, 1, 0, 0, 16,  1, 1, 1);
+  u_xst_P1_N3            : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50,  TRUE, 1, 0, 0, 16,  1, 3, 1);
+  u_xst_P9               : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50,  TRUE, 1, 0, 0, 16,  9, 1, 1);
+  u_xst_P9_N3            : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50,  TRUE, 1, 0, 0, 16,  9, 3, 1);
+  u_xst_P9_N3_no_reverse : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50, FALSE, 1, 0, 0, 16,  9, 3, 1);
+  u_xst_P9_N3_neg        : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50,  TRUE, 1, 0, 0, 16,  9, 3, 0);
+  u_xst_P8_N7_RN1_15     : ENTITY work.tb_sdp_statistics_offload GENERIC MAP("XST", 50,  TRUE, 1, 0, 1, 15,  8, 7, 0);
 
 END tb;
diff --git a/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd b/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd
index 795c772f562a4c8e01bd747ff4e3c6bc49016fed..462d489dce2291ffc9e2e82d5603d9bba517bbb4 100644
--- a/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd
+++ b/libraries/base/dp/src/vhdl/dp_block_from_mm.vhd
@@ -18,11 +18,42 @@
 
 -- --------------------------------------------------------------------------
 -- Author: 
--- . Pieter Donker, R van der Walle
+-- . Pieter Donker, R van der Walle, E. Kooistra
 -- Purpose:
 -- . Read a block of data from memory mapped (MM) location and stream it as a block of data.
 -- Description:
 -- . https://support.astron.nl/confluence/display/L2M/L5+SDPFW+Design+Document%3A+Subband+filterbank
+--
+-- . g_*_size, g_word_w:
+--   The g_*_size values are in number of g_word_w memory words, so e.g.
+--   32bit words. The 32bit words are read in data blocks of g_data_size
+--   words. The data block contains U = g_data_size / g_user_size
+--   number of user words. U is and integer. This occurs e.g. for U = 2
+--   when the data block contains:
+--   - a complex value, so with real part and imag part
+--   - dual polarization value, so with X polarization and Y polarization
+--   The user words contain g_user_size number of g_word_w = 32bit words.
+--   The output out_sosi.data width is also g_word_w bits.
+--
+-- . g_step_size:
+--   The g_step_size = K * g_data_size, where K >= 1 to allow read out of
+--   data blocks that are interleaved by a factor K.
+--
+-- . g_nof_data and start_pulse, start_address, mm_mosi, mm_miso, mm_done:
+--   The g_nof_data is the number of data blocks that are read out via
+--   mm_mosi/mm_miso per start_pulse, to form a new aggregate output block
+--   with out_sosi.sop and out_sosi.eop. When the read out is done, then
+--   mm_done pulses and a new start_pulse can be issued. By incrementing
+--   the start_address for every start_pulse it is possible to read out K
+--   interleaved sets of data blocks from the memory.
+--
+-- . g_reverse_word_order per g_user_size:
+--   The g_reverse_word_order has no effect when FALSE, but reverses the
+--   read out order of the 32bit words per user word when TRUE. The
+--   g_reverse_word_order has to apply per user word and not per data block,
+--   to preserve the order of the user parts (e.g. real and imag, X and Y
+--   polarization) in a data block.
+--
 -- --------------------------------------------------------------------------
 
 LIBRARY IEEE,common_lib;
@@ -34,10 +65,11 @@ USE work.dp_stream_pkg.ALL;
 
 ENTITY dp_block_from_mm IS
   GENERIC (
+    g_user_size          : NATURAL;
     g_data_size          : NATURAL;
     g_step_size          : NATURAL;
     g_nof_data           : NATURAL;
-    g_data_w             : NATURAL := c_word_w;
+    g_word_w             : NATURAL := c_word_w;
     g_mm_rd_latency      : NATURAL := 1;  -- default 1 from rd_en to rd_val, use 2 to ease timing closure
     g_reverse_word_order : BOOLEAN := FALSE
   ); 
@@ -58,23 +90,25 @@ END dp_block_from_mm;
 ARCHITECTURE rtl OF dp_block_from_mm IS 
 
   CONSTANT c_mem_size : NATURAL := g_step_size * g_nof_data;
-  CONSTANT c_word_index_rst : NATURAL := sel_a_b(g_reverse_word_order, g_data_size - 1, 0);
 
   TYPE t_reg IS RECORD
-    busy       : STD_LOGIC;
-    sop        : STD_LOGIC;
-    eop        : STD_LOGIC;
-    word_index : NATURAL;
-    step_index : NATURAL;
+    busy         : STD_LOGIC;
+    sop          : STD_LOGIC;
+    eop          : STD_LOGIC;
+    user_index   : NATURAL RANGE 0 TO g_user_size;  -- word index in g_user_size
+    data_index   : NATURAL RANGE 0 TO g_data_size;  -- default word order index in g_data_size
+    word_index   : NATURAL RANGE 0 TO g_data_size;  -- default or reversed word order index in g_data_size
+    step_address : NATURAL RANGE 0 TO c_mem_size;   -- step address offset
   END RECORD;
 
-  CONSTANT c_reg_rst : t_reg := ('0', '0', '0', c_word_index_rst, 0);
+  CONSTANT c_reg_rst : t_reg := ('0', '0', '0', 0, 0, 0, 0);
 
   SIGNAL r     : t_reg;
   SIGNAL nxt_r : t_reg;
 
-  SIGNAL mm_address      : NATURAL := 0;
   SIGNAL last_mm_address : NATURAL := 0;
+  SIGNAL mm_address      : NATURAL := 0;
+  SIGNAL mm_address_rev  : NATURAL := 0;
 
   SIGNAL r_sop_p  : STD_LOGIC;
   SIGNAL r_eop_p  : STD_LOGIC;
@@ -84,8 +118,9 @@ ARCHITECTURE rtl OF dp_block_from_mm IS
 BEGIN
 
   last_mm_address <= g_step_size * (g_nof_data - 1) + g_data_size + start_address - 1;
-  mm_address      <= start_address + r.word_index + r.step_index;
-  
+  mm_address      <= start_address + r.data_index + r.step_address;  -- default word order per g_user_size
+  mm_address_rev  <= start_address + r.word_index + r.step_address;  -- reverse word order per g_user_size
+
   -- Take care of g_mm_rd_latency for out_sosi.sop and out_sosi.eop
   r_sop_p <= r.sop WHEN rising_edge(clk);
   r_eop_p <= r.eop WHEN rising_edge(clk);
@@ -95,7 +130,7 @@ BEGIN
   u_sosi : PROCESS(r, mm_miso, out_sop, out_eop)
   BEGIN
     out_sosi       <= c_dp_sosi_rst;  -- To avoid Modelsim warnings on conversion to integer from unused fields.
-    out_sosi.data  <= RESIZE_DP_DATA(mm_miso.rddata(g_data_w-1 DOWNTO 0));
+    out_sosi.data  <= RESIZE_DP_DATA(mm_miso.rddata(g_word_w-1 DOWNTO 0));
     out_sosi.valid <= mm_miso.rdval;  -- read latency from mm_mosi.rd to mm_miso.rdval is 1, so same as the ready latency (RL = 1)
     out_sosi.sop   <= out_sop;        -- read latency from mm_mosi.rd to mm_miso.rdval is 1, so r.sop can be used for output sop
     out_sosi.eop   <= out_eop;        -- read latency from mm_mosi.rd to mm_miso.rdval is 1, so r.eop can be used for output eop
@@ -112,17 +147,20 @@ BEGIN
     END IF;
   END PROCESS;
 
-  p_comb : PROCESS(r, start_pulse, out_siso, mm_address, last_mm_address)
-    VARIABLE v : t_reg;
+  p_comb : PROCESS(r, start_pulse, out_siso, mm_address, mm_address_rev, last_mm_address)
+    VARIABLE v         : t_reg;
+    VARIABLE v_base    : NATURAL;
+    VARIABLE v_reverse : NATURAL;
   BEGIN
     v := r;
     v.sop := '0';
     v.eop := '0';
-    mm_mosi <= c_mem_mosi_rst;  -- use default 0 to avoid Warning: (vsim-8684) No drivers exist on out port .wr, .wrdata
-    mm_mosi.address <= TO_MEM_ADDRESS(mm_address);  -- only use mosi.rd and mosi.address
+
+    -- Use default c_mem_mosi_rst to avoid Warning: (vsim-8684) No drivers exist on out port .wr, .wrdata
+    mm_mosi <= c_mem_mosi_rst;
 
     IF r.busy = '0' AND start_pulse = '1' THEN
-      -- initiate next block
+      -- initiate next output block
       v.busy := '1';
     END IF;
 
@@ -130,57 +168,54 @@ BEGIN
     -- support zero gaps between output blocks
     IF v.busy = '1' THEN
       IF out_siso.ready = '1' THEN
-        -- continue with block
+        -- Continue with output block
         mm_mosi.rd <= '1';
 
-        IF g_reverse_word_order THEN
-
-          IF r.word_index > 0 THEN
-            v.word_index := r.word_index - 1;
-          ELSE
-            v.word_index := g_data_size - 1;
-            v.step_index := r.step_index + g_step_size;
-          END IF;
-          
-          -- check start of block
-          IF r.word_index = g_data_size - 1 AND r.step_index = 0 THEN
-            v.sop := '1';
-          END IF;
-
+        -- Calculate data_index for default word order
+        IF r.data_index < g_data_size - 1 THEN
+          v.data_index := r.data_index + 1;
         ELSE
+          v.data_index := 0;
+          v.step_address := r.step_address + g_step_size;
+        END IF;
 
-          IF r.word_index < g_data_size - 1 THEN
-            v.word_index := r.word_index + 1;
-          ELSE
-            v.word_index := 0;
-            v.step_index := r.step_index + g_step_size;
-          END IF;
-          
-          -- check start of block
-          IF r.word_index = 0 AND r.step_index = 0 THEN
-            v.sop := '1';
-          END IF;
+        -- maintain user_index within g_user_size
+        IF r.user_index < g_user_size - 1 THEN
+          v.user_index := r.user_index + 1;
+        ELSE
+          v.user_index := 0;
+        END IF;
 
+        -- check start of output block
+        IF r.data_index = 0 AND r.step_address = 0 THEN
+          v.sop := '1';
         END IF;
-        
-        -- check end of block
-        IF g_reverse_word_order THEN
-          IF mm_address = last_mm_address - (g_data_size - 1) THEN -- with reversed word order the last word to read is actually the first word of the last step index
-            v.eop := '1';
-            -- prepare for next block
-            v.busy := '0';
-            v.step_index := 0;
-            v.word_index := g_data_size - 1;
-          END IF;
-        ELSIF mm_address >= last_mm_address THEN -- g_reverse_word_order = False
+
+        -- check end of output block
+        IF mm_address >= last_mm_address THEN
           v.eop := '1';
-          -- prepare for next block
+          -- prepare for next output block at next start_pulse
           v.busy := '0';
-          v.step_index := 0;
-          v.word_index := 0;
+          v.step_address := 0;
+          v.data_index := 0;
+          v.user_index := 0;
         END IF;
       END IF;
     END IF;
+
+    -- Default word order
+    v.word_index := v.data_index;
+    mm_mosi.address <= TO_MEM_ADDRESS(mm_address);
+
+    -- Account for g_reverse_word_order
+    IF g_reverse_word_order THEN
+      v_base    := v.data_index - v.user_index;     -- data_index of first word in g_user_size
+      v_reverse := g_user_size - 1 - v.user_index;  -- reverse word index in g_user_size
+      v.word_index := v_base + v_reverse;
+
+      mm_mosi.address <= TO_MEM_ADDRESS(mm_address_rev);
+    END IF;
+
     nxt_r <= v;
   END PROCESS;
     
diff --git a/libraries/base/dp/src/vhdl/dp_block_from_mm_dc.vhd b/libraries/base/dp/src/vhdl/dp_block_from_mm_dc.vhd
index cdf640ced48b4b93bd1906b931864646998525b6..0ac01ec489d22cf6d3e2843e7df9e9e6243e2150 100644
--- a/libraries/base/dp/src/vhdl/dp_block_from_mm_dc.vhd
+++ b/libraries/base/dp/src/vhdl/dp_block_from_mm_dc.vhd
@@ -24,6 +24,7 @@
 --   this is a dual-clock wrapper around dp_block_from_mm.vhd 
 -- Description:
 -- . https://support.astron.nl/confluence/display/L2M/L5+SDPFW+Design+Document%3A+Subband+filterbank
+-- . see dp_block_from_mm.vhd
 -- --------------------------------------------------------------------------
 
 LIBRARY IEEE,common_lib;
@@ -35,9 +36,11 @@ USE work.dp_stream_pkg.ALL;
 
 ENTITY dp_block_from_mm_dc IS
   GENERIC (
+    g_user_size          : NATURAL;
     g_data_size          : NATURAL;
     g_step_size          : NATURAL;
     g_nof_data           : NATURAL;
+    g_word_w             : NATURAL := c_word_w;
     g_reverse_word_order : BOOLEAN := FALSE
   ); 
   PORT (
@@ -135,9 +138,11 @@ BEGIN
 
   u_dp_block_from_mm : ENTITY work.dp_block_from_mm
   GENERIC MAP (
+    g_user_size          => g_user_size,
     g_data_size          => g_data_size,
     g_step_size          => g_step_size,
     g_nof_data           => g_nof_data,
+    g_word_w             => g_word_w,
     g_reverse_word_order => g_reverse_word_order 
   )
   PORT MAP (
diff --git a/libraries/base/dp/src/vhdl/dp_bsn_align_v2.vhd b/libraries/base/dp/src/vhdl/dp_bsn_align_v2.vhd
index e94cd4efd070011f1e89c84d1ca3ffdd8a6c89ed..20ca5fa3b09f0bf0ae1faa8e2cd028927add33f5 100644
--- a/libraries/base/dp/src/vhdl/dp_bsn_align_v2.vhd
+++ b/libraries/base/dp/src/vhdl/dp_bsn_align_v2.vhd
@@ -418,10 +418,11 @@ BEGIN
     gen_mm_to_dp : FOR I IN 0 TO g_nof_streams-1 GENERATE
       u_mm_to_dp: ENTITY work.dp_block_from_mm
       GENERIC MAP (
+        g_user_size          => 1,
         g_data_size          => 1,
         g_step_size          => 1,
         g_nof_data           => g_block_size,
-        g_data_w             => g_data_w,
+        g_word_w             => g_data_w,
         g_mm_rd_latency      => g_rd_latency,
         g_reverse_word_order => FALSE
       )
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_block_from_mm.vhd b/libraries/base/dp/tb/vhdl/tb_dp_block_from_mm.vhd
index d139f3759ed1daaac47c051f7902127421137580..321286228995bdcf88e91619cccaaf1e3de9306e 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_block_from_mm.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_block_from_mm.vhd
@@ -33,6 +33,9 @@
 --   . p_verify_read, set ram address (using g_data_size and g_step_size) to check and
 --     read value from ram, also set expected ram value.
 --   . p_verify_check, check if ram_value is equal to expected value. 
+--
+-- Remark:
+-- . g_user_size and g_reverse_word_order are verified in tb_sdp_statistics_offload.vhd
 -- --------------------------------------------------------------------------
 
 -- > as 10
@@ -222,6 +225,7 @@ BEGIN
   -- DUT, dp_block_from_mm
   u_dp_block_from_mm: ENTITY work.dp_block_from_mm
   GENERIC MAP (
+    g_user_size => g_data_size,
     g_data_size => g_data_size,
     g_step_size => g_step_size,
     g_nof_data  => g_nof_data
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd b/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd
index 1c464c468c67424c91dadffc99860e32c941e4c4..30f6a9475042ae14f1f04d2c064b0fa4d32fe4c5 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_bsn_align_v2.vhd
@@ -603,10 +603,11 @@ BEGIN
     gen_mm_to_dp : FOR I IN 0 TO g_nof_streams-1 GENERATE
       u_mm_to_dp: ENTITY work.dp_block_from_mm
       GENERIC MAP (
+        g_user_size          => 1,
         g_data_size          => 1,
         g_step_size          => 1,
         g_nof_data           => g_block_size,
-        g_data_w             => g_data_w,
+        g_word_w             => g_data_w,
         g_mm_rd_latency      => g_rd_latency,
         g_reverse_word_order => FALSE
       )