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 7dbf44536ae3c60faa6be94109636d2fc364180c..e51876b7d4d5972fcb4e5f70adbbe29595b0f768 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
@@ -20,13 +20,35 @@
 -- Author: R. van der Walle
 -- Purpose: Assembles the RDMA header at snk_in.sop
 -- Description:
--- The hdr_fields_slv output is set one st_clk cycle after snk_in.sop and will
--- contain the RoCEv2 (RDMA over Converged Ethernet v2) header information for
--- the corresponding data frame.
--- Remark
--- . The incoming data frame on snk_in should consist of at least 2 clock cycles.
---   i.e. two consecutive 1 cycle frames (sop + eop on the same clock cycle)
---   without a gap inbetween is not supported.
+-- Generates a RoCEv2 header (ETH + UDP + IP + RDMA). See [1].
+-- Generics:
+-- . g_use_immediate: When true, the immediate data field will be added to the
+--   header.
+-- . g_use_msg_cnt_as_immediate: When true, the message counter going from 0 to
+--   "nof_msg" is used as immediate data. When false, the "immediate_data"
+--   input port is used.
+-- Signal inputs:
+-- . immediate_data: Will be used as immediate data when
+--   g_use_msg_cnt_as_immediate = False.
+-- . block_len: Should be set to the length of the incoming data frame in octets.
+-- . nof_packets_in_msg: Should be set to the desired amount of packets in a message.
+-- . nof_msg: Should be set to the desired amount of messages, this determines the
+--   address space aswell, see remarks.
+-- . dma_len: The amount with which the address should increase every message,
+--   this should be set to >= nof_packets_in_msg * block_len.
+-- . start_address: The start address for the virtual_address field.
+-- Remarks
+-- . The hdr_fields_slv output is set one st_clk cycle after snk_in.sop and will
+--   contain the RoCEv2 (RDMA over Converged Ethernet v2) header information for
+--   the corresponding data frame.
+-- . The virtual_address is set automatically by increasing it with dma_len every
+--   new message. The virtual address is reset to "start_address" when the number
+--   of messages has reached "nof_msg". Then the cycle repeats.
+-- . The PSN field (= Packet Sequence Number) is set to LSBs of the incoming BSN.
+--   This can be used to check the order or detect missing packets at the receiver.
+
+-- References:
+-- . [1] https://support.astron.nl/confluence/x/3pKrB
 
 library IEEE, common_lib, dp_lib, eth_lib;
   use IEEE.std_logic_1164.all;
@@ -61,7 +83,6 @@ entity rdma_packetiser_assemble_header is
     nof_msg            : in  std_logic_vector(c_word_w - 1 downto 0);
     dma_len            : in  std_logic_vector(c_word_w - 1 downto 0); -- = block_len * nof_packets_in_msg
     start_address      : in  std_logic_vector(c_longword_w - 1 downto 0)
-
   );
 end rdma_packetiser_assemble_header;
 
@@ -71,33 +92,74 @@ architecture str of rdma_packetiser_assemble_header is
   constant c_udp_app_hdr_length    : natural := c_network_udp_header_len + c_app_hdr_length;
   constant c_ip_udp_app_hdr_length : natural := c_network_ip_header_len + c_udp_app_hdr_length;
 
-  type t_state is (s_idle, s_first, s_middle, s_last);
-  type t_reg is record
+  type t_state is (s_first, s_middle, s_last);
+  type t_reg is record -- record to keep the registers organized.
     state              : t_state;
     opcode             : std_logic_vector(c_byte_w - 1 downto 0);
     immediate_data     : std_logic_vector(c_rdma_packetiser_roce_imm_len * c_octet_w - 1 downto 0);
     psn                : std_logic_vector(c_word_w - 1 downto 0);
     virtual_address    : unsigned(c_longword_w - 1 downto 0);
     dma_len            : unsigned(c_word_w - 1 downto 0);
-    p_cnt              : natural;
-    msg_cnt            : natural;
+    p_cnt              : natural; -- Packet count (0 to nof_packets_in_msg).
+    msg_cnt            : natural; -- message count (0 to nof_msg).
     udp_total_length   : natural;
     ip_total_length    : natural;
     nof_packets_in_msg : natural;
   end record;
 
-  constant c_reg_rst : t_reg := (s_idle, (others => '1'), (others => '0'), (others => '0'), (others => '0'), (others => '0'), 0, 0, 0, 0, 0);
+  constant c_reg_rst : t_reg := (s_first, (others => '1'), (others => '0'), (others => '0'), (others => '0'), (others => '0'), 0, 0, 0, 0, 0);
   signal d, q : t_reg;
 begin
   q <= d when rising_edge(st_clk);
 
+  -- State machine to derive RDMA header fields.
   p_comb : process(st_rst, q, snk_in, nof_packets_in_msg, start_address, nof_msg, immediate_data, dma_len, block_len)
     variable v : t_reg;
   begin
     v := q;
-    if snk_in.sop = '1' then -- set on sop
+    if snk_in.sop = '1' then
       v.psn := resize_uvec(snk_in.bsn, c_word_w);
+      v.p_cnt := q.p_cnt + 1;
+      case q.state is
+        when s_first => -- wait to start a new message and set the first opcode.
+          v.p_cnt := 1;
+          if q.p_cnt >= v.nof_packets_in_msg then -- (re)set message counter and virtual address.
+            if q.msg_cnt >= to_uint(nof_msg) - 1 then
+              v.msg_cnt := 0;
+            else
+              v.msg_cnt := q.msg_cnt + 1;
+              v.virtual_address := q.virtual_address + q.dma_len;
+            end if;
+          end if;
+
+          if v.nof_packets_in_msg = 1 then -- set opcode to write_only.
+            v.opcode := c_rdma_packetiser_opcode_uc_write_only;
+            if g_use_immediate then  -- set opcode to write_only with immediate data.
+              v.opcode := c_rdma_packetiser_opcode_uc_write_only_imm;
+            end if;
+          elsif v.nof_packets_in_msg = 2 then -- set opcode to write_first.
+            v.state := s_last; -- next state is last as there are only 2 packets.
+            v.opcode := c_rdma_packetiser_opcode_uc_write_first;
+          elsif v.nof_packets_in_msg > 2 then
+            v.state := s_middle;
+            v.opcode := c_rdma_packetiser_opcode_uc_write_first;
+          end if;
+
+        when s_middle => -- wait unitl the first packet is done and set next opcode.
+          v.opcode := c_rdma_packetiser_opcode_uc_write_middle;
+          if q.p_cnt >= v.nof_packets_in_msg - 2 then -- wait until last middle packet
+            v.state := s_last;
+          end if;
+
+        when s_last => -- next packet must be last packet, set opcode.
+          v.state := s_first;
+          v.opcode := c_rdma_packetiser_opcode_uc_write_last;
+          if g_use_immediate then -- set opcode to write_last with immediate data
+            v.opcode := c_rdma_packetiser_opcode_uc_write_last_imm;
+          end if;
+      end case;
     end if;
+
     if v.msg_cnt = 0 then -- set on new message
       v.virtual_address    := unsigned(start_address);
       v.dma_len            := unsigned(dma_len);
@@ -107,57 +169,6 @@ begin
       v.immediate_data     := immediate_data;
     end if;
 
-    case q.state is
-      when s_idle =>
-        if snk_in.sop = '1' and v.nof_packets_in_msg > 1 then
-          v.state := s_first;
-          v.opcode := c_rdma_packetiser_opcode_uc_write_first;
-          v.p_cnt := 1;
-        elsif snk_in.sop = '1' and v.nof_packets_in_msg = 1 then
-          v.state := s_last;
-          v.opcode := c_rdma_packetiser_opcode_uc_write_only;
-          if g_use_immediate then
-            v.opcode := c_rdma_packetiser_opcode_uc_write_only_im;
-          end if;
-        end if;
-
-      when s_first =>
-        if snk_in.sop = '1' and v.nof_packets_in_msg > 2 then
-          v.state := s_middle;
-          v.opcode := c_rdma_packetiser_opcode_uc_write_middle;
-          v.p_cnt := q.p_cnt + 1;
-        elsif snk_in.sop = '1' and v.nof_packets_in_msg = 2 then
-          v.state := s_last;
-          v.opcode := c_rdma_packetiser_opcode_uc_write_last;
-          v.p_cnt := q.p_cnt + 1;
-          if g_use_immediate then
-            v.opcode := c_rdma_packetiser_opcode_uc_write_last_im;
-          end if;
-        end if;
-
-      when s_middle =>
-        if snk_in.sop = '1' and q.p_cnt >= v.nof_packets_in_msg - 1 then
-          v.state := s_last;
-          v.opcode := c_rdma_packetiser_opcode_uc_write_last;
-          v.p_cnt := q.p_cnt + 1;
-          if g_use_immediate then
-            v.opcode := c_rdma_packetiser_opcode_uc_write_last_im;
-          end if;
-        elsif snk_in.sop = '1' then
-          v.p_cnt := q.p_cnt + 1;
-        end if;
-
-      when s_last =>
-        v.state := s_idle;
-        v.p_cnt := 0;
-        if q.msg_cnt >= to_uint(nof_msg) - 1 then
-          v.msg_cnt := 0;
-        else
-          v.msg_cnt := q.msg_cnt + 1;
-          v.virtual_address := q.virtual_address + q.dma_len;
-        end if;
-    end case;
-
     if st_rst = '1' then
       v := c_reg_rst;
     end if;
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 c3f2a078aed2d799568c62bfba9dd952acde1438..bebc9205415d93fa2e33336d48b6a880852ae40c 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
@@ -17,11 +17,14 @@
 -- limitations under the License.
 --
 -------------------------------------------------------------------------------
---
+
+-------------------------------------------------------------------------------
 -- Author: R. vd Walle
--- Purpose: This package contains rdma_generator specific constants and/or functions
--- Description:
---
+-- Purpose: This package contains rdma_packetiser specific constants and/or functions
+-- Description: See [1] for RDMA explanation.
+-- References:
+-- . [1] https://support.astron.nl/confluence/x/3pKrB
+-------------------------------------------------------------------------------
 library IEEE, common_lib;
   use IEEE.std_logic_1164.all;
   use common_lib.common_pkg.all;
@@ -90,97 +93,97 @@ package rdma_packetiser_pkg is
 
   constant c_rdma_packetiser_roce_hdr_field_arr : t_common_field_arr(
     c_rdma_packetiser_roce_nof_hdr_fields - 1 downto 0) := (
-    ( field_name_pad("eth_dst_mac"         ), "RW", 48, field_default(0) ),
-    ( field_name_pad("eth_src_mac"         ), "RW", 48, field_default(0) ),
-    ( field_name_pad("eth_type"            ), "RW", 16, field_default(x"0800") ),
+    ( field_name_pad("eth_dst_mac"         ), "RW", 48, field_default(0) ), -- set by M&C
+    ( field_name_pad("eth_src_mac"         ), "RW", 48, field_default(0) ), -- set by M&C
+    ( field_name_pad("eth_type"            ), "RW", 16, field_default(x"0800") ), -- fixed
 
-    ( field_name_pad("ip_version"          ), "RW",  4, field_default(4) ),
-    ( field_name_pad("ip_header_length"    ), "RW",  4, field_default(5) ),
-    ( field_name_pad("ip_services"         ), "RW",  8, field_default(0) ),
-    ( field_name_pad("ip_total_length"     ), "RW", 16, field_default(0) ),  -- depends on BG block size, so set by data path
-    ( field_name_pad("ip_identification"   ), "RW", 16, field_default(0) ),
-    ( field_name_pad("ip_flags"            ), "RW",  3, field_default(2) ),
-    ( field_name_pad("ip_fragment_offset"  ), "RW", 13, field_default(0) ),
-    ( field_name_pad("ip_time_to_live"     ), "RW",  8, field_default(127) ),
-    ( field_name_pad("ip_protocol"         ), "RW",  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(0) ),  -- c_eth_tester_ip_dst_addr
+    ( field_name_pad("ip_version"          ), "RW",  4, field_default(4) ), -- fixed
+    ( field_name_pad("ip_header_length"    ), "RW",  4, field_default(5) ), -- fixed
+    ( field_name_pad("ip_services"         ), "RW",  8, field_default(0) ), -- fixed
+    ( field_name_pad("ip_total_length"     ), "RW", 16, field_default(0) ), -- set by data path
+    ( field_name_pad("ip_identification"   ), "RW", 16, field_default(0) ), -- fixed
+    ( field_name_pad("ip_flags"            ), "RW",  3, field_default(2) ), -- fixed
+    ( field_name_pad("ip_fragment_offset"  ), "RW", 13, field_default(0) ), -- fixed
+    ( field_name_pad("ip_time_to_live"     ), "RW",  8, field_default(127) ), -- fixed
+    ( field_name_pad("ip_protocol"         ), "RW",  8, field_default(17) ), -- fixed
+    ( field_name_pad("ip_header_checksum"  ), "RW", 16, field_default(0) ), -- set by data path
+    ( field_name_pad("ip_src_addr"         ), "RW", 32, field_default(0) ), -- set by M&C
+    ( field_name_pad("ip_dst_addr"         ), "RW", 32, field_default(0) ), -- set by M&C
 
-    ( field_name_pad("udp_src_port"        ), "RW", 16, field_default(0) ),
-    ( field_name_pad("udp_dst_port"        ), "RW", 16, field_default(0) ),  -- c_eth_tester_udp_dst_port
-    ( field_name_pad("udp_total_length"    ), "RW", 16, field_default(0) ),  -- depends on BG block size, so set by data path
-    ( field_name_pad("udp_checksum"        ), "RW", 16, field_default(0) ),
+    ( field_name_pad("udp_src_port"        ), "RW", 16, field_default(0) ), -- set by M&C
+    ( field_name_pad("udp_dst_port"        ), "RW", 16, field_default(0) ), -- set by M&C
+    ( field_name_pad("udp_total_length"    ), "RW", 16, field_default(0) ), -- set by data path
+    ( field_name_pad("udp_checksum"        ), "RW", 16, field_default(0) ), -- fixed
 
-    ( field_name_pad("bth_opcode"          ), "RW",  8, field_default(x"FF") ),
-    ( field_name_pad("bth_se"              ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_m"               ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_pad"             ), "RW",  2, field_default(0) ),
-    ( field_name_pad("bth_tver"            ), "RW",  4, field_default(0) ),
-    ( field_name_pad("bth_partition_key"   ), "RW", 16, field_default(65535) ),
-    ( field_name_pad("bth_fres"            ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_bres"            ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_reserved_a"      ), "RW",  6, field_default(0) ),
-    ( field_name_pad("bth_dest_qp"         ), "RW", 16, field_default(0) ),
-    ( field_name_pad("bth_ack_req"         ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_reserved_b"      ), "RW",  7, field_default(0) ),
-    ( field_name_pad("bth_psn"             ), "RW", 32, field_default(0) ),
+    ( field_name_pad("bth_opcode"          ), "RW",  8, field_default(x"FF") ), -- set by data path
+    ( field_name_pad("bth_se"              ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_m"               ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_pad"             ), "RW",  2, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_tver"            ), "RW",  4, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_partition_key"   ), "RW", 16, field_default(65535) ), -- set by M&C
+    ( field_name_pad("bth_fres"            ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_bres"            ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_reserved_a"      ), "RW",  6, field_default(0) ), -- fixed
+    ( field_name_pad("bth_dest_qp"         ), "RW", 16, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_ack_req"         ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_reserved_b"      ), "RW",  7, field_default(0) ), -- fixed
+    ( field_name_pad("bth_psn"             ), "RW", 32, field_default(0) ), -- set by data path
 
-    ( field_name_pad("reth_virtual_address"), "RW", 64, field_default(0) ),
-    ( field_name_pad("reth_r_key"          ), "RW", 32, field_default(0) ),
-    ( field_name_pad("reth_dma_length"     ), "RW", 32, field_default(0) ),
+    ( field_name_pad("reth_virtual_address"), "RW", 64, field_default(0) ), -- set by data path
+    ( field_name_pad("reth_r_key"          ), "RW", 32, field_default(0) ), -- set by M&C
+    ( field_name_pad("reth_dma_length"     ), "RW", 32, field_default(0) ), -- set by M&C
 
-    ( field_name_pad("immediate_data"      ), "RW", 32, field_default(0) )
+    ( field_name_pad("immediate_data"      ), "RW", 32, field_default(0) ) -- set by data path or M&C
     );
   constant c_rdma_packetiser_roce_reg_hdr_dat_addr_w    : natural := ceil_log2(field_nof_words(c_rdma_packetiser_roce_hdr_field_arr, c_word_w));
   constant c_rdma_packetiser_roce_reg_hdr_dat_addr_span : natural := 2**c_rdma_packetiser_roce_reg_hdr_dat_addr_w;
 
   -- RoCEv2 header for RDMA operation without immediate data
-  -- ETH + IP + UDP + Base Transport Header (BTH) + RDMA Extended Transport Header (RETH)
+  -- ETH + IP + UDP + Base Transport Header (BTH) + RDMA Extended Transport Header (RETH), so no immediate data ("no_imm").
   constant c_rdma_packetiser_roce_no_imm_nof_hdr_fields : natural := 3 + 12 + 4 + 13 + 3;
   constant c_rdma_packetiser_roce_no_imm_hdr_field_sel  : std_logic_vector(c_rdma_packetiser_roce_no_imm_nof_hdr_fields - 1 downto 0) :=  "111" & "111011111001" & "0100" & "1111111111111" & "111";
 
   constant c_rdma_packetiser_roce_no_imm_hdr_field_arr : t_common_field_arr(
     c_rdma_packetiser_roce_no_imm_nof_hdr_fields - 1 downto 0) := (
-    ( field_name_pad("eth_dst_mac"         ), "RW", 48, field_default(0) ),
-    ( field_name_pad("eth_src_mac"         ), "RW", 48, field_default(0) ),
-    ( field_name_pad("eth_type"            ), "RW", 16, field_default(x"0800") ),
+    ( field_name_pad("eth_dst_mac"         ), "RW", 48, field_default(0) ), -- set by M&C
+    ( field_name_pad("eth_src_mac"         ), "RW", 48, field_default(0) ), -- set by M&C
+    ( field_name_pad("eth_type"            ), "RW", 16, field_default(x"0800") ), -- fixed
 
-    ( field_name_pad("ip_version"          ), "RW",  4, field_default(4) ),
-    ( field_name_pad("ip_header_length"    ), "RW",  4, field_default(5) ),
-    ( field_name_pad("ip_services"         ), "RW",  8, field_default(0) ),
-    ( field_name_pad("ip_total_length"     ), "RW", 16, field_default(0) ),  -- depends on BG block size, so set by data path
-    ( field_name_pad("ip_identification"   ), "RW", 16, field_default(0) ),
-    ( field_name_pad("ip_flags"            ), "RW",  3, field_default(2) ),
-    ( field_name_pad("ip_fragment_offset"  ), "RW", 13, field_default(0) ),
-    ( field_name_pad("ip_time_to_live"     ), "RW",  8, field_default(127) ),
-    ( field_name_pad("ip_protocol"         ), "RW",  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(0) ),  -- c_eth_tester_ip_dst_addr
+    ( field_name_pad("ip_version"          ), "RW",  4, field_default(4) ), -- fixed
+    ( field_name_pad("ip_header_length"    ), "RW",  4, field_default(5) ), -- fixed
+    ( field_name_pad("ip_services"         ), "RW",  8, field_default(0) ), -- fixed
+    ( field_name_pad("ip_total_length"     ), "RW", 16, field_default(0) ), -- set by data path
+    ( field_name_pad("ip_identification"   ), "RW", 16, field_default(0) ), -- fixed
+    ( field_name_pad("ip_flags"            ), "RW",  3, field_default(2) ), -- fixed
+    ( field_name_pad("ip_fragment_offset"  ), "RW", 13, field_default(0) ), -- fixed
+    ( field_name_pad("ip_time_to_live"     ), "RW",  8, field_default(127) ), -- fixed
+    ( field_name_pad("ip_protocol"         ), "RW",  8, field_default(17) ), -- fixed
+    ( field_name_pad("ip_header_checksum"  ), "RW", 16, field_default(0) ), -- set by data path
+    ( field_name_pad("ip_src_addr"         ), "RW", 32, field_default(0) ), -- set by M&C
+    ( field_name_pad("ip_dst_addr"         ), "RW", 32, field_default(0) ), -- set by M&C
 
-    ( field_name_pad("udp_src_port"        ), "RW", 16, field_default(0) ),
-    ( field_name_pad("udp_dst_port"        ), "RW", 16, field_default(0) ),  -- c_eth_tester_udp_dst_port
-    ( field_name_pad("udp_total_length"    ), "RW", 16, field_default(0) ),  -- depends on BG block size, so set by data path
-    ( field_name_pad("udp_checksum"        ), "RW", 16, field_default(0) ),
+    ( field_name_pad("udp_src_port"        ), "RW", 16, field_default(0) ), -- set by M&C
+    ( field_name_pad("udp_dst_port"        ), "RW", 16, field_default(0) ), -- set by M&C
+    ( field_name_pad("udp_total_length"    ), "RW", 16, field_default(0) ), -- set by data path
+    ( field_name_pad("udp_checksum"        ), "RW", 16, field_default(0) ), -- fixed
 
-    ( field_name_pad("bth_opcode"          ), "RW",  8, field_default(x"FF") ),
-    ( field_name_pad("bth_se"              ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_m"               ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_pad"             ), "RW",  2, field_default(0) ),
-    ( field_name_pad("bth_tver"            ), "RW",  4, field_default(0) ),
-    ( field_name_pad("bth_partition_key"   ), "RW", 16, field_default(65535) ),
-    ( field_name_pad("bth_fres"            ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_bres"            ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_reserved_a"      ), "RW",  6, field_default(0) ),
-    ( field_name_pad("bth_dest_qp"         ), "RW", 16, field_default(0) ),
-    ( field_name_pad("bth_ack_req"         ), "RW",  1, field_default(0) ),
-    ( field_name_pad("bth_reserved_b"      ), "RW",  7, field_default(0) ),
-    ( field_name_pad("bth_psn"             ), "RW", 32, field_default(0) ),
+    ( field_name_pad("bth_opcode"          ), "RW",  8, field_default(x"FF") ), -- set by data path
+    ( field_name_pad("bth_se"              ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_m"               ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_pad"             ), "RW",  2, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_tver"            ), "RW",  4, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_partition_key"   ), "RW", 16, field_default(65535) ), -- set by M&C
+    ( field_name_pad("bth_fres"            ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_bres"            ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_reserved_a"      ), "RW",  6, field_default(0) ), -- fixed
+    ( field_name_pad("bth_dest_qp"         ), "RW", 16, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_ack_req"         ), "RW",  1, field_default(0) ), -- set by M&C
+    ( field_name_pad("bth_reserved_b"      ), "RW",  7, field_default(0) ), -- fixed
+    ( field_name_pad("bth_psn"             ), "RW", 32, field_default(0) ), -- set by data path
 
-    ( field_name_pad("reth_virtual_address"), "RW", 64, field_default(0) ),
-    ( field_name_pad("reth_r_key"          ), "RW", 32, field_default(0) ),
-    ( field_name_pad("reth_dma_length"     ), "RW", 32, field_default(0) )
+    ( field_name_pad("reth_virtual_address"), "RW", 64, field_default(0) ), -- set by data path
+    ( field_name_pad("reth_r_key"          ), "RW", 32, field_default(0) ), -- set by M&C
+    ( field_name_pad("reth_dma_length"     ), "RW", 32, field_default(0) ) -- set by M&C
     );
   constant c_rdma_packetiser_roce_reg_no_imm_hdr_dat_addr_w    : natural := ceil_log2(field_nof_words(c_rdma_packetiser_roce_no_imm_hdr_field_arr, c_word_w));
   constant c_rdma_packetiser_roce_reg_no_imm_hdr_dat_addr_span : natural := 2**c_rdma_packetiser_roce_reg_no_imm_hdr_dat_addr_w;
@@ -190,18 +193,18 @@ package rdma_packetiser_pkg is
   constant c_rdma_packetiser_roce_icrc_len        : natural := 4;   -- octets
   constant c_rdma_packetiser_roce_no_imm_hdr_len  : natural := c_rdma_packetiser_roce_hdr_len - c_rdma_packetiser_roce_imm_len;
 
-  constant c_rdma_packetiser_opcode_uc_send_first    : std_logic_vector := "001" & "00000";
-  constant c_rdma_packetiser_opcode_uc_send_middle   : std_logic_vector := "001" & "00001";
-  constant c_rdma_packetiser_opcode_uc_send_last     : std_logic_vector := "001" & "00010";
-  constant c_rdma_packetiser_opcode_uc_send_last_im  : std_logic_vector := "001" & "00011";
-  constant c_rdma_packetiser_opcode_uc_send_only     : std_logic_vector := "001" & "00100";
-  constant c_rdma_packetiser_opcode_uc_send_only_im  : std_logic_vector := "001" & "00101";
-  constant c_rdma_packetiser_opcode_uc_write_first   : std_logic_vector := "001" & "00110";
-  constant c_rdma_packetiser_opcode_uc_write_middle  : std_logic_vector := "001" & "00111";
-  constant c_rdma_packetiser_opcode_uc_write_last    : std_logic_vector := "001" & "01000";
-  constant c_rdma_packetiser_opcode_uc_write_last_im : std_logic_vector := "001" & "01001";
-  constant c_rdma_packetiser_opcode_uc_write_only    : std_logic_vector := "001" & "01010";
-  constant c_rdma_packetiser_opcode_uc_write_only_im : std_logic_vector := "001" & "01011";
+  constant c_rdma_packetiser_opcode_uc_send_first      : std_logic_vector := "001" & "00000";
+  constant c_rdma_packetiser_opcode_uc_send_middle     : std_logic_vector := "001" & "00001";
+  constant c_rdma_packetiser_opcode_uc_send_last       : std_logic_vector := "001" & "00010"; -- without immediate
+  constant c_rdma_packetiser_opcode_uc_send_last_imm   : std_logic_vector := "001" & "00011"; -- with immediate
+  constant c_rdma_packetiser_opcode_uc_send_only       : std_logic_vector := "001" & "00100"; -- without immediate
+  constant c_rdma_packetiser_opcode_uc_send_only_imm   : std_logic_vector := "001" & "00101"; -- with immediate
+  constant c_rdma_packetiser_opcode_uc_write_first     : std_logic_vector := "001" & "00110";
+  constant c_rdma_packetiser_opcode_uc_write_middle    : std_logic_vector := "001" & "00111";
+  constant c_rdma_packetiser_opcode_uc_write_last      : std_logic_vector := "001" & "01000"; -- without immediate
+  constant c_rdma_packetiser_opcode_uc_write_last_imm  : std_logic_vector := "001" & "01001"; -- with immediate
+  constant c_rdma_packetiser_opcode_uc_write_only      : std_logic_vector := "001" & "01010"; -- without immediate
+  constant c_rdma_packetiser_opcode_uc_write_only_imm  : std_logic_vector := "001" & "01011"; -- with immediate
 
   function func_rdma_packetiser_map_header(hdr_fields_raw : std_logic_vector; use_immediate : boolean) return t_rdma_packetiser_roce_header;
 
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 9644b24454b1803bf9820a447a8113a797d07ea6..b6a19a3744ecbbf954656b5f6af1b60f151dd18d 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
@@ -21,15 +21,24 @@
 -------------------------------------------------------------------------------
 --
 -- Author: R. vd Walle
-
 -- Purpose:
 -- . test bench for rdma_packetiser_assemble_header
 -- Description:
 -- . Generates DP data using proc_dp_gen_block_data that streams into DUT.
 -- . Verifies the resulting header field array comming from the DUT by
 --   comparing to expected values.
--- Remark:
--- .
+-- . The generics can be used to test specific conditions.
+--   . g_use_immediate: When true, the DUT will use the optional immediate data
+--     field.
+--   . g_use_msg_cnt_as_immediate: When true, the DUT will use the message count
+--     value as immediate data. When false, the DUT sets the immediate data to
+--     the value of the immediate_data input port.
+--   . g_nof_rep: number of packets the TB should generate.
+--   . g_frame_len: length of the data frames that the TB should generate.
+--   . g_start_address: 64 bit value to use as a start address for the DUT
+--   . g_nof_packets_in_msg: The number of packets the DUT should put in one
+--     RDMA message.
+--   . g_nof_msg: Number of RDMA messages the DUT should create.
 -------------------------------------------------------------------------------
 
 library IEEE, common_lib, dp_lib;
@@ -48,7 +57,7 @@ entity tb_rdma_packetiser_assemble_header is
   generic (
     g_use_immediate            : boolean := true;
     g_use_msg_cnt_as_immediate : boolean := true;
-    g_nof_rep                  : natural := 15;
+    g_nof_rep                  : natural := 60;
     g_frame_len                : natural := 15;
     g_start_address            : unsigned(c_longword_w - 1 downto 0) := (others => '0');
     g_nof_packets_in_msg       : natural := 4;
@@ -80,7 +89,7 @@ architecture tb of tb_rdma_packetiser_assemble_header is
   signal start_address       : std_logic_vector(c_longword_w - 1 downto 0) := std_logic_vector(g_start_address);
 
   signal hdr_fields_slv      : std_logic_vector(1023 downto 0) := (others => '0');
-  signal rdma_header         : t_rdma_packetiser_roce_header;
+  signal rx_rdma_header         : t_rdma_packetiser_roce_header;
   signal exp_rdma_header     : t_rdma_packetiser_roce_header := func_rdma_packetiser_map_header(c_hdr_fields_slv_rst, g_use_immediate);
   signal in_en : std_logic := '0';
 
@@ -90,7 +99,7 @@ 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;
 
-  rdma_header <= func_rdma_packetiser_map_header(hdr_fields_slv, g_use_immediate );
+  rx_rdma_header <= func_rdma_packetiser_map_header(hdr_fields_slv, g_use_immediate );
 
   p_dp_stimuli : process
   begin
@@ -107,7 +116,7 @@ begin
   end process;
 
   -- check if values in rdma_packetiser_assemble_header match with expected values
-  p_rdma_packetiser_assemble_header_stimuli : process
+  p_verify_rdma_header : process
     variable v_exp_ip_total_length      : natural;
     variable v_exp_udp_total_length     : natural;
     variable v_exp_bth_opcode           : std_logic_vector(c_byte_w - 1 downto 0);
@@ -132,14 +141,14 @@ begin
       if v_p mod g_nof_packets_in_msg = 0 then
         v_exp_bth_opcode := c_rdma_packetiser_opcode_uc_write_first;
         if g_nof_packets_in_msg = 1 and g_use_immediate then
-          v_exp_bth_opcode := c_rdma_packetiser_opcode_uc_write_only_im;
+          v_exp_bth_opcode := c_rdma_packetiser_opcode_uc_write_only_imm;
         elsif g_nof_packets_in_msg = 1 then
           v_exp_bth_opcode := c_rdma_packetiser_opcode_uc_write_only;
         end if;
       elsif v_p mod g_nof_packets_in_msg = g_nof_packets_in_msg - 1 then
         v_exp_bth_opcode := c_rdma_packetiser_opcode_uc_write_last;
         if g_use_immediate then
-          v_exp_bth_opcode := c_rdma_packetiser_opcode_uc_write_last_im;
+          v_exp_bth_opcode := c_rdma_packetiser_opcode_uc_write_last_imm;
         end if;
       else
         v_exp_bth_opcode := c_rdma_packetiser_opcode_uc_write_middle;
@@ -160,13 +169,14 @@ begin
       proc_common_wait_some_cycles(dp_clk, 1);
 
       -- assert when header is not as expected.
-      assert TO_UINT(rdma_header.ip.total_length)       = v_exp_ip_total_length      report "Wrong rdma_header.ip.total_length value" severity error;
-      assert TO_UINT(rdma_header.udp.total_length)      = v_exp_udp_total_length     report "Wrong rdma_header.udp.total_length value" severity error;
-      assert rdma_header.bth.opcode                     = v_exp_bth_opcode           report "Wrong rdma_header.bth.opcode value" severity error;
-      assert TO_UINT(rdma_header.bth.psn)               = v_exp_bth_psn              report "Wrong rdma_header.bth.psn value" severity error;
-      assert unsigned(rdma_header.reth.virtual_address) = v_exp_reth_virtual_address report "Wrong rdma_header.reth.virtual_address value" severity error;
-      assert TO_UINT(rdma_header.reth.dma_length)       = v_exp_reth_dma_length      report "Wrong rdma_header.reth.dma_length value" severity error;
-      assert rdma_header.immediate_data                 = v_exp_immediate_data       report "Wrong rdma_header.immediate_data value" severity error;
+      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;
+      assert rx_rdma_header.udp.total_length     = exp_rdma_header.udp.total_length     report "Wrong rx_rdma_header.udp.total_length value" severity error;
+      assert rx_rdma_header.bth.opcode           = exp_rdma_header.bth.opcode           report "Wrong rx_rdma_header.bth.opcode value" severity error;
+      assert rx_rdma_header.bth.psn              = exp_rdma_header.bth.psn              report "Wrong rx_rdma_header.bth.psn value" severity error;
+      assert rx_rdma_header.reth.virtual_address = exp_rdma_header.reth.virtual_address report "Wrong rx_rdma_header.reth.virtual_address value" severity error;
+      assert rx_rdma_header.reth.dma_length      = exp_rdma_header.reth.dma_length      report "Wrong rx_rdma_header.reth.dma_length value" severity error;
+      assert rx_rdma_header.immediate_data       = exp_rdma_header.immediate_data       report "Wrong rx_rdma_header.immediate_data value" severity error;
     end loop;
 
     proc_common_wait_some_cycles(dp_clk, 100);
diff --git a/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_tb_rdma_packetiser_assemble_header.vhd b/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_tb_rdma_packetiser_assemble_header.vhd
index 4bc4b5ebe94a6a037caa0fbb4291cb775306dba2..f660180caa85165c58e1994f55addcf8c66bdc66 100644
--- a/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_tb_rdma_packetiser_assemble_header.vhd
+++ b/applications/rdma_demo/libraries/rdma_packetiser/tb/vhdl/tb_tb_rdma_packetiser_assemble_header.vhd
@@ -48,14 +48,14 @@ begin
   --    g_nof_packets_in_msg       : natural := 4;
   --    g_nof_msg                  : natural := 3
 
-  u_lo_addr   : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   15,   c_low_start_addr,  4, 5);
-  u_hi_addr   : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   15,   c_high_start_addr, 4, 5);
-  u_no_mid    : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   15,   c_high_start_addr, 2, 5);
-  u_wr_only   : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   15,   c_high_start_addr, 1, 5);
-  u_large     : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  10,   2000, c_low_start_addr,  3, 1);
-  u_no_im_cnt : entity work.tb_rdma_packetiser_assemble_header generic map( false, true,  100,  15,   c_low_start_addr,  4, 10);
-  u_no_cnt    : entity work.tb_rdma_packetiser_assemble_header generic map( true,  false, 20,   15,   c_low_start_addr,  4, 5);
-  u_no_im     : entity work.tb_rdma_packetiser_assemble_header generic map( false, false, 30,   7,    c_high_start_addr, 3, 2);
-  u_two       : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   2,    c_low_start_addr,  1, 5);
-  u_many      : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  6000, 3,    c_low_start_addr,  5, 1000);
+  u_lo_addr    : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   15,   c_low_start_addr,  4, 5);
+  u_hi_addr    : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   15,   c_high_start_addr, 4, 5);
+  u_no_mid     : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   15,   c_high_start_addr, 2, 5);
+  u_wr_only    : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   15,   c_high_start_addr, 1, 5);
+  u_large      : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  10,   2000, c_low_start_addr,  3, 1);
+  u_no_imm_cnt : entity work.tb_rdma_packetiser_assemble_header generic map( false, true,  100,  15,   c_low_start_addr,  4, 10);
+  u_no_cnt     : entity work.tb_rdma_packetiser_assemble_header generic map( true,  false, 20,   15,   c_low_start_addr,  4, 5);
+  u_no_imm     : entity work.tb_rdma_packetiser_assemble_header generic map( false, false, 30,   7,    c_high_start_addr, 3, 2);
+  u_one        : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  20,   1,    c_low_start_addr,  1, 5);
+  u_many       : entity work.tb_rdma_packetiser_assemble_header generic map( true,  true,  6000, 3,    c_low_start_addr,  5, 1000);
 end tb;