diff --git a/applications/rdma_demo/libraries/rdma_packetiser/hdllib.cfg b/applications/rdma_demo/libraries/rdma_packetiser/hdllib.cfg
index c449e83d95a91ecdf4244a1e792bbbc7ca5316ae..70a9f1437ef434bb1c44fe5f959ffb0cf9e57f7f 100644
--- a/applications/rdma_demo/libraries/rdma_packetiser/hdllib.cfg
+++ b/applications/rdma_demo/libraries/rdma_packetiser/hdllib.cfg
@@ -1,12 +1,13 @@
 hdl_lib_name = rdma_packetiser
 hdl_library_clause_name = rdma_packetiser_lib
-hdl_lib_uses_synth = common dp eth 
+hdl_lib_uses_synth = common dp eth rdma_icrc_external
 hdl_lib_uses_sim = diag technology
 hdl_lib_technology = 
 
 synth_files =
     src/vhdl/rdma_packetiser_pkg.vhd
     src/vhdl/rdma_packetiser_assemble_header.vhd
+    src/vhdl/rdma_packetiser.vhd
 
 test_bench_files = 
     tb/vhdl/tb_rdma_packetiser_assemble_header.vhd
diff --git a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser.vhd b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..462ff07b7e61f46855866a901d076d990c9c527d
--- /dev/null
+++ b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser.vhd
@@ -0,0 +1,200 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2024
+-- 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: R. van der Walle
+-- Purpose: Packetizes an incoming data stream as RDMA "WRITE" packets.
+-- Description: see https://support.astron.nl/confluence/x/urT-Bg
+-- 
+library IEEE, common_lib, dp_lib, eth_lib, rdma_icrc_external_lib;
+use IEEE.std_logic_1164.all;
+use common_lib.common_pkg.all;
+use common_lib.common_mem_pkg.all;
+use common_lib.common_network_layers_pkg.all;
+use dp_lib.dp_stream_pkg.all;
+use dp_lib.dp_components_pkg.all;
+use eth_lib.eth_pkg.all;
+use eth_lib.eth_tester_pkg.all;
+
+entity rdma_packetiser is
+  generic (
+    g_cross_clock_domain : boolean := false;
+    g_sync_timeout       : natural := c_dp_sync_timeout
+  );
+  port (
+    -- Clocks and reset
+    dp_clk             : in  std_logic;
+    dp_rst             : in  std_logic;
+
+    mm_clk             : in  std_logic;
+    mm_rst             : in  std_logic;
+
+    reg_hdr_dat_copi   : in  t_mem_copi := c_mem_copi_rst;
+    reg_hdr_dat_cipo   : out t_mem_cipo;
+
+    reg_bsn_monitor_v2_rdma_packetiser_input_copi  : in  t_mem_copi := c_mem_copi_rst;
+    reg_bsn_monitor_v2_rdma_packetiser_input_cipo  : out t_mem_cipo;
+    reg_bsn_monitor_v2_rdma_packetiser_output_copi : in  t_mem_copi := c_mem_copi_rst;
+    reg_bsn_monitor_v2_rdma_packetiser_output_cipo : out t_mem_cipo;
+
+    snk_in             : in  t_dp_sosi := c_dp_sosi_rst;
+    snk_out            : out t_dp_siso := c_dp_siso_rdy;
+
+    src_out            : out t_dp_sosi := c_dp_sosi_rst;
+    src_in             : in  t_dp_siso := c_dp_siso_rdy;
+
+    block_len          : in  std_logic_vector(c_halfword_w - 1 downto 0) -- in octets
+  );
+end rdma_packetiser;
+
+architecture str of rdma_packetiser is
+  constant c_nof_byte        : natural := 64;
+  constant c_data_w          : natural := c_nof_byte * c_byte_w;
+  constant c_max_packet_size : natural := ceil_div(9000, c_nof_byte);
+
+  signal dp_xonoff_sosi       : t_dp_sosi := c_dp_sosi_rst;
+  signal dp_xonoff_siso       : t_dp_siso := c_dp_siso_rdy;
+  signal dp_fifo_data_sosi    : t_dp_sosi := c_dp_sosi_rst;
+  signal dp_fifo_data_siso    : t_dp_siso := c_dp_siso_rdy;
+  signal assemble_header_sosi : t_dp_sosi := c_dp_sosi_rst;
+  signal assemble_header_siso : t_dp_siso := c_dp_siso_rdy;
+  signal icrc_sosi            : t_dp_sosi := c_dp_sosi_rst;
+  signal icrc_siso            : t_dp_siso := c_dp_siso_rdy;
+
+begin
+  -- dp_xonoff to prevent fifo overflow
+  u_dp_xonoff : entity dp_lib.dp_xonoff
+  port map (
+    rst      => dp_rst,
+    clk      => dp_clk,
+
+    in_siso  => snk_out,
+    in_sosi  => snk_in,
+    out_siso => dp_xonoff_siso,
+    out_sosi => dp_xonoff_sosi
+  );
+
+  -- dp_fifo_fill_eop
+  u_dp_fifo_data : entity dp_lib.dp_fifo_fill_eop_sc
+  generic map (
+    g_data_w         => c_data_w,
+    g_empty_w        => c_byte_w,
+    g_bsn_w          => 64,
+    g_use_empty      => true,
+    g_use_bsn        => true,
+    g_use_sync       => true,
+    g_fifo_size      => c_max_packet_size * 2,
+    g_fifo_fill      => c_max_packet_size,
+    g_fifo_rl        => 1,
+    g_fifo_af_margin => 0,
+    g_fifo_af_xon    => 0
+  )
+  port map (
+    clk     => dp_clk,
+    rst     => dp_rst,
+    snk_in  => dp_xonoff_sosi,
+    snk_out => dp_xonoff_siso,
+    src_out => dp_fifo_data_sosi,
+    src_in  => dp_fifo_data_siso
+  );
+
+  -- mms_dp_bsn_monitor_v2
+  u_bsn_mon_input : entity dp_lib.mms_dp_bsn_monitor_v2
+  generic map (
+    g_nof_streams        => 1,
+    g_cross_clock_domain => g_cross_clock_domain,
+    g_sync_timeout       => g_sync_timeout
+  )
+  port map (
+    -- Memory-mapped clock domain
+    mm_rst         => mm_rst,
+    mm_clk         => mm_clk,
+    reg_mosi       => reg_bsn_monitor_v2_rdma_packetiser_input_copi,
+    reg_miso       => reg_bsn_monitor_v2_rdma_packetiser_input_cipo,
+
+    -- Streaming clock domain
+    dp_rst         => dp_rst,
+    dp_clk         => dp_clk,
+    ref_sync       => snk_in.sync,
+
+    in_sosi_arr(0) => dp_fifo_data_sosi
+  );
+
+  u_rdma_assemble_header : entity work.rdma_packetiser_assemble_header
+  generic map (
+    g_data_w => c_data_w
+  )
+  port map (
+    -- Clocks and reset
+    mm_rst           => mm_rst,
+    mm_clk           => mm_clk,
+    st_rst           => dp_rst,
+    st_clk           => dp_clk,
+
+    -- Streaming interfaces
+    snk_in           => dp_fifo_data_sosi,
+    snk_out          => dp_fifo_data_siso,
+    src_out          => assemble_header_sosi,
+    src_in           => assemble_header_siso,
+
+    -- Memory Mapped Peripherals
+    reg_hdr_dat_copi => reg_hdr_dat_copi,
+    reg_hdr_dat_cipo => reg_hdr_dat_cipo,
+
+    -- block length in nof octets
+    block_len        => block_len
+  );
+
+  u_icrc_append : entity rdma_icrc_external_lib.append_crc_dp_wrapper
+  port map (
+    dp_clk => dp_clk,
+    dp_rst => dp_rst,
+
+    in_dp_sosi  => assemble_header_sosi,
+    in_dp_siso  => assemble_header_siso,
+
+    out_dp_sosi => icrc_sosi,
+    out_dp_siso => icrc_siso
+  );
+
+  -- mms_dp_bsn_monitor_v2
+  u_bsn_mon_output : entity dp_lib.mms_dp_bsn_monitor_v2
+  generic map (
+    g_nof_streams        => 1,
+    g_cross_clock_domain => g_cross_clock_domain,
+    g_sync_timeout       => g_sync_timeout
+  )
+  port map (
+    -- Memory-mapped clock domain
+    mm_rst         => mm_rst,
+    mm_clk         => mm_clk,
+    reg_mosi       => reg_bsn_monitor_v2_rdma_packetiser_output_copi,
+    reg_miso       => reg_bsn_monitor_v2_rdma_packetiser_output_cipo,
+
+    -- Streaming clock domain
+    dp_rst         => dp_rst,
+    dp_clk         => dp_clk,
+    ref_sync       => snk_in.sync,
+
+    in_sosi_arr(0) => icrc_sosi
+  );
+
+  src_out <= icrc_sosi;
+  icrc_siso <= src_in;
+
+end str;
diff --git a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_assemble_header.vhd b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_assemble_header.vhd
index a71c4922a3629945ec991744097b1c3c73546024..9ab165aaf994a8e9caed130beacc04ccc208eec4 100644
--- a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_assemble_header.vhd
+++ b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_assemble_header.vhd
@@ -120,9 +120,10 @@ architecture str of rdma_packetiser_assemble_header is
     ip_total_length    : natural;
     nof_packets_in_msg : natural;
     sel_ctrl           : natural range 0 to c_nof_offload - 1;
+    sel_ctrl_delayed   : natural range 0 to c_nof_offload - 1;
   end record;
 
-  constant c_reg_rst : t_reg := (s_first, (others => '1'), (others => '0'), (others => '0'), (others => '0'), 0, 0, 0, 0, 0, 0);
+  constant c_reg_rst : t_reg := (s_first, (others => '1'), (others => '0'), (others => '0'), (others => '0'), 0, 0, 0, 0, 0, 0, 0);
   signal d, q : t_reg;
 
   signal use_immediate            : std_logic;
@@ -144,22 +145,22 @@ architecture str of rdma_packetiser_assemble_header is
   signal dp_demux_src_in_arr      : t_dp_siso_arr(c_nof_offload - 1 downto 0) := (others => c_dp_siso_rdy);
   signal dp_mux_snk_in_arr        : t_dp_sosi_arr(c_nof_offload - 1 downto 0) := (others => c_dp_sosi_rst);
   signal dp_mux_snk_out_arr       : t_dp_siso_arr(c_nof_offload - 1 downto 0) := (others => c_dp_siso_rdy);
-  signal dp_offload_first_snk_in  : t_dp_sosi := c_dp_sosi_rst;
-  signal dp_offload_first_snk_out : t_dp_siso := c_dp_siso_rdy;
-  signal dp_offload_first_src_out : t_dp_sosi := c_dp_sosi_rst;
-  signal dp_offload_first_src_in  : t_dp_siso := c_dp_siso_rdy;
-  signal dp_offload_mid_snk_in    : t_dp_sosi := c_dp_sosi_rst;
-  signal dp_offload_mid_snk_out   : t_dp_siso := c_dp_siso_rdy;
-  signal dp_offload_mid_src_out   : t_dp_sosi := c_dp_sosi_rst;
-  signal dp_offload_mid_src_in    : t_dp_siso := c_dp_siso_rdy;
-  signal dp_offload_last_snk_in   : t_dp_sosi := c_dp_sosi_rst;
-  signal dp_offload_last_snk_out  : t_dp_siso := c_dp_siso_rdy;
-  signal dp_offload_last_src_out  : t_dp_sosi := c_dp_sosi_rst;
-  signal dp_offload_last_src_in   : t_dp_siso := c_dp_siso_rdy;
-  signal dp_offload_wo_snk_in     : t_dp_sosi := c_dp_sosi_rst;
-  signal dp_offload_wo_snk_out    : t_dp_siso := c_dp_siso_rdy;
-  signal dp_offload_wo_src_out    : t_dp_sosi := c_dp_sosi_rst;
-  signal dp_offload_wo_src_in     : t_dp_siso := c_dp_siso_rdy;
+  signal eth_ip_offload_first_snk_in  : t_dp_sosi := c_dp_sosi_rst;
+  signal eth_ip_offload_first_snk_out : t_dp_siso := c_dp_siso_rdy;
+  signal eth_ip_offload_first_src_out : t_dp_sosi := c_dp_sosi_rst;
+  signal eth_ip_offload_first_src_in  : t_dp_siso := c_dp_siso_rdy;
+  signal eth_ip_offload_mid_snk_in    : t_dp_sosi := c_dp_sosi_rst;
+  signal eth_ip_offload_mid_snk_out   : t_dp_siso := c_dp_siso_rdy;
+  signal eth_ip_offload_mid_src_out   : t_dp_sosi := c_dp_sosi_rst;
+  signal eth_ip_offload_mid_src_in    : t_dp_siso := c_dp_siso_rdy;
+  signal eth_ip_offload_last_snk_in   : t_dp_sosi := c_dp_sosi_rst;
+  signal eth_ip_offload_last_snk_out  : t_dp_siso := c_dp_siso_rdy;
+  signal eth_ip_offload_last_src_out  : t_dp_sosi := c_dp_sosi_rst;
+  signal eth_ip_offload_last_src_in   : t_dp_siso := c_dp_siso_rdy;
+  signal eth_ip_offload_wo_snk_in     : t_dp_sosi := c_dp_sosi_rst;
+  signal eth_ip_offload_wo_snk_out    : t_dp_siso := c_dp_siso_rdy;
+  signal eth_ip_offload_wo_src_out    : t_dp_sosi := c_dp_sosi_rst;
+  signal eth_ip_offload_wo_src_in     : t_dp_siso := c_dp_siso_rdy;
   signal dp_pipeline_src_out      : t_dp_sosi := c_dp_sosi_rst;
 
 begin
@@ -177,6 +178,7 @@ begin
     variable v : t_reg;
   begin
     v := q;
+    v.sel_ctrl_delayed := q.sel_ctrl;
     if snk_in.sop = '1' then
       v.psn := resize_uvec(snk_in.bsn, c_word_w);
       v.p_cnt := q.p_cnt + 1;
@@ -265,7 +267,7 @@ begin
   hdr_fields_slv_in(field_hi(c_rdma_packetiser_mm_field_arr, "reth_dma_length"     ) downto field_lo(c_rdma_packetiser_mm_field_arr, "reth_dma_length"     )) <= std_logic_vector(q.dma_len);
 
   -------------------------------------------------------------------------------
-  -- demux to guide the incoming stream to the correct dp_offload_tx_v3 
+  -- demux to guide the incoming stream to the correct eth_ip_offload_tx 
   -------------------------------------------------------------------------------
   u_dp_demux : entity dp_lib.dp_demux
   generic map (
@@ -289,16 +291,16 @@ begin
   );
 
   -- Wire demux outputs to dp_offload inputs.
-  dp_offload_first_snk_in <= dp_demux_src_out_arr(0);
-  dp_offload_mid_snk_in   <= dp_demux_src_out_arr(1);
-  dp_offload_last_snk_in  <= dp_demux_src_out_arr(2);
-  dp_offload_wo_snk_in    <= dp_demux_src_out_arr(3);
-  dp_demux_src_in_arr(0)  <= dp_offload_first_snk_out;
-  dp_demux_src_in_arr(1)  <= dp_offload_mid_snk_out;
-  dp_demux_src_in_arr(2)  <= dp_offload_last_snk_out;
-  dp_demux_src_in_arr(3)  <= dp_offload_wo_snk_out;
-
-  -- Wire header fields for every do_offload
+  eth_ip_offload_first_snk_in <= dp_demux_src_out_arr(0);
+  eth_ip_offload_mid_snk_in   <= dp_demux_src_out_arr(1);
+  eth_ip_offload_last_snk_in  <= dp_demux_src_out_arr(2);
+  eth_ip_offload_wo_snk_in    <= dp_demux_src_out_arr(3);
+  dp_demux_src_in_arr(0)  <= eth_ip_offload_first_snk_out;
+  dp_demux_src_in_arr(1)  <= eth_ip_offload_mid_snk_out;
+  dp_demux_src_in_arr(2)  <= eth_ip_offload_last_snk_out;
+  dp_demux_src_in_arr(3)  <= eth_ip_offload_wo_snk_out;
+
+  -- Wire header fields for every eth_ip_offload_tx
   p_wire_headers : process(hdr_fields_slv_out_mm, use_msg_cnt_as_immediate, q)
   begin
     -- set headers.
@@ -322,11 +324,10 @@ begin
                              field_lo(c_rdma_packetiser_wo_hdr_field_arr,   "immediate_data")) <= TO_UVEC(q.msg_cnt, 32);
     end if;
   end process;
-
   -------------------------------------------------------------------------------
   -- Header for first packets or write only without immediate data 
   -------------------------------------------------------------------------------
-  u_dp_offload_first : entity dp_lib.dp_offload_tx_v3
+  u_eth_ip_offload_first : entity eth_lib.eth_ip_offload_tx
   generic map (
     g_nof_streams    => 1,
     g_data_w         => g_data_w,
@@ -338,17 +339,17 @@ begin
   port map (
     dp_rst                => st_rst,
     dp_clk                => st_clk,
-    snk_in_arr(0)         => dp_offload_first_snk_in,
-    snk_out_arr(0)        => dp_offload_first_snk_out,
-    src_out_arr(0)        => dp_offload_first_src_out,
-    src_in_arr(0)         => dp_offload_first_src_in,
+    snk_in_arr(0)         => eth_ip_offload_first_snk_in,
+    snk_out_arr(0)        => eth_ip_offload_first_snk_out,
+    src_out_arr(0)        => eth_ip_offload_first_src_out,
+    src_in_arr(0)         => eth_ip_offload_first_src_in,
     hdr_fields_in_arr(0)  => hdr_fields_slv_in_first
   );
 
   -------------------------------------------------------------------------------
   -- Header for middle or last without immediate data (no RETH, no immediate data)
   -------------------------------------------------------------------------------
-  u_dp_offload_mid : entity dp_lib.dp_offload_tx_v3
+  u_eth_ip_offload_mid : entity eth_lib.eth_ip_offload_tx
   generic map (
     g_nof_streams    => 1,
     g_data_w         => g_data_w,
@@ -360,17 +361,17 @@ begin
   port map (
     dp_rst                => st_rst,
     dp_clk                => st_clk,
-    snk_in_arr(0)         => dp_offload_mid_snk_in,
-    snk_out_arr(0)        => dp_offload_mid_snk_out,
-    src_out_arr(0)        => dp_offload_mid_src_out,
-    src_in_arr(0)         => dp_offload_mid_src_in,
+    snk_in_arr(0)         => eth_ip_offload_mid_snk_in,
+    snk_out_arr(0)        => eth_ip_offload_mid_snk_out,
+    src_out_arr(0)        => eth_ip_offload_mid_src_out,
+    src_in_arr(0)         => eth_ip_offload_mid_src_in,
     hdr_fields_in_arr(0)  => hdr_fields_slv_in_mid
   );
 
   -------------------------------------------------------------------------------
   -- Header for last packets with immediate data
   -------------------------------------------------------------------------------
-  u_dp_offload_last : entity dp_lib.dp_offload_tx_v3
+  u_eth_ip_offload_last : entity eth_lib.eth_ip_offload_tx
   generic map (
     g_nof_streams    => 1,
     g_data_w         => g_data_w,
@@ -382,17 +383,17 @@ begin
   port map (
     dp_rst                => st_rst,
     dp_clk                => st_clk,
-    snk_in_arr(0)         => dp_offload_last_snk_in,
-    snk_out_arr(0)        => dp_offload_last_snk_out,
-    src_out_arr(0)        => dp_offload_last_src_out,
-    src_in_arr(0)         => dp_offload_last_src_in,
+    snk_in_arr(0)         => eth_ip_offload_last_snk_in,
+    snk_out_arr(0)        => eth_ip_offload_last_snk_out,
+    src_out_arr(0)        => eth_ip_offload_last_src_out,
+    src_in_arr(0)         => eth_ip_offload_last_src_in,
     hdr_fields_in_arr(0)  => hdr_fields_slv_in_last 
   );
 
   -------------------------------------------------------------------------------
   -- Header for write only packets with immediate data 
   -------------------------------------------------------------------------------
-  u_dp_offload_wo : entity dp_lib.dp_offload_tx_v3
+  u_eth_ip_offload_wo : entity eth_lib.eth_ip_offload_tx
   generic map (
     g_nof_streams    => 1,
     g_data_w         => g_data_w,
@@ -404,10 +405,10 @@ begin
   port map (
     dp_rst                => st_rst,
     dp_clk                => st_clk,
-    snk_in_arr(0)         => dp_offload_wo_snk_in,
-    snk_out_arr(0)        => dp_offload_wo_snk_out,
-    src_out_arr(0)        => dp_offload_wo_src_out,
-    src_in_arr(0)         => dp_offload_wo_src_in,
+    snk_in_arr(0)         => eth_ip_offload_wo_snk_in,
+    snk_out_arr(0)        => eth_ip_offload_wo_snk_out,
+    src_out_arr(0)        => eth_ip_offload_wo_src_out,
+    src_in_arr(0)         => eth_ip_offload_wo_src_in,
     hdr_fields_in_arr(0)  => hdr_fields_slv_in_wo
   );
 
@@ -419,7 +420,6 @@ begin
   port map (
     rst => st_rst,
     clk => st_clk,
-    snk_out => open,
     snk_in  => snk_in,
     src_out => dp_pipeline_src_out
   );
@@ -447,17 +447,17 @@ begin
   );
 
   -------------------------------------------------------------------------------
-  -- Mux to merge the packets from the different dp_offload_tx_v3
+  -- Mux to merge the packets from the different eth_ip_offload_tx
   -------------------------------------------------------------------------------
   -- Wire demux outputs to dp_offload inputs.
-  dp_mux_snk_in_arr(0)    <= dp_offload_first_src_out;
-  dp_mux_snk_in_arr(1)    <= dp_offload_mid_src_out;
-  dp_mux_snk_in_arr(2)    <= dp_offload_last_src_out;
-  dp_mux_snk_in_arr(3)    <= dp_offload_wo_src_out;
-  dp_offload_first_src_in <= dp_mux_snk_out_arr(0);
-  dp_offload_mid_src_in   <= dp_mux_snk_out_arr(1);
-  dp_offload_last_src_in  <= dp_mux_snk_out_arr(2);
-  dp_offload_wo_src_in    <= dp_mux_snk_out_arr(3);
+  dp_mux_snk_in_arr(0)    <= eth_ip_offload_first_src_out;
+  dp_mux_snk_in_arr(1)    <= eth_ip_offload_mid_src_out;
+  dp_mux_snk_in_arr(2)    <= eth_ip_offload_last_src_out;
+  dp_mux_snk_in_arr(3)    <= eth_ip_offload_wo_src_out;
+  eth_ip_offload_first_src_in <= dp_mux_snk_out_arr(0);
+  eth_ip_offload_mid_src_in   <= dp_mux_snk_out_arr(1);
+  eth_ip_offload_last_src_in  <= dp_mux_snk_out_arr(2);
+  eth_ip_offload_wo_src_in    <= dp_mux_snk_out_arr(3);
 
   u_dp_mux : entity dp_lib.dp_mux
   generic map (
@@ -472,7 +472,7 @@ begin
   port map (
     rst         => st_rst,
     clk         => st_clk,
-    sel_ctrl    => q.sel_ctrl,
+    sel_ctrl    => q.sel_ctrl_delayed,
     snk_in_arr  => dp_mux_snk_in_arr,
     snk_out_arr => dp_mux_snk_out_arr,
     src_out     => src_out,
diff --git a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_pkg.vhd b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_pkg.vhd
index b66da5f7dc56ef1eb9d137d0c2bca9c350c5bc0f..6909c4c228cfe15996c18f19c6b0b00fe404710b 100644
--- a/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_pkg.vhd
+++ b/applications/rdma_demo/libraries/rdma_packetiser/src/vhdl/rdma_packetiser_pkg.vhd
@@ -356,6 +356,7 @@ package rdma_packetiser_pkg is
   constant c_rdma_packetiser_opcode_uc_write_only_imm  : std_logic_vector(7 downto 0) := "001" & "01011"; -- with immediate
 
   function func_rdma_packetiser_map_header(hdr_fields_raw : std_logic_vector; field_arr : t_common_field_arr) return t_rdma_packetiser_roce_header;
+  function func_rdma_packetiser_unmap_header(hdr_fields : t_rdma_packetiser_roce_header; field_arr : t_common_field_arr) return std_logic_vector;
 end rdma_packetiser_pkg;
 
 package body rdma_packetiser_pkg is
@@ -420,4 +421,60 @@ package body rdma_packetiser_pkg is
     return v;
   end func_rdma_packetiser_map_header;
 
+  function func_rdma_packetiser_unmap_header(hdr_fields : t_rdma_packetiser_roce_header; field_arr : t_common_field_arr) return std_logic_vector is
+    constant c_field_len : natural := field_slv_len(field_arr);
+    variable v : std_logic_vector(c_field_len-1 downto 0) := (others => '0');
+    constant c_hdr_field_arr : t_common_field_arr := field_arr;
+  begin
+    -- eth header
+    v(field_hi(c_hdr_field_arr, "eth_dst_mac") downto field_lo(c_hdr_field_arr, "eth_dst_mac"))               := hdr_fields.eth.dst_mac;
+    v(field_hi(c_hdr_field_arr, "eth_src_mac") downto field_lo(c_hdr_field_arr, "eth_src_mac"))               := hdr_fields.eth.src_mac;
+    v(field_hi(c_hdr_field_arr, "eth_type")    downto field_lo(c_hdr_field_arr, "eth_type"))                  := hdr_fields.eth.eth_type;
+
+    -- ip header            
+    v(field_hi(c_hdr_field_arr, "ip_version")         downto field_lo(c_hdr_field_arr, "ip_version"))         := hdr_fields.ip.version;
+    v(field_hi(c_hdr_field_arr, "ip_header_length")   downto field_lo(c_hdr_field_arr, "ip_header_length"))   := hdr_fields.ip.header_length;
+    v(field_hi(c_hdr_field_arr, "ip_services")        downto field_lo(c_hdr_field_arr, "ip_services"))        := hdr_fields.ip.services;
+    v(field_hi(c_hdr_field_arr, "ip_total_length")    downto field_lo(c_hdr_field_arr, "ip_total_length"))    := hdr_fields.ip.total_length;
+    v(field_hi(c_hdr_field_arr, "ip_identification")  downto field_lo(c_hdr_field_arr, "ip_identification"))  := hdr_fields.ip.identification;
+    v(field_hi(c_hdr_field_arr, "ip_flags")           downto field_lo(c_hdr_field_arr, "ip_flags"))           := hdr_fields.ip.flags;
+    v(field_hi(c_hdr_field_arr, "ip_fragment_offset") downto field_lo(c_hdr_field_arr, "ip_fragment_offset")) := hdr_fields.ip.fragment_offset;
+    v(field_hi(c_hdr_field_arr, "ip_time_to_live")    downto field_lo(c_hdr_field_arr, "ip_time_to_live"))    := hdr_fields.ip.time_to_live;
+    v(field_hi(c_hdr_field_arr, "ip_protocol")        downto field_lo(c_hdr_field_arr, "ip_protocol"))        := hdr_fields.ip.protocol;
+    v(field_hi(c_hdr_field_arr, "ip_header_checksum") downto field_lo(c_hdr_field_arr, "ip_header_checksum")) := hdr_fields.ip.header_checksum;
+    v(field_hi(c_hdr_field_arr, "ip_src_addr")        downto field_lo(c_hdr_field_arr, "ip_src_addr"))        := hdr_fields.ip.src_ip_addr;
+    v(field_hi(c_hdr_field_arr, "ip_dst_addr")        downto field_lo(c_hdr_field_arr, "ip_dst_addr"))        := hdr_fields.ip.dst_ip_addr;
+
+    -- udp header           
+    v(field_hi(c_hdr_field_arr, "udp_src_port")     downto field_lo(c_hdr_field_arr, "udp_src_port"))         := hdr_fields.udp.src_port;
+    v(field_hi(c_hdr_field_arr, "udp_dst_port")     downto field_lo(c_hdr_field_arr, "udp_dst_port"))         := hdr_fields.udp.dst_port;
+    v(field_hi(c_hdr_field_arr, "udp_total_length") downto field_lo(c_hdr_field_arr, "udp_total_length"))     := hdr_fields.udp.total_length;
+    v(field_hi(c_hdr_field_arr, "udp_checksum")     downto field_lo(c_hdr_field_arr, "udp_checksum"))         := hdr_fields.udp.checksum;
+
+    -- bth header           
+    v(field_hi(c_hdr_field_arr, "bth_opcode")        downto field_lo(c_hdr_field_arr, "bth_opcode"))          := hdr_fields.bth.opcode;
+    v(field_hi(c_hdr_field_arr, "bth_se")            downto field_lo(c_hdr_field_arr, "bth_se"))              := hdr_fields.bth.se;
+    v(field_hi(c_hdr_field_arr, "bth_m")             downto field_lo(c_hdr_field_arr, "bth_m"))               := hdr_fields.bth.m;
+    v(field_hi(c_hdr_field_arr, "bth_pad")           downto field_lo(c_hdr_field_arr, "bth_pad"))             := hdr_fields.bth.pad;
+    v(field_hi(c_hdr_field_arr, "bth_tver")          downto field_lo(c_hdr_field_arr, "bth_tver"))            := hdr_fields.bth.tver;
+    v(field_hi(c_hdr_field_arr, "bth_partition_key") downto field_lo(c_hdr_field_arr, "bth_partition_key"))   := hdr_fields.bth.partition_key;
+    v(field_hi(c_hdr_field_arr, "bth_fres")          downto field_lo(c_hdr_field_arr, "bth_fres"))            := hdr_fields.bth.fres;
+    v(field_hi(c_hdr_field_arr, "bth_bres")          downto field_lo(c_hdr_field_arr, "bth_bres"))            := hdr_fields.bth.bres;
+    v(field_hi(c_hdr_field_arr, "bth_reserved_a")    downto field_lo(c_hdr_field_arr, "bth_reserved_a"))      := hdr_fields.bth.reserved_a;
+    v(field_hi(c_hdr_field_arr, "bth_dest_qp")       downto field_lo(c_hdr_field_arr, "bth_dest_qp"))         := hdr_fields.bth.dest_qp;
+    v(field_hi(c_hdr_field_arr, "bth_ack_req")       downto field_lo(c_hdr_field_arr, "bth_ack_req"))         := hdr_fields.bth.ack_req;
+    v(field_hi(c_hdr_field_arr, "bth_reserved_b")    downto field_lo(c_hdr_field_arr, "bth_reserved_b"))      := hdr_fields.bth.reserved_b;
+    v(field_hi(c_hdr_field_arr, "bth_psn")           downto field_lo(c_hdr_field_arr, "bth_psn"))             := hdr_fields.bth.psn;
+    
+    -- reth header
+    v(field_hi(c_hdr_field_arr, "reth_virtual_address") downto field_lo(c_hdr_field_arr, "reth_virtual_address")) := hdr_fields.reth.virtual_address;
+    v(field_hi(c_hdr_field_arr, "reth_r_key")           downto field_lo(c_hdr_field_arr, "reth_r_key"))           := hdr_fields.reth.r_key;
+    v(field_hi(c_hdr_field_arr, "reth_dma_length")      downto field_lo(c_hdr_field_arr, "reth_dma_length"))      := hdr_fields.reth.dma_length;
+
+    --immediate data
+    v(field_hi(c_hdr_field_arr, "immediate_data") downto field_lo(c_hdr_field_arr, "immediate_data")) := hdr_fields.immediate_data;
+
+    return v;
+  end func_rdma_packetiser_unmap_header;
+
 end rdma_packetiser_pkg;
diff --git a/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_rdma_packetiser_assemble_header.vhd b/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_rdma_packetiser_assemble_header.vhd
index 66b41e714ef9bdf1ecf9cdc54577d267667194cc..d4d6c6b101d2bc99249e51cb1e504a552a06eabf 100644
--- a/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_rdma_packetiser_assemble_header.vhd
+++ b/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_rdma_packetiser_assemble_header.vhd
@@ -17,9 +17,6 @@
 -- limitations under the License.
 --
 -------------------------------------------------------------------------------
--- NOTE Work in progress, will be finished in HPR-131
--------------------------------------------------------------------------------
---
 -- Author: R. vd Walle
 -- Purpose:
 -- . test bench for rdma_packetiser_assemble_header
@@ -47,6 +44,7 @@ library IEEE, common_lib, dp_lib;
   use common_lib.common_pkg.all;
   use common_lib.common_mem_pkg.all;
   use common_lib.common_network_layers_pkg.all;
+  use common_lib.common_field_pkg.all;
   use common_lib.tb_common_pkg.all;
   use common_lib.tb_common_mem_pkg.all;
   use dp_lib.tb_dp_pkg.all;
@@ -164,6 +162,8 @@ begin
     variable v_exp_reth_dma_length      : natural;
     variable v_exp_immediate_data       : std_logic_vector(c_word_w - 1 downto 0);
     variable v_p, v_m                   : natural := 0;
+    variable v_exp_hdr_raw              : std_logic_vector(field_slv_len(c_rdma_packetiser_wo_hdr_field_arr) - 1 downto 0);
+    variable v_exp_rdma_header          : t_rdma_packetiser_roce_header := func_rdma_packetiser_map_header(c_hdr_fields_slv_rst, c_rdma_packetiser_wo_hdr_field_arr);
   begin
 
     proc_common_wait_until_high(dp_clk, mm_done);  -- wait mm setup
@@ -229,28 +229,33 @@ begin
 
       -- assign expected values to signal to view in wave window.
       -- defaults
-      exp_rdma_header.eth.eth_type         <= x"0800";
-      exp_rdma_header.ip.version           <= to_uvec(4, 4);
-      exp_rdma_header.ip.header_length     <= to_uvec(5, 4);
-      exp_rdma_header.ip.flags             <= to_uvec(2, 3);
-      exp_rdma_header.ip.time_to_live      <= to_uvec(127, 8);
-      exp_rdma_header.ip.protocol          <= to_uvec(17, 8);
-      exp_rdma_header.bth.partition_key    <= to_uvec(65535, 16);
+      v_exp_rdma_header.eth.eth_type         := x"0800";
+      v_exp_rdma_header.ip.version           := to_uvec(4, 4);
+      v_exp_rdma_header.ip.header_length     := to_uvec(5, 4);
+      v_exp_rdma_header.ip.flags             := to_uvec(2, 3);
+      v_exp_rdma_header.ip.time_to_live      := to_uvec(127, 8);
+      v_exp_rdma_header.ip.protocol          := to_uvec(17, 8);
+      v_exp_rdma_header.bth.partition_key    := to_uvec(65535, 16);
       -- changed by DUT
-      exp_rdma_header.ip.total_length      <= to_uvec(v_exp_ip_total_length, c_halfword_w);
-      exp_rdma_header.udp.total_length     <= to_uvec(v_exp_udp_total_length, c_halfword_w );
-      exp_rdma_header.bth.opcode           <= v_exp_bth_opcode;
-      exp_rdma_header.bth.psn              <= to_uvec(v_exp_bth_psn, c_word_w);
-      exp_rdma_header.reth.virtual_address <= std_logic_vector(v_exp_reth_virtual_address);
-      exp_rdma_header.reth.dma_length      <= to_uvec(v_exp_reth_dma_length, c_word_w);
-      exp_rdma_header.immediate_data       <= v_exp_immediate_data;
+      v_exp_rdma_header.ip.total_length      := to_uvec(v_exp_ip_total_length, c_halfword_w);
+      v_exp_rdma_header.udp.total_length     := to_uvec(v_exp_udp_total_length, c_halfword_w );
+      v_exp_rdma_header.bth.opcode           := v_exp_bth_opcode;
+      v_exp_rdma_header.bth.psn              := to_uvec(v_exp_bth_psn, c_word_w);
+      v_exp_rdma_header.reth.virtual_address := std_logic_vector(v_exp_reth_virtual_address);
+      v_exp_rdma_header.reth.dma_length      := to_uvec(v_exp_reth_dma_length, c_word_w);
+      v_exp_rdma_header.immediate_data       := v_exp_immediate_data;
+       -- determine expected ip header checksum
+      v_exp_hdr_raw := func_rdma_packetiser_unmap_header(v_exp_rdma_header, c_rdma_packetiser_wo_hdr_field_arr);
+      v_exp_rdma_header.ip.header_checksum := func_network_ip_header_checksum(c_rdma_packetiser_wo_hdr_field_arr, v_exp_hdr_raw);
+
+      exp_rdma_header <= v_exp_rdma_header; -- for view in wave window
 
       -- increase counters
       v_p := v_p + 1;
       v_m := v_p / g_nof_packets_in_msg;
 
       proc_common_wait_some_cycles(dp_clk, 1);
-
+      
       -- assert when header is not as expected.
       assert rx_rdma_header                      = exp_rdma_header                      report "Wrong rx_rdma_header" severity error;
       assert rx_rdma_header.ip.total_length      = exp_rdma_header.ip.total_length      report "Wrong rx_rdma_header.ip.total_length value" severity error;
diff --git a/libraries/io/eth/hdllib.cfg b/libraries/io/eth/hdllib.cfg
index 86eb82159e6c2e1299e59bb71258a3df01426a58..2c904dd81bf8f9f2cfaf363282742d11261a5b2a 100644
--- a/libraries/io/eth/hdllib.cfg
+++ b/libraries/io/eth/hdllib.cfg
@@ -8,6 +8,7 @@ synth_files =
     src/vhdl/eth_pkg.vhd
     src/vhdl/eth_checksum.vhd
     src/vhdl/eth_ip_header_checksum.vhd
+    src/vhdl/eth_ip_offload_tx.vhd
     src/vhdl/eth_hdr_store.vhd
     src/vhdl/eth_hdr_status.vhd
     src/vhdl/eth_hdr_ctrl.vhd
diff --git a/libraries/io/eth/src/vhdl/eth_ip_offload_tx.vhd b/libraries/io/eth/src/vhdl/eth_ip_offload_tx.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..f4e4c935f61481f4a2e827155375f20ff7647093
--- /dev/null
+++ b/libraries/io/eth/src/vhdl/eth_ip_offload_tx.vhd
@@ -0,0 +1,120 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2024
+-- 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: R. van der Walle
+-- Purpose:
+-- . concatenate header from hdr_fields_in_arr to incoming sosi stream and 
+--   calculate + insert ip header checksum (crc).
+-- Description:
+-- . dp_offload_tx_v3 is used to concatenate the header to the dp sosi stream.
+-- . eth_ip_header_checksum is used to calculate and insert the ip header 
+--   checksum.
+library IEEE, common_lib, dp_lib;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+use common_lib.common_pkg.all;
+use common_lib.common_mem_pkg.all;
+use dp_lib.dp_stream_pkg.all;
+use common_lib.common_field_pkg.all;
+
+entity eth_ip_offload_tx is
+  generic (
+    g_nof_streams    : natural;
+    g_data_w         : natural;
+    g_symbol_w       : natural;
+    g_hdr_field_arr  : t_common_field_arr;  -- User defined header fields
+    g_hdr_field_sel  : std_logic_vector;  -- For each header field, select the source: 0=data path, 1=MM controlled
+    g_pipeline_ready : boolean := false
+  );
+  port (
+    mm_rst               : in  std_logic := '0';
+    mm_clk               : in  std_logic := '0';
+
+    dp_rst               : in  std_logic;
+    dp_clk               : in  std_logic;
+
+    reg_hdr_dat_copi     : in  t_mem_copi := c_mem_copi_rst;
+    reg_hdr_dat_cipo     : out t_mem_cipo;
+
+    snk_in_arr           : in  t_dp_sosi_arr(g_nof_streams - 1 downto 0);
+    snk_out_arr          : out t_dp_siso_arr(g_nof_streams - 1 downto 0);
+
+    src_out_arr          : out t_dp_sosi_arr(g_nof_streams - 1 downto 0);
+    src_in_arr           : in  t_dp_siso_arr(g_nof_streams - 1 downto 0) := (others => c_dp_siso_rdy);
+
+    hdr_fields_in_arr    : in  t_slv_1024_arr(g_nof_streams - 1 downto 0);  -- hdr_fields_in_arr(i) is considered valid @ snk_in_arr(i).sop
+    hdr_fields_out_arr   : out t_slv_1024_arr(g_nof_streams - 1 downto 0)
+  );
+end eth_ip_offload_tx;
+
+architecture str of eth_ip_offload_tx is
+
+  signal dp_offload_tx_src_out_arr        : t_dp_sosi_arr(g_nof_streams-1 downto 0) := (others => c_dp_sosi_rst);  
+  signal dp_offload_tx_src_in_arr         : t_dp_siso_arr(g_nof_streams-1 downto 0) := (others => c_dp_siso_rdy);  
+  signal dp_offload_tx_hdr_fields_out_arr : t_slv_1024_arr(g_nof_streams - 1 downto 0);
+
+begin
+
+  u_dp_offload_tx_v3 : entity dp_lib.dp_offload_tx_v3
+  generic map (
+    g_nof_streams    => g_nof_streams,
+    g_data_w         => g_data_w,
+    g_symbol_w       => g_symbol_w,
+    g_hdr_field_arr  => g_hdr_field_arr,
+    g_hdr_field_sel  => g_hdr_field_sel,
+    g_pipeline_ready => g_pipeline_ready
+  )
+  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_copi,
+    reg_hdr_dat_miso   => reg_hdr_dat_cipo,
+    snk_in_arr         => snk_in_arr,
+    snk_out_arr        => snk_out_arr,
+    src_out_arr        => dp_offload_tx_src_out_arr,
+    src_in_arr         => dp_offload_tx_src_in_arr,
+    hdr_fields_in_arr  => hdr_fields_in_arr,
+    hdr_fields_out_arr => dp_offload_tx_hdr_fields_out_arr
+  );
+
+  hdr_fields_out_arr <= dp_offload_tx_hdr_fields_out_arr;
+
+  gen_crc : for i in 0 to g_nof_streams - 1 generate
+    u_eth_ip_header_checksum : entity work.eth_ip_header_checksum
+    generic map (
+      g_data_w        => g_data_w,
+      g_hdr_field_arr => g_hdr_field_arr
+    )
+    port map (
+      rst               => dp_rst,
+      clk               => dp_clk,
+
+      snk_in            => dp_offload_tx_src_out_arr(i),
+      snk_out           => dp_offload_tx_src_in_arr(i),
+
+      src_out           => src_out_arr(i),
+      src_in            => src_in_arr(i),
+
+      hdr_fields_slv_in => dp_offload_tx_hdr_fields_out_arr(i)
+    );
+  end generate;
+
+ end str;