diff --git a/applications/lofar2/libraries/sdp/hdllib.cfg b/applications/lofar2/libraries/sdp/hdllib.cfg
index 06720dbf4fed95af61f17c22350b8afce784719d..d82f2018d6eee058d3c6c5894ff4bfdfc5d075bf 100644
--- a/applications/lofar2/libraries/sdp/hdllib.cfg
+++ b/applications/lofar2/libraries/sdp/hdllib.cfg
@@ -13,12 +13,14 @@ synth_files =
     src/vhdl/sdp_info_reg.vhd 
     src/vhdl/sdp_info.vhd 
     src/vhdl/sdp_beamformer_output.vhd 
+    src/vhdl/sdp_statistics_offload.vhd 
     src/vhdl/node_sdp_adc_input_and_timing.vhd
     src/vhdl/node_sdp_filterbank.vhd
     src/vhdl/node_sdp_beamformer.vhd
 
 test_bench_files =
     tb/vhdl/tb_sdp_info.vhd 
+    tb/vhdl/tb_sdp_statistics_offload.vhd 
 
 regression_test_vhdl = 
     tb/vhdl/tb_sdp_info.vhd
diff --git a/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..1e364d312a7e91a0a00f14098c023513f7769ef5
--- /dev/null
+++ b/applications/lofar2/libraries/sdp/src/vhdl/sdp_statistics_offload.vhd
@@ -0,0 +1,377 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2020
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+--
+-- Author: P. Donker
+
+-- Purpose:
+-- . SDP statistics offload
+-- Description:
+--
+-- https://support.astron.nl/confluence/pages/viewpage.action?spaceKey=L2M&title=L5+SDPFW+Design+Document%3A+Subband+filterbank
+-- https://plm.astron.nl/polarion/#/project/LOFAR2System/wiki/L2%20Interface%20Control%20Documents/SC%20to%20SDP%20ICD
+--
+-- Remark:
+-- . Offload SST, BST or XST data from the memory to a network interface
+--   get data from mm bus and assemble header from from other input settings
+--
+--   A processing node (PN) in the ring ia called a ring node (RN).
+-- 
+--   g_statistics_type = "SST"   
+--     data_id.signal_input_index = rn_id * S_pn
+--     nof_signal_inputs = 1
+--     nof_statistics_per_packet = N_sub
+--
+--   g_statistics_type = "BST"
+--     data_id.beamlet_index = g_beamset_index * S_sub_bf
+--     nof_signal_inputs = 0 (default not used)
+--     nof_statistics_per_packet = S_sub_bf
+--
+--   g_statistics_type = "XST"
+--     data_id.signal_input_A_index = rn_id * S_pn
+--     data_id.signal_input_B_index = function of correlator cell instance and rn_id * S_pn
+--     nof_signal_inputs = S_pn => 12 (fixed)
+--     nof_statistics_per_packet = S_pn * S_pn => 12 * 12 = 144
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, mm_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE work.sdp_pkg.ALL;
+
+ENTITY sdp_statistics_offload IS
+  GENERIC (
+    g_statistics_type : STRING  := "SST";
+    g_offload_time    : NATURAL := 0;
+    g_beamset_id      : NATURAL := 0
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst : IN  STD_LOGIC;   -- reset synchronous with mm_clk
+    mm_clk : IN  STD_LOGIC;   -- memory-mapped bus clock
+
+    dp_clk : IN  STD_LOGIC;
+    dp_rst : IN  STD_LOGIC;
+
+    -- from MM master multiplexer
+    master_mosi : IN  t_mem_mosi := c_mem_mosi_rst;
+    master_miso : OUT t_mem_miso;
+
+    reg_enable_mosi : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_enable_miso : OUT t_mem_miso;
+
+    reg_hdr_dat_mosi : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_hdr_dat_miso : OUT t_mem_miso;
+
+    in_sosi     : IN t_dp_sosi;  -- from selector (sst_sosi_arr[0])
+    out_sosi    : OUT t_dp_sosi;  -- output from SST UDP offload (sst_udp_sosi)
+
+    -- inputs from other blocks
+    eth_src_mac  : IN STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
+    udp_src_port : IN STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0);
+    ip_src_addr  : IN STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0);
+    sdp_info     : IN t_sdp_info;
+
+    gn_index     : IN NATURAL
+  );
+END sdp_statistics_offload;
+
+
+ARCHITECTURE str OF sdp_statistics_offload IS
+
+  CONSTANT c_version                    : NATURAL  := 1;
+  CONSTANT c_marker                     : NATURAL  := sel_a_b((g_statistics_type="BST"), 66, sel_a_b((g_statistics_type="XST"), 88, 83));  -- based on g_statistics_type: 'S'=0x53="SST", 'B'=0x42="BST", 'X'=0x58="XST"
+  CONSTANT c_nof_statistics_per_packet  : NATURAL  := 0;
+  CONSTANT c_data_size                  : NATURAL  := 2;
+  CONSTANT c_step_size                  : NATURAL  := 4;
+  CONSTANT c_nof_data                   : NATURAL  := 512;
+  CONSTANT c_block_size                 : NATURAL  := c_nof_data * c_data_size * (c_step_size / c_data_size);
+  CONSTANT c_nof_streams                : NATURAL  := 1;
+  CONSTANT c_nof_signal_inputs          : NATURAL  := sel_a_b(g_statistics_type="BST", 0, sel_a_b(g_statistics_type="XST", c_sdp_S_pn, 1));
+  CONSTANT c_nof_statistics_per_package : NATURAL := sel_a_b(g_statistics_type="BST", c_sdp_S_sub_bf, sel_a_b(g_statistics_type="XST", (c_sdp_S_pn*c_sdp_S_pn*c_nof_complex), c_sdp_N_sub));
+
+  CONSTANT c_beamlet_id                 : NATURAL := g_beamset_id * c_sdp_S_sub_bf;
+
+  TYPE t_reg IS RECORD
+    block_count    : NATURAL;
+    start_address  : NATURAL;
+    start_pulse    : STD_LOGIC;
+    dp_header_info : STD_LOGIC_VECTOR(1023 DOWNTO 0);
+    data_id        : STD_LOGIC_VECTOR(31 DOWNTO 0);
+  END RECORD;
+
+  CONSTANT c_reg_rst : t_reg := (0, 0, '0', (OTHERS => '0'), (OTHERS => '0'));
+
+  SIGNAL r : t_reg;
+  SIGNAL d : t_reg;
+
+  SIGNAL m_mosi : t_mem_mosi;
+  SIGNAL m_miso : t_mem_miso;
+  SIGNAL trigger                  : STD_LOGIC := '0';
+  SIGNAL nof_cycles_dly           : NATURAL   := 0;
+  SIGNAL mm_done                  : STD_LOGIC := '0';
+  SIGNAL start_addr               : NATURAL   := 0;
+  SIGNAL start_pulse              : STD_LOGIC := '0';
+  SIGNAL dp_block_from_mm_src_out : t_dp_sosi;
+  SIGNAL dp_block_from_mm_src_in  : t_dp_siso;
+  
+  SIGNAL dp_header_info           : STD_LOGIC_VECTOR(1023 DOWNTO 0):= (OTHERS => '0');
+  SIGNAL payload_err              : STD_LOGIC := '0';
+  SIGNAL integration_interval_cnt : NATURAL   := 0;
+  SIGNAL integration_interval     : STD_LOGIC_VECTOR(24-1 DOWNTO 0) := (OTHERS => '0');
+  SIGNAL bsn_at_sync              : STD_LOGIC_VECTOR(64-1 DOWNTO 0) := (OTHERS => '0');
+
+  SIGNAL sdp_data_id : STD_LOGIC_VECTOR(32-1 DOWNTO 0);
+
+  -------------------------------------------------------------------------------
+  -- dp_offload_tx
+  -------------------------------------------------------------------------------
+  CONSTANT c_nof_hdr_fields : NATURAL := 3+12+4+20+1; -- 592b; 9.25 64b words
+  -- c_hdr_field_sel for each field: 0=data path, 1=MM controlled
+  CONSTANT c_hdr_field_sel  : STD_LOGIC_VECTOR(c_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111001"&"0111"&"00000000000000000000"&"0";  -- TODO
+
+  CONSTANT c_hdr_field_arr : t_common_field_arr(c_nof_hdr_fields-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac"                             ), "RW", 48, field_default(x"00074306C700") ), -- 00074306C700=DOP36-eth0 
+                                                                                  ( field_name_pad("eth_src_mac"                             ), "RW", 48, field_default(0) ),
+                                                                                  ( field_name_pad("eth_type"                                ), "RO", 16, field_default(x"0800") ),
+
+                                                                                  ( field_name_pad("ip_version"                              ), "RO",  4, field_default(4) ),
+                                                                                  ( field_name_pad("ip_header_length"                        ), "RO",  4, field_default(5) ),
+                                                                                  ( field_name_pad("ip_services"                             ), "RO",  8, field_default(0) ),
+                                                                                  ( field_name_pad("ip_total_length"                         ), "RO", 16, field_default(7868) ), 
+                                                                                  ( field_name_pad("ip_identification"                       ), "RO", 16, field_default(0) ),
+                                                                                  ( field_name_pad("ip_flags"                                ), "RO",  3, field_default(2) ),
+                                                                                  ( field_name_pad("ip_fragment_offset"                      ), "RO", 13, field_default(0) ),
+                                                                                  ( field_name_pad("ip_time_to_live"                         ), "RO",  8, field_default(127) ),
+                                                                                  ( field_name_pad("ip_protocol"                             ), "RO",  8, field_default(17) ),
+                                                                                  ( field_name_pad("ip_header_checksum"                      ), "RW", 16, field_default(0) ),
+                                                                                  ( field_name_pad("ip_src_addr"                             ), "RW", 32, field_default(0) ),
+                                                                                  ( field_name_pad("ip_dst_addr"                             ), "RW", 32, field_default(x"C0A80001") ), -- C0A80001=DOP36-eth0 '192.168.0.1'
+                                                                                  
+                                                                                  ( field_name_pad("udp_src_port"                            ), "RW", 16, field_default(0) ), 
+                                                                                  ( field_name_pad("udp_dst_port"                            ), "RW", 16, field_default(0) ), 
+                                                                                  ( field_name_pad("udp_total_length"                        ), "RO", 16, field_default(7848) ), 
+                                                                                  ( field_name_pad("udp_checksum"                            ), "RO", 16, field_default(0) ),
+                                                                                  
+                                                                                  ( field_name_pad("sdp_marker"                              ), "RO",  8, field_default(c_marker) ),
+                                                                                  ( field_name_pad("sdp_version_id"                          ), "RO",  8, field_default(c_version) ),
+                                                                                  ( field_name_pad("sdp_observation_id"                      ), "RW", 32, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_station_id"                          ), "RW", 16, field_default(0) ),
+                                                                                  
+                                                                                  ( field_name_pad("sdp_source_info_antenna_band_id"         ), "RW",  1, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_source_info_nyquist_zone_id"         ), "RW",  2, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_source_info_f_adc"                   ), "RW",  1, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_source_info_fsub_type"               ), "RW",  1, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_source_info_payload_error"           ), "RW",  1, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_source_info_beam_repositioning_flag" ), "RW",  1, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_source_info_subband_calibrated_flag" ), "RW",  1, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_source_info_reserved"                ), "RO",  3, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_source_info_gn_id"                   ), "RW",  5, field_default(0) ),
+                                                                                  
+                                                                                  ( field_name_pad("sdp_reserved"                            ), "RO",  8, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_integration_interval"                ), "RW", 24, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_data_id"                             ), "RW", 32, field_default(0) ),
+                                                                                  ( field_name_pad("sdp_nof_signal_inputs"                   ), "RO",  8, field_default(c_nof_signal_inputs) ),
+                                                                                  ( field_name_pad("sdp_nof_bytes_per_statistics"            ), "RO",  8, field_default(8) ),
+                                                                                  ( field_name_pad("sdp_nof_statistics_per_package"          ), "RO", 16, field_default(c_nof_statistics_per_package) ),
+                                                                                  ( field_name_pad("sdp_block_period"                        ), "RO", 16, field_default(5120) ),
+                                         
+                                                                                  ( field_name_pad("dp_bsn"                                  ), "RW", 64, field_default(0) ) );
+
+BEGIN
+  
+  m_mosi <= master_mosi;
+  master_miso <= m_miso; 
+
+  -- count number of sop's in a sync interval
+  p_bsn_at_sync : PROCESS(in_sosi)
+  BEGIN
+    IF in_sosi.sync = '1' THEN
+      bsn_at_sync <= in_sosi.bsn(63 DOWNTO 0);
+    END IF;
+  END PROCESS;
+
+  -- count number of sop's in a sync interval
+  p_integration_interval : PROCESS(in_sosi)
+    VARIABLE cnt : NATURAL;
+  BEGIN
+    cnt := integration_interval_cnt;
+    IF in_sosi.sync = '1' THEN
+      integration_interval <= TO_UVEC(cnt, integration_interval'LENGTH);
+      integration_interval_cnt <= 0;
+    ELSE
+      IF in_sosi.sop = '1' THEN
+        integration_interval_cnt <= cnt + 1;
+      END IF;
+    END IF;
+  END PROCESS;
+
+  -- get payload errors and keep them till next sync
+  p_payload_error : PROCESS(in_sosi)
+    VARIABLE err : STD_LOGIC;
+  BEGIN
+    err := payload_err;
+    IF in_sosi.sync = '1' THEN
+      payload_err <= '0';
+    ELSE
+      payload_err <= err OR in_sosi.err(0);
+    END IF;
+  END PROCESS;
+
+
+  -------------------------------------------------------------------------------
+  -- Assemble offload info
+  -------------------------------------------------------------------------------
+  dp_header_info(field_hi(c_hdr_field_arr, "eth_src_mac" ) DOWNTO field_lo(c_hdr_field_arr, "eth_src_mac" )) <= eth_src_mac;
+  dp_header_info(field_hi(c_hdr_field_arr, "udp_src_port") DOWNTO field_lo(c_hdr_field_arr, "udp_src_port")) <= udp_src_port;
+  dp_header_info(field_hi(c_hdr_field_arr, "ip_src_addr" ) DOWNTO field_lo(c_hdr_field_arr, "ip_src_addr" )) <= ip_src_addr;
+  
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_observation_id"                      ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_observation_id"                      )) <= sdp_info.observation_id;
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_station_id"                          ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_station_id"                          )) <= sdp_info.station_id;
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_antenna_band_id"         ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_source_info_antenna_band_id"         )) <= SLV(sdp_info.antenna_band_index);
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_nyquist_zone_id"         ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_source_info_nyquist_zone_id"         )) <= sdp_info.nyquist_zone_index;
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_f_adc"                   ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_source_info_f_adc"                   )) <= SLV(sdp_info.f_adc);
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_fsub_type"               ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_source_info_fsub_type"               )) <= SLV(sdp_info.fsub_type);
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_payload_error"           ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_source_info_payload_error"           )) <= SLV(payload_err);
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_beam_repositioning_flag" ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_source_info_beam_repositioning_flag" )) <= SLV(sdp_info.beam_repositioning_flag);
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_subband_calibrated_flag" ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_source_info_subband_calibrated_flag" )) <= SLV(sdp_info.subband_calibrated_flag);
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_reserved"                ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_source_info_reserved"                )) <= (OTHERS => '0');
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_source_info_gn_id"                   ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_source_info_gn_id"                   )) <= TO_UVEC(gn_index, 5);
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_reserved"                            ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_reserved"                            )) <= (OTHERS => '0');
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_integration_interval"                ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_integration_interval"                )) <= integration_interval;
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_data_id"                             ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_data_id"                             )) <= sdp_data_id;
+  dp_header_info(field_hi(c_hdr_field_arr, "sdp_block_period"                        ) DOWNTO field_lo(c_hdr_field_arr,  "sdp_block_period"                        )) <= sdp_info.block_period;
+
+  dp_header_info(field_hi(c_hdr_field_arr, "dp_bsn"                                  ) DOWNTO field_lo(c_hdr_field_arr,  "dp_bsn"                                   )) <= bsn_at_sync; 
+
+
+
+  nof_cycles_dly <= gn_index * g_offload_time;
+  sdp_data_id    <= r.data_id;
+
+  p_reg : PROCESS(dp_rst, dp_clk)
+  BEGIN
+    IF dp_rst='1' THEN
+      r <= c_reg_rst;
+    ELSIF rising_edge(dp_clk) THEN
+      r <= d;
+    END IF;
+  END PROCESS;
+
+
+  p_control_packet_offload : PROCESS(r, trigger, mm_done)
+  BEGIN
+    d <= r;
+    
+    -- assign sdp_data_id for different statistic types
+    IF g_statistics_type = "SST" THEN
+      d.data_id <= x"000000" & TO_UVEC(r.block_count, 8);
+    ELSIF g_statistics_type = "BST" THEN
+      d.data_id <= x"0000" & TO_UVEC(c_beamlet_id, 24);
+    ELSIF g_statistics_type = "XST" THEN
+      d.data_id <= x"00" & TO_UVEC(0, 8) & TO_UVEC(0, 8) & TO_UVEC(0, 8);  -- TODO fill fill in right values.
+    ELSE
+      d.data_id <= x"00000000";
+    END IF;
+
+    IF trigger = '1' OR mm_done = '1' THEN
+      d.block_count <= r.block_count + 1;
+      IF (r.block_count + 1) mod 2 = 0 THEN
+        d.start_address <= d.block_count / 2 * c_block_size;
+      ELSE 
+        d.start_address <= r.start_address + c_data_size; 
+      END IF;
+      d.start_pulse <= '1';
+    END IF;
+
+    IF mm_done = '1' THEN
+      d.dp_header_info <= dp_header_info;
+    END IF;
+    
+    IF d.block_count >= c_sdp_S_pn THEN
+      d.block_count   <= 0;
+      d.start_address <= 0; 
+    END IF;
+
+  END PROCESS;
+    
+
+  u_mms_common_variable_delay : ENTITY common_lib.mms_common_variable_delay
+  GENERIC MAP (
+    g_max_delay => 1 
+  )
+  PORT MAP (
+    mm_rst => mm_rst,
+    mm_clk => mm_clk,
+    dp_rst => dp_rst,
+    dp_clk => dp_clk,
+
+    -- MM interface
+    reg_enable_mosi => reg_enable_mosi,
+    reg_enable_miso => reg_enable_miso,
+
+    delay           => nof_cycles_dly,
+    trigger         => in_sosi.sync,
+    trigger_dly     => trigger
+  );
+  
+  u_dp_block_from_mm : ENTITY dp_lib.dp_block_from_mm
+  GENERIC MAP (
+    g_data_size => c_data_size,
+    g_step_size => c_step_size,
+    g_nof_data  => c_nof_data
+  ) 
+  PORT MAP(
+    rst           => mm_rst,
+    clk           => mm_clk,
+    start_pulse   => r.start_pulse,
+    start_address => r.start_address,
+    mm_done       => mm_done,
+    mm_mosi       => m_mosi,
+    mm_miso       => m_miso,
+    out_sosi      => dp_block_from_mm_src_out,
+    out_siso      => dp_block_from_mm_src_in
+  );
+
+  u_dp_offload_tx_v3: ENTITY dp_lib.dp_offload_tx_v3
+  GENERIC MAP (
+    g_nof_streams   => c_nof_streams,
+    g_data_w        => c_word_w,
+    g_symbol_w      => c_byte_w,
+    g_hdr_field_arr => c_hdr_field_arr,
+    g_hdr_field_sel => c_hdr_field_sel
+  )
+  PORT MAP(
+    mm_rst               => mm_rst,
+    mm_clk               => mm_clk,
+    dp_rst               => dp_rst,
+    dp_clk               => dp_clk,
+    reg_hdr_dat_mosi     => reg_hdr_dat_mosi,
+    reg_hdr_dat_miso     => reg_hdr_dat_miso,
+    snk_in_arr(0)        => dp_block_from_mm_src_out,
+    snk_out_arr(0)       => dp_block_from_mm_src_in,
+    src_out_arr(0)       => out_sosi,
+    hdr_fields_in_arr(0) => r.dp_header_info -- hdr_fields_in_arr(i) is considered valid @ snk_in_arr(i).sop
+  );
+END str;
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
new file mode 100644
index 0000000000000000000000000000000000000000..0f95f9a467771a3254ac791b060cee4769931b32
--- /dev/null
+++ b/applications/lofar2/libraries/sdp/tb/vhdl/tb_sdp_statistics_offload.vhd
@@ -0,0 +1,246 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2020
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+--
+-- Author: P. Donker
+
+-- Purpose:
+-- . test bench for sdp_info.vhd (and sdp_info_reg.vhd)
+-- Description:
+--
+-- https://plm.astron.nl/polarion/#/project/LOFAR2System/workitem?id=LOFAR2-9258
+-- https://plm.astron.nl/polarion/#/project/LOFAR2System/workitem?id=LOFAR2-8855
+--
+-- Remark:
+-- .
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL; 
+USE common_lib.tb_common_mem_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE work.sdp_pkg.ALL;
+
+
+ENTITY tb_sdp_statistics_offload IS
+  GENERIC (
+    g_statistics_type : STRING := "SST";
+    g_nof_signal_inputs_per_pn : NATURAL := 4
+  );
+END tb_sdp_statistics_offload;
+
+ARCHITECTURE tb OF tb_sdp_statistics_offload IS
+  CONSTANT c_dp_clk_period        : TIME := 5 ns;     -- 200 MHz
+  CONSTANT c_mm_clk_period        : TIME := 20 ns;    -- 50 MHz
+
+  CONSTANT c_cross_clock_domain_latency : NATURAL := 40;
+  
+  CONSTANT c_eth_src_mac  : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := x"123456789ABC";
+  CONSTANT c_udp_src_port : STD_LOGIC_VECTOR(c_network_udp_port_w-1 DOWNTO 0) := x"D001";
+  CONSTANT c_ip_src_addr  : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0) := x"0A090807";
+
+  -- used mm_adresses on mm bus
+  CONSTANT c_mm_addr_enable   : NATURAL := 0;
+  
+  -- used test ram size: c_block_size = c_nof_data * c_data_size * (c_step_size / c_data_size) => 512 * 2 * (4 / 2) = 2048 words per pair of signal inputs;
+  -- with 12 signal input, 6 pairs (blocks) we will fill 2 blocks for testing 2 * 2048 = 4096 = 
+  CONSTANT c_nof_data  : NATURAL := 512;
+  CONSTANT c_data_size : NATURAL := 2;
+  CONSTANT c_step_size : NATURAL := 4;
+  CONSTANT c_ram_size  : NATURAL := c_nof_data * c_data_size * g_nof_signal_inputs_per_pn;
+  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');
+
+  SIGNAL tb_end              : STD_LOGIC := '0';
+  SIGNAL tb_mm_reg_end       : STD_LOGIC := '0';
+
+  SIGNAL dp_clk              : STD_LOGIC := '1';   -- digital data path clock = 200 MHz (deser factor 4);
+  SIGNAL dp_rst              : STD_LOGIC;
+
+  SIGNAL mm_clk              : STD_LOGIC := '1';   -- MM control clock = 50 MHz
+  SIGNAL mm_rst              : STD_LOGIC;
+  
+  SIGNAL master_mosi         : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL master_miso         : t_mem_miso;
+
+  SIGNAL enable_mosi : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL enable_miso : t_mem_miso;
+
+  SIGNAL hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL hdr_dat_miso : t_mem_miso;
+
+  SIGNAL in_sosi             : t_dp_sosi := c_dp_sosi_rst;
+  SIGNAL out_sosi            : t_dp_sosi;
+
+  -- signals used to change settings of sdp_info 
+  SIGNAL gn_index  : NATURAL   := 15; 
+  SIGNAL f_adc     : STD_LOGIC := '0'; 
+  SIGNAL fsub_type : STD_LOGIC := '0';
+
+  SIGNAL sdp_info  : t_sdp_info; 
+
+  -- signals used for response of mm bus
+  SIGNAL mm_natural_response : NATURAL;
+
+  -- signals used for starting processes
+  SIGNAL wr_data      : STD_LOGIC_VECTOR(c_ram_buf.dat_w-1 DOWNTO 0);
+  SIGNAL wr_addr      : STD_LOGIC_VECTOR(c_ram_buf.adr_w-1 DOWNTO 0);
+  SIGNAL wr_en        : STD_LOGIC;
+  SIGNAL init_ram_done: STD_LOGIC := '0';
+
+BEGIN
+  dp_rst <= '1', '0' AFTER c_dp_clk_period*7;
+  dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2;
+  
+  mm_rst <= '1', '0' AFTER c_mm_clk_period*7;
+  mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2;
+
+  
+  -- fill ram with data, data is same as address number.
+  p_mm_statistics_ram : PROCESS
+    VARIABLE addr_cnt : NATURAL := 0;
+  BEGIN
+    wr_en <= '0';
+    -- initialyze
+    proc_common_wait_until_low(mm_clk, mm_rst);
+    proc_common_wait_some_cycles(mm_clk, 10);
+
+    FOR i IN 0 TO c_ram_buf.nof_dat-1 LOOP
+      wr_addr <= TO_UVEC(addr_cnt, c_ram_buf.adr_w);
+      wr_data <= TO_UVEC(addr_cnt, c_ram_buf.dat_w);
+      wr_en   <= '1';
+      proc_common_wait_some_cycles(dp_clk, 1);
+      addr_cnt := addr_cnt + 1;
+    END LOOP; 
+    wr_en <= '0';
+    
+    init_ram_done <= '1'; 
+    WAIT;
+  END PROCESS;
+
+  p_in_sosi : PROCESS
+  BEGIN
+    proc_common_wait_until_high(dp_clk, init_ram_done);
+    -- enable common variabel delay
+    proc_mem_mm_bus_wr(c_mm_addr_enable, 1, mm_clk, enable_miso, enable_mosi);
+    proc_common_wait_some_cycles(mm_clk, c_cross_clock_domain_latency);
+    FOR i IN 0 TO g_nof_signal_inputs_per_pn LOOP
+      in_sosi.sync  <= '1';
+      in_sosi.valid <= '1';
+      in_sosi.sop   <= '1';                 
+      proc_common_wait_some_cycles(dp_clk, 1);
+      in_sosi.sync  <= '0';
+      in_sosi.sop   <= '0';
+      proc_common_wait_some_cycles(dp_clk, c_nof_data*c_data_size);                 
+      in_sosi.eop   <= '1';                 
+      proc_common_wait_some_cycles(dp_clk, 1);
+      in_sosi.eop   <= '0';
+      in_sosi.valid <= '0';
+      proc_common_wait_some_cycles(dp_clk, 1);
+    END LOOP;
+    WAIT;
+  END PROCESS;
+
+  p_mm_reg_stimuli : PROCESS
+  BEGIN
+    --enable_mosi  <= c_mem_mosi_rst;
+    --hdr_dat_mosi <= c_mem_mosi_rst;
+
+    proc_common_wait_until_high(dp_clk, init_ram_done);
+    proc_common_wait_some_cycles(mm_clk, 100);
+
+    -- station_id, antenna_band_index, observation_id, nyquist_zone_index, f_adc, fsub_type, beam_repositioning_flag, subband_calibrated_flag, O_si, N_si, O_rn, N_rn, block_period, beamlet_scale
+    sdp_info <= ( x"0001", '0', x"00000003", b"01", '0', '0', '0', '0', x"00", x"00", x"00", x"00", x"0000", x"0000");
+    proc_common_wait_some_cycles(mm_clk, 1);
+    out_sosi.sync <= '1';
+
+    proc_common_wait_some_cycles(mm_clk, 100);
+    tb_end <= '1';
+    WAIT;
+  END PROCESS;
+
+  
+  u_ram: ENTITY common_lib.common_ram_crw_crw_ratio
+  GENERIC MAP (
+    g_ram_a => c_ram_buf,  -- settings for port a
+    g_ram_b => c_ram_buf  -- settings for port b
+  )
+  PORT MAP (
+    -- MM read/write port clock domain
+    rst_a    => mm_rst,
+    clk_a    => mm_clk,
+    wr_en_a  => master_mosi.wr,
+    wr_dat_a => master_mosi.wrdata(c_ram_buf.dat_w-1 DOWNTO 0),
+    adr_a    => master_mosi.address(c_ram_buf.adr_w-1 DOWNTO 0),
+    rd_en_a  => master_mosi.rd,
+    rd_dat_a => master_miso.rddata(c_ram_buf.dat_w-1 DOWNTO 0),
+    rd_val_a => master_miso.rdval,
+
+    -- ST write only port clock domain
+    rst_b     => dp_rst,
+    clk_b     => dp_clk,
+    wr_en_b   => wr_en,
+    wr_dat_b  => wr_data,
+    adr_b     => wr_addr,
+    rd_en_b   => '0',
+    rd_dat_b  => OPEN,
+    rd_val_b  => OPEN
+  ); 
+
+  -- SDP info
+  u_dut: ENTITY work.sdp_statistics_offload
+  GENERIC MAP (
+    g_statistics_type => "SST",
+    g_offload_time    => 0,
+    g_beamset_id      => 0
+  )
+  PORT MAP (
+    mm_clk    => mm_clk,
+    mm_rst    => mm_rst,
+
+    dp_clk    => dp_clk,
+    dp_rst    => dp_rst,
+
+    master_mosi => master_mosi,
+    master_miso => master_miso,
+
+    reg_enable_mosi  => enable_mosi,
+    reg_enable_miso  => enable_miso,
+
+    reg_hdr_dat_mosi  => hdr_dat_mosi,
+    reg_hdr_dat_miso  => hdr_dat_miso,
+
+    sdp_info  => sdp_info,
+    gn_index  => gn_index,
+
+    in_sosi   => in_sosi,
+    out_sosi  => out_sosi,
+
+    eth_src_mac  => c_eth_src_mac,
+    udp_src_port => c_udp_src_port,
+    ip_src_addr  => c_ip_src_addr
+  );
+
+END tb;
\ No newline at end of file