diff --git a/libraries/base/common/src/vhdl/common_network_total_header_pkg.vhd b/libraries/base/common/src/vhdl/common_network_total_header_pkg.vhd
index 544b97ac9341718f62e4c32865e4e1452f31be6e..deaf4c35acacc09743dd0d71088acb01b9f1e3ec 100644
--- a/libraries/base/common/src/vhdl/common_network_total_header_pkg.vhd
+++ b/libraries/base/common/src/vhdl/common_network_total_header_pkg.vhd
@@ -222,6 +222,18 @@ PACKAGE common_network_total_header_pkg IS
   FUNCTION func_network_total_header_extract_icmp(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_icmp_header;
   FUNCTION func_network_total_header_extract_udp( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_udp_header;
   FUNCTION func_network_total_header_extract_udp( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_udp_header;
+
+  -- Combinatorial map just as above but for network packets without word align field.
+  FUNCTION func_network_total_header_no_align_extract_eth( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_eth_header;
+  FUNCTION func_network_total_header_no_align_extract_eth( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_eth_header;
+  FUNCTION func_network_total_header_no_align_extract_ip(  hdr_arr : t_network_total_header_32b_arr) RETURN t_network_ip_header;
+  FUNCTION func_network_total_header_no_align_extract_ip(  hdr_arr : t_network_total_header_64b_arr) RETURN t_network_ip_header;
+  FUNCTION func_network_total_header_no_align_extract_arp( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_arp_packet;
+  FUNCTION func_network_total_header_no_align_extract_arp( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_arp_packet;
+  FUNCTION func_network_total_header_no_align_extract_icmp(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_icmp_header;
+  FUNCTION func_network_total_header_no_align_extract_icmp(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_icmp_header;
+  FUNCTION func_network_total_header_no_align_extract_udp( hdr_arr : t_network_total_header_32b_arr) RETURN t_network_udp_header;
+  FUNCTION func_network_total_header_no_align_extract_udp( hdr_arr : t_network_total_header_64b_arr) RETURN t_network_udp_header;
   
   -- Construct the total header array from the individual header records
   FUNCTION func_network_total_header_construct_eth( eth : t_network_eth_header)                                                          RETURN t_network_total_header_32b_arr;  -- sets unused words to zero
@@ -250,6 +262,25 @@ PACKAGE common_network_total_header_pkg IS
   FUNCTION func_network_total_header_response_icmp(icmp_arr : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
   FUNCTION func_network_total_header_response_udp( udp_arr  : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
   FUNCTION func_network_total_header_response_udp( udp_arr  : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
+
+  -- Construct the response total header array for a total header array without alignment bytes
+  FUNCTION func_network_total_header_no_align_response_eth( eth_arr  : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
+  FUNCTION func_network_total_header_no_align_response_eth( eth_arr  : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
+  FUNCTION func_network_total_header_no_align_response_arp( arp_arr  : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
+                                                                                              ip_addr  : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0))
+                                                                                              RETURN t_network_total_header_32b_arr;
+  FUNCTION func_network_total_header_no_align_response_arp( arp_arr  : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
+                                                                                              ip_addr  : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0))
+                                                                                              RETURN t_network_total_header_64b_arr;
+  FUNCTION func_network_total_header_no_align_response_ip(  ip_arr   : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
+  FUNCTION func_network_total_header_no_align_response_ip(  ip_arr   : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
+  FUNCTION func_network_total_header_no_align_response_icmp(icmp_arr : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
+  FUNCTION func_network_total_header_no_align_response_icmp(icmp_arr : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
+  FUNCTION func_network_total_header_no_align_response_udp( udp_arr  : t_network_total_header_32b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr;
+  FUNCTION func_network_total_header_no_align_response_udp( udp_arr  : t_network_total_header_64b_arr; mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr;
+
+
+
   
 END common_network_total_header_pkg;
 
@@ -396,6 +427,146 @@ PACKAGE BODY common_network_total_header_pkg IS
     v_hdr.checksum            := hdr_arr(5)(15 DOWNTO  0);
     RETURN v_hdr;
   END;
+
+  -- Assume the total header has NOT been padded with the word align field
+  -- Map the 11 32b words or 6 64b longwords from the total header to the header field records
+  
+  FUNCTION func_network_total_header_no_align_extract_eth(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_eth_header IS
+    VARIABLE v_hdr : t_network_eth_header;
+  BEGIN
+    v_hdr.dst_mac(47 DOWNTO 16) := hdr_arr(0);
+    v_hdr.dst_mac(15 DOWNTO  0) := hdr_arr(1)(31 DOWNTO 16);
+    v_hdr.src_mac(47 DOWNTO 32) := hdr_arr(1)(15 DOWNTO  0);
+    v_hdr.src_mac(31 DOWNTO  0) := hdr_arr(2);
+    v_hdr.eth_type              := hdr_arr(3)(31 DOWNTO  16);
+    RETURN v_hdr;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_extract_eth(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_eth_header IS
+    VARIABLE v_hdr : t_network_eth_header;
+  BEGIN
+    v_hdr.dst_mac               := hdr_arr(0)(63 DOWNTO 16);
+    v_hdr.src_mac(47 DOWNTO 32) := hdr_arr(0)(15 DOWNTO  0);
+    v_hdr.src_mac(31 DOWNTO  0) := hdr_arr(1)(63 DOWNTO 32);
+    v_hdr.eth_type              := hdr_arr(1)(31 DOWNTO 16);
+    RETURN v_hdr;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_extract_ip(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_ip_header IS
+    VARIABLE v_hdr : t_network_ip_header;
+  BEGIN
+    v_hdr.version                   := hdr_arr(3)(15 DOWNTO 12);
+    v_hdr.header_length             := hdr_arr(3)(11 DOWNTO  8);
+    v_hdr.services                  := hdr_arr(3)( 7 DOWNTO  0);
+    v_hdr.total_length              := hdr_arr(4)(31 DOWNTO 16);
+    v_hdr.identification            := hdr_arr(4)(15 DOWNTO  0);
+    v_hdr.flags                     := hdr_arr(5)(31 DOWNTO 29);
+    v_hdr.fragment_offset           := hdr_arr(5)(28 DOWNTO 16);
+    v_hdr.time_to_live              := hdr_arr(5)(15 DOWNTO  8);
+    v_hdr.protocol                  := hdr_arr(5)( 7 DOWNTO  0);
+    v_hdr.header_checksum           := hdr_arr(6)(31 DOWNTO 16);
+    v_hdr.src_ip_addr(31 DOWNTO 16) := hdr_arr(6)(15 DOWNTO  0);
+    v_hdr.src_ip_addr(15 DOWNTO  0) := hdr_arr(7)(31 DOWNTO 16);
+    v_hdr.dst_ip_addr(31 DOWNTO 16) := hdr_arr(7)(15 DOWNTO  0);
+    v_hdr.dst_ip_addr(15 DOWNTO  0) := hdr_arr(8)(31 DOWNTO 16);
+    RETURN v_hdr;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_extract_ip(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_ip_header IS
+    VARIABLE v_hdr : t_network_ip_header;
+  BEGIN
+    v_hdr.version            := hdr_arr(1)(15 DOWNTO 12);
+    v_hdr.header_length      := hdr_arr(1)(11 DOWNTO  8);
+    v_hdr.services           := hdr_arr(1)( 7 DOWNTO  0);
+    v_hdr.total_length       := hdr_arr(2)(63 DOWNTO 48);
+    v_hdr.identification     := hdr_arr(2)(47 DOWNTO 32);
+    v_hdr.flags              := hdr_arr(2)(31 DOWNTO 29);
+    v_hdr.fragment_offset    := hdr_arr(2)(28 DOWNTO 16);
+    v_hdr.time_to_live       := hdr_arr(2)(15 DOWNTO  8);
+    v_hdr.protocol           := hdr_arr(2)( 7 DOWNTO  0);
+    v_hdr.header_checksum    := hdr_arr(3)(63 DOWNTO 48);
+    v_hdr.src_ip_addr        := hdr_arr(3)(47 DOWNTO 16);
+    v_hdr.dst_ip_addr(31 DOWNTO 16) := hdr_arr(3)(15 DOWNTO  0);
+    v_hdr.dst_ip_addr(15 DOWNTO  0) := hdr_arr(4)(63 DOWNTO 48);
+    RETURN v_hdr;
+  END;
+ 
+  FUNCTION func_network_total_header_no_align_extract_arp(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_arp_packet IS
+    VARIABLE v_arp : t_network_arp_packet;
+  BEGIN
+    v_arp.htype              := hdr_arr(3)(15 DOWNTO  0);
+    v_arp.ptype              := hdr_arr(4)(31 DOWNTO 16);
+    v_arp.hlen               := hdr_arr(4)(15 DOWNTO  8);
+    v_arp.plen               := hdr_arr(4)( 7 DOWNTO  0);
+    v_arp.oper               := hdr_arr(5)(31 DOWNTO 16);
+    v_arp.sha(47 DOWNTO 32)  := hdr_arr(5)(15 DOWNTO  0);
+    v_arp.sha(31 DOWNTO  0)  := hdr_arr(6);
+    v_arp.spa                := hdr_arr(7);
+    v_arp.tha(47 DOWNTO 16)  := hdr_arr(8);
+    v_arp.tha(15 DOWNTO  0)  := hdr_arr(9)(31 DOWNTO 16);
+    v_arp.tpa(31 DOWNTO 16)  := hdr_arr(9)(15 DOWNTO  0);
+    v_arp.tpa(15 DOWNTO  0)  := hdr_arr(9)(31 DOWNTO 16);
+    RETURN v_arp;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_extract_arp(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_arp_packet IS
+    VARIABLE v_arp : t_network_arp_packet;
+  BEGIN
+    v_arp.htype              := hdr_arr(1)(15 DOWNTO  0);
+    v_arp.ptype              := hdr_arr(2)(63 DOWNTO 48);
+    v_arp.hlen               := hdr_arr(2)(47 DOWNTO 40);
+    v_arp.plen               := hdr_arr(2)(39 DOWNTO 32);
+    v_arp.oper               := hdr_arr(2)(31 DOWNTO 16);
+    v_arp.sha(47 DOWNTO 32)  := hdr_arr(2)(15 DOWNTO  0);
+    v_arp.sha(31 DOWNTO  0)  := hdr_arr(3)(63 DOWNTO 32);
+    v_arp.spa                := hdr_arr(3)(31 DOWNTO  0);
+    v_arp.tha                := hdr_arr(4)(63 DOWNTO 16);
+    v_arp.tpa(31 DOWNTO 16)  := hdr_arr(4)(15 DOWNTO  0);
+    v_arp.tpa(15 DOWNTO  0)  := hdr_arr(5)(63 DOWNTO 48);
+    RETURN v_arp;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_extract_icmp(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_icmp_header IS
+    VARIABLE v_hdr : t_network_icmp_header;
+  BEGIN
+    v_hdr.msg_type  := hdr_arr(8)(15 DOWNTO  8);
+    v_hdr.code      := hdr_arr(8)( 7 DOWNTO  0);
+    v_hdr.checksum  := hdr_arr(9)(31 DOWNTO 16);
+    v_hdr.id        := hdr_arr(9)(15 DOWNTO  0);
+    v_hdr.sequence  := hdr_arr(10)(31 DOWNTO 16);
+    RETURN v_hdr;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_extract_icmp(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_icmp_header IS
+    VARIABLE v_hdr : t_network_icmp_header;
+  BEGIN
+    v_hdr.msg_type  := hdr_arr(4)(47 DOWNTO 40);
+    v_hdr.code      := hdr_arr(4)(39 DOWNTO 32);
+    v_hdr.checksum  := hdr_arr(4)(31 DOWNTO 16);
+    v_hdr.id        := hdr_arr(4)(15 DOWNTO  0);
+    v_hdr.sequence  := hdr_arr(5)(63 DOWNTO 48);
+    RETURN v_hdr;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_extract_udp(hdr_arr : t_network_total_header_32b_arr) RETURN t_network_udp_header IS
+    VARIABLE v_hdr : t_network_udp_header;
+  BEGIN
+    v_hdr.src_port            := hdr_arr(8)(15 DOWNTO  0);
+    v_hdr.dst_port            := hdr_arr(9)(31 DOWNTO 16);
+    v_hdr.total_length        := hdr_arr(9)(15 DOWNTO  0);
+    v_hdr.checksum            := hdr_arr(10)(31 DOWNTO 16);
+    RETURN v_hdr;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_extract_udp(hdr_arr : t_network_total_header_64b_arr) RETURN t_network_udp_header IS
+    VARIABLE v_hdr : t_network_udp_header;
+  BEGIN
+    v_hdr.src_port            := hdr_arr(4)(47 DOWNTO 32);
+    v_hdr.dst_port            := hdr_arr(4)(31 DOWNTO 16);
+    v_hdr.total_length        := hdr_arr(4)(15 DOWNTO  0);
+    v_hdr.checksum            := hdr_arr(5)(63 DOWNTO 48);
+    RETURN v_hdr;
+  END;
   
   -- Construct the total header array from the individual header records
   FUNCTION func_network_total_header_construct_eth( eth : t_network_eth_header) RETURN t_network_total_header_32b_arr IS
@@ -712,5 +883,174 @@ PACKAGE BODY common_network_total_header_pkg IS
     v_response(5)(15 DOWNTO  0) := TO_UVEC(0, 16);
     RETURN v_response;
   END;
+ 
+
+
+  -- Construct the response headers for headers without word align padding
+  FUNCTION func_network_total_header_no_align_response_eth(eth_arr  : t_network_total_header_32b_arr;
+                                                  mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
+    VARIABLE v_response : t_network_total_header_32b_arr;
+  BEGIN
+    -- Default
+    v_response := eth_arr;
+    -- ETH
+    -- . use input src mac for dst mac
+    v_response(0)               := eth_arr(1)(15 DOWNTO  0) & eth_arr(2)(31 DOWNTO 16);
+    v_response(1)(31 DOWNTO 16) := eth_arr(2)(15 DOWNTO  0);
+    -- . force eth src mac to this node mac address (because the input dst_mac can be via eth broadcast mac)
+    v_response(1)(15 DOWNTO 0)  := mac_addr(47 DOWNTO 32);
+    v_response(2)               := mac_addr(31 DOWNTO  0);
+    RETURN v_response;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_response_eth(eth_arr  : t_network_total_header_64b_arr;
+                                                  mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
+    VARIABLE v_response : t_network_total_header_64b_arr;
+  BEGIN
+    -- Default
+    v_response := eth_arr;
+    -- ETH
+    -- . use input src mac for dst mac
+    v_response(0)(63 DOWNTO 16) := eth_arr(0)(15 DOWNTO  0) & eth_arr(1)(63 DOWNTO 32);
+    -- . force eth src mac to this node mac address (because the input dst_mac can be via eth broadcast mac)
+    v_response(0)(15 DOWNTO  0) := mac_addr(47 DOWNTO 32);
+    v_response(1)(63 DOWNTO 32) := mac_addr(31 DOWNTO  0);
+    RETURN v_response;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_response_arp(arp_arr  : t_network_total_header_32b_arr;
+                                                  mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
+                                                  ip_addr  : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
+    VARIABLE v_response : t_network_total_header_32b_arr;
+  BEGIN
+    -- ETH
+    v_response := func_network_total_header_no_align_response_eth(arp_arr, mac_addr);
+    -- ARP
+    -- . force operation arp reply
+    v_response(5)(15 DOWNTO  0) := TO_UVEC(c_network_arp_oper_reply, 16);
+    -- . force sha to this node mac address
+    v_response(6)               := mac_addr(47 DOWNTO 16);
+    v_response(7)(31 DOWNTO 16) := mac_addr(15 DOWNTO  0);
+    -- . force spa to this node ip address
+    v_response(7)(15 DOWNTO  0) := ip_addr(31 DOWNTO 16);
+    v_response(8)(31 DOWNTO 16) := ip_addr(15 DOWNTO  0);
+    -- . use input sha for tha
+    v_response(8)(15 DOWNTO  0) := arp_arr(6)(31 DOWNTO 16);
+    v_response(9)               := arp_arr(6)(15 DOWNTO  0) & arp_arr(7)(31 DOWNTO 16);
+    -- . use input spa for tpa
+    v_response(10)              := arp_arr(7)(15 DOWNTO  0) & arp_arr(8)(31 DOWNTO 16);
+    RETURN v_response;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_response_arp(arp_arr  : t_network_total_header_64b_arr;
+                                                  mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
+                                                  ip_addr  : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
+    VARIABLE v_response : t_network_total_header_64b_arr;
+  BEGIN
+    -- ETH
+    v_response := func_network_total_header_no_align_response_eth(arp_arr, mac_addr);
+    -- ARP
+    -- . force operation arp reply
+    v_response(3)(47 DOWNTO 32) := TO_UVEC(c_network_arp_oper_reply, 16);
+    -- . force sha to this node mac address
+    v_response(3)(31 DOWNTO  0) := mac_addr(47 DOWNTO 16);
+    v_response(4)(63 DOWNTO 48) := mac_addr(15 DOWNTO  0);
+    -- . force spa to this node ip address
+    v_response(4)(47 DOWNTO 16) := ip_addr(31 DOWNTO  0);
+    -- . use input sha for tha
+    v_response(4)(15 DOWNTO  0) := arp_arr(3)(31 DOWNTO 16);
+    v_response(5)(63 DOWNTO 32) := arp_arr(3)(15 DOWNTO  0) & arp_arr(4)(63 DOWNTO 48);
+    -- . use input spa for tpa
+    v_response(5)(31 DOWNTO  0) := arp_arr(4)(47 DOWNTO 16);
+    RETURN v_response;
+  END;
+ 
+  FUNCTION func_network_total_header_no_align_response_ip(ip_arr   : t_network_total_header_32b_arr;
+                                                 mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
+    VARIABLE v_response : t_network_total_header_32b_arr;
+  BEGIN
+    -- ETH
+    v_response := func_network_total_header_no_align_response_eth(ip_arr, mac_addr);
+    -- IP
+    -- . force ip header checksum to 0
+    v_response(6)(31 DOWNTO 16) := TO_UVEC(0, 16);
+    -- . swap ip dst_addr and ip src_addr
+    v_response(6)(15 DOWNTO  0) := ip_arr(7)(15 DOWNTO  0);
+    v_response(7)(31 DOWNTO 16) := ip_arr(8)(31 DOWNTO 16);
+    v_response(7)(15 DOWNTO  0) := ip_arr(6)(15 DOWNTO  0); 
+    v_response(8)(31 DOWNTO 16) := ip_arr(7)(31 DOWNTO 16);
+    RETURN v_response;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_response_ip(ip_arr   : t_network_total_header_64b_arr;
+                                                 mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
+    VARIABLE v_response : t_network_total_header_64b_arr;
+  BEGIN
+    -- ETH
+    v_response := func_network_total_header_no_align_response_eth(ip_arr, mac_addr);
+    -- IP
+    -- . force ip header checksum to 0
+    v_response(3)(63 DOWNTO 48) := TO_UVEC(0, 16);
+    -- . swap ip dst_addr and ip src_addr
+    v_response(3)(47 DOWNTO 16) := ip_arr(3)(15 DOWNTO  0) & ip_arr(4)(63 DOWNTO 48);
+    v_response(3)(15 DOWNTO  0) := ip_arr(3)(47 DOWNTO 32);
+    v_response(4)(63 DOWNTO 48) := ip_arr(3)(31 DOWNTO 16);
+    RETURN v_response;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_response_icmp(icmp_arr : t_network_total_header_32b_arr;
+                                                   mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
+    VARIABLE v_response : t_network_total_header_32b_arr;
+  BEGIN
+    -- ETH, IP
+    v_response := func_network_total_header_no_align_response_ip(icmp_arr, mac_addr);
+    -- ICMP : force type to icmp reply
+    v_response(8)(15 DOWNTO  8) := TO_UVEC(c_network_icmp_msg_type_reply, 8);
+    -- ICMP : force icmp checksum to 0
+    v_response(9)(31 DOWNTO 16) := TO_UVEC(0, 16);
+    RETURN v_response;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_response_icmp(icmp_arr : t_network_total_header_64b_arr;
+                                          mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
+    VARIABLE v_response : t_network_total_header_64b_arr;
+  BEGIN
+    -- ETH, IP
+    v_response := func_network_total_header_no_align_response_ip(icmp_arr, mac_addr);
+    -- ICMP : force type to icmp reply
+    v_response(4)(47 DOWNTO 40) := TO_UVEC(c_network_icmp_msg_type_reply, 8);
+    -- ICMP : force icmp checksum to 0
+    v_response(4)(31 DOWNTO 16) := TO_UVEC(0, 16);
+    RETURN v_response;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_response_udp(udp_arr  : t_network_total_header_32b_arr;
+                                                  mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_32b_arr IS
+    VARIABLE v_response : t_network_total_header_32b_arr;
+  BEGIN
+    -- ETH, IP
+    v_response := func_network_total_header_no_align_response_ip(udp_arr, mac_addr);
+    -- UDP : swap udp dst port and udp src port
+    v_response(9)               := udp_arr(9)(15 DOWNTO  0) & udp_arr(9)(31 DOWNTO 16);
+    -- UDP : force udp checksum to 0
+    v_response(10)(15 DOWNTO 0) := TO_UVEC(0, 16);
+    RETURN v_response;
+  END;
+  
+  FUNCTION func_network_total_header_no_align_response_udp(udp_arr  : t_network_total_header_64b_arr;
+                                                  mac_addr : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)) RETURN t_network_total_header_64b_arr IS
+    VARIABLE v_response : t_network_total_header_64b_arr;
+  BEGIN
+    -- ETH, IP
+    v_response := func_network_total_header_no_align_response_ip(udp_arr, mac_addr);
+    -- UDP : swap udp dst port and udp src port
+    v_response(5)(63 DOWNTO 32) := udp_arr(5)(47 DOWNTO 32) & udp_arr(5)(63 DOWNTO 48);
+    -- UDP : force udp checksum to 0
+    v_response(5)(15 DOWNTO  0) := TO_UVEC(0, 16);
+    RETURN v_response;
+  END;
   
+
+
+ 
 END common_network_total_header_pkg;
diff --git a/libraries/base/dp/hdllib.cfg b/libraries/base/dp/hdllib.cfg
index 864bb29d1acdfba549ed7fafb99a0c5a7b027f47..49811810201ec2f9fdc82d583e57fe3355bda0ec 100644
--- a/libraries/base/dp/hdllib.cfg
+++ b/libraries/base/dp/hdllib.cfg
@@ -128,6 +128,7 @@ synth_files =
     src/vhdl/dp_field_blk.vhd
     src/vhdl/dp_concat_field_blk.vhd
     src/vhdl/dp_offload_tx.vhd
+    src/vhdl/dp_offload_tx_v3.vhd
     src/vhdl/dp_offload_rx_filter.vhd
     src/vhdl/dp_offload_rx_filter_mm.vhd
     src/vhdl/dp_offload_rx.vhd
@@ -289,6 +290,7 @@ test_bench_files =
     tb/vhdl/tb_tb_dp_xonoff.vhd
     
     tb/vhdl/tb_tb_tb_dp_backpressure.vhd
+    tb/vhdl/tb_dp_offload_tx_v3.vhd
     tb/vhdl/tb_dp_offload_rx_filter.vhd
 
 regression_test_vhdl = 
diff --git a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd
index c8e3d4e667ff1a49202863cf048f982bb954f2f3..47427a6d14f68477f41b1c7e7407a1183427be71 100644
--- a/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd
+++ b/libraries/base/dp/src/vhdl/dp_fifo_fill_eop.vhd
@@ -1,36 +1,38 @@
---------------------------------------------------------------------------------
+-------------------------------------------------------------------------------
 --
--- Copyright (C) 2019
+-- 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.
 --
--- This program is free software: you can redistribute it and/or modify
--- it under the terms of the GNU General Public License as published by
--- the Free Software Foundation, either version 3 of the License, or
--- (at your option) any later version.
---
--- This program is distributed in the hope that it will be useful,
--- but WITHOUT ANY WARRANTY; without even the implied warranty of
--- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--- GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License
--- along with this program.  If not, see <http://www.gnu.org/licenses/>.
---
---------------------------------------------------------------------------------
+-------------------------------------------------------------------------------
+
+-------------------------------------------------------------------------------
+-- Author: R. van der Walle
 
 -- Purpose:
 --   The FIFO starts outputting data when the output is ready and it has been
 --   filled with more than g_fifo_fill words or an eop signal has been received. 
---   Given a fixed frame length, this is useful when the in_val is throttled while 
---   the out_val should not be inactive valid between out_sop to out_eop. 
---   This is necessary for frame transport over a PHY link without separate data 
---   valid signal.
+--   This is useful when the in_val is throttled while the out_val should not be 
+--   inactive valid between out_sop to out_eop. This is necessary for frame 
+--   transport over a PHY link without separate data valid signal.
 -- Description:
 --   Modified version of dp_fifo_fill_core. In addition to a frame being available
 --   after the fifo has been filled sufficiently, a frame is also available when
 --   the in_eop has been received earlier than the specified g_fifo_fill. For
 --   more details, please consult the description of dp_fill_fifo_core.
+-------------------------------------------------------------------------------
 
 LIBRARY IEEE, common_lib, technology_lib;
 USE IEEE.std_logic_1164.ALL;
@@ -82,7 +84,6 @@ ENTITY dp_fifo_fill_eop IS
   );
 END dp_fifo_fill_eop;
 
-
 ARCHITECTURE rtl OF dp_fifo_fill_eop IS
 
   CONSTANT c_fifo_rl          : NATURAL := sel_a_b(g_fifo_fill=0, 1, g_fifo_rl);
@@ -99,6 +100,8 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS
   CONSTANT s_fill    : STD_LOGIC_VECTOR(1 DOWNTO 0) := "01";
   CONSTANT s_output  : STD_LOGIC_VECTOR(1 DOWNTO 0) := "10";
   CONSTANT s_xoff    : STD_LOGIC_VECTOR(1 DOWNTO 0) := "11";
+
+  CONSTANT c_nof_spulse : NATURAL := 3;
   
   SIGNAL state       : STD_LOGIC_VECTOR(1 DOWNTO 0);  -- t_state
   SIGNAL nxt_state   : STD_LOGIC_VECTOR(1 DOWNTO 0);  -- t_state
@@ -121,7 +124,12 @@ ARCHITECTURE rtl OF dp_fifo_fill_eop IS
   SIGNAL pend_src_out : t_dp_sosi;
  
   SIGNAL received_eop : BOOLEAN := FALSE;
-  SIGNAL nxt_received_eop : BOOLEAN := FALSE;
+  SIGNAL nxt_received_eop : BOOLEAN := FALSE; 
+  SIGNAL expecting_eop : BOOLEAN := FALSE;
+  SIGNAL nxt_expecting_eop : BOOLEAN := FALSE;
+  SIGNAL common_spulse_clken : STD_LOGIC_VECTOR(c_nof_spulse DOWNTO 0) := (OTHERS => '1');
+  SIGNAL common_spulse_out_pulse : STD_LOGIC_VECTOR(c_nof_spulse-1 DOWNTO 0);
+  SIGNAL common_spulse_busy : STD_LOGIC_VECTOR(c_nof_spulse-1 DOWNTO 0);
   SIGNAL crossed_domain_snk_in_eop : STD_LOGIC := '0';
 BEGIN
 
@@ -136,7 +144,7 @@ BEGIN
   rd_fill_ctrl <= rd_fill_32b(c_fifo_size_w-1 DOWNTO 0);
 
   gen_dp_fifo_sc : IF g_use_dual_clock=FALSE GENERATE
-    crossed_domain_snk_in_eop <= snk_in.eop;
+    crossed_domain_snk_in_eop <= snk_in.eop; -- No need to transfer eop across clock domains
     u_dp_fifo_sc : ENTITY work.dp_fifo_sc
     GENERIC MAP (
       g_technology     => g_technology,
@@ -175,15 +183,22 @@ BEGIN
   END GENERATE;
   
   gen_dp_fifo_dc : IF g_use_dual_clock=TRUE GENERATE  
-    u_common_spulse : ENTITY common_lib.common_spulse
-    PORT MAP (
-      in_rst  => wr_rst,
-      in_clk  => wr_clk,
-      in_pulse  => snk_in.eop,
-      out_rst => rd_rst,
-      out_clk => rd_clk,
-      out_pulse => crossed_domain_snk_in_eop
-    );
+    -- Transfer eop across clock domain
+    crossed_domain_snk_in_eop <= vector_or(common_spulse_out_pulse);
+    gen_spulse : FOR I IN 0 TO c_nof_spulse-1 GENERATE
+      common_spulse_clken(I+1) <= vector_and(common_spulse_busy(I DOWNTO 0));
+      u_common_spulse : ENTITY common_lib.common_spulse
+      PORT MAP (
+        in_rst  => wr_rst,
+        in_clk  => wr_clk,
+        in_clken => common_spulse_clken(I),
+        in_pulse  => snk_in.eop,
+        in_busy => common_spulse_busy(I),
+        out_rst => rd_rst,
+        out_clk => rd_clk,
+        out_pulse => common_spulse_out_pulse(I)
+      );
+    END GENERATE;
 
     u_dp_fifo_dc : ENTITY work.dp_fifo_dc
     GENERIC MAP (
@@ -239,13 +254,19 @@ BEGIN
         state     <= s_idle;
         i_src_out <= c_dp_sosi_rst;
         received_eop <= FALSE;
+        expecting_eop <= FALSE;
       ELSIF rising_edge(rd_clk) THEN
         xon_reg   <= nxt_xon_reg;
         state     <= nxt_state;
         i_src_out <= nxt_src_out;
         IF crossed_domain_snk_in_eop = '1' THEN
-          received_eop <= TRUE;
+          IF expecting_eop THEN
+            expecting_eop <= FALSE;
+          ELSE
+            received_eop <= TRUE;
+          END IF;
         ELSE
+          expecting_eop <= nxt_expecting_eop;
           received_eop <= nxt_received_eop;
         END IF;
       END IF;
@@ -254,10 +275,11 @@ BEGIN
     nxt_xon_reg <= src_in.xon;  -- register xon to easy timing closure
       
     gen_rl_0 : IF g_fifo_rl=0 GENERATE
-      p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, received_eop)
+      p_state : PROCESS(state, rd_sosi, src_in, xon_reg, rd_fifo_usedw, rd_fill_ctrl, received_eop, expecting_eop)
       BEGIN
         nxt_state <= state;
         nxt_received_eop <= received_eop;
+        nxt_expecting_eop <= expecting_eop;
         rd_siso <= src_in;  -- default acknowledge (RL=1) this input when output is ready
         
         -- The output register stage increase RL=0 to 1, so it matches RL = 1 for src_in.ready
@@ -291,8 +313,12 @@ BEGIN
                 -- if the output is ready, then start outputting the frame
                 IF src_in.ready='1' THEN
                   nxt_src_out <= rd_sosi;  -- output sop that is still at FIFO output (RL=0)
-                  nxt_received_eop <= FALSE;
                   nxt_state <= s_output;
+                  IF received_eop THEN
+                    nxt_received_eop <= FALSE;
+                  ELSE
+                    nxt_expecting_eop <= TRUE;
+                  END IF;
                 END IF;
               END IF;
             END IF;
@@ -335,10 +361,11 @@ BEGIN
         src_out_reg  => i_src_out
       );
       
-      p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, received_eop)
+      p_state : PROCESS(state, src_in, xon_reg, pend_src_out, rd_fifo_usedw, rd_fill_ctrl, received_eop, expecting_eop)
       BEGIN
         nxt_state <= state;
         nxt_received_eop <= received_eop;
+        nxt_expecting_eop <= expecting_eop;
 
         hold_src_in <= src_in;  -- default request (RL=1) new input when output is ready
         
@@ -373,8 +400,12 @@ BEGIN
                 -- if the output is ready, then start outputting the input frame
                 IF src_in.ready='1' THEN
                   nxt_src_out <= pend_src_out;  -- output sop that is still pending in dp_hold_input
-                  nxt_received_eop <= FALSE;
                   nxt_state <= s_output;
+                  IF received_eop THEN
+                    nxt_received_eop <= FALSE;
+                  ELSE
+                    nxt_expecting_eop <= TRUE;
+                  END IF;
                 END IF;
               END IF;
             END IF;
diff --git a/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd b/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..e841015d5418e980fad3d84ca0c347f4df7170f8
--- /dev/null
+++ b/libraries/base/dp/src/vhdl/dp_offload_tx_v3.vhd
@@ -0,0 +1,232 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2017
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose:
+-- . Concatenate a user-defined header to a DP frame e.g. to create an Ethernet frame
+-- Description:
+-- . The header contents can be controlled dynamically by data path or MM control (selected by g_hdr_field_sel)
+-- . The header and data can be concatened at symbol level. The g_symbol_w defines the
+--   resolution of the empty field. The g_data_w must be an integer multiple of the 
+--   g_symbol_w. If the empty field is not used or if the empty field is always 0 then
+--   set g_symbol_w = g_data_w.
+-- . For example to concat header and data for an Ethernet frame use:
+--   - g_data_w = 32 (1GbE) or 64 (10GbE)
+--   - g_symbol_w = c_byte_w = 8 if either the header or the data can have an
+--                  non-zero empty field, so when they are not a multiple of 4 bytes
+--                  (= 32b) or 8 bytes (= 64b).
+--     g_symbol_w = g_data_w if the empty field is always 0, so the number of bits in
+--                  the header and data are an integer number of g_data_w.
+
+
+LIBRARY IEEE, common_lib, technology_lib, mm_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 work.dp_stream_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+
+ENTITY dp_offload_tx_v3 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;
+    mm_clk               : IN  STD_LOGIC; 
+    
+    dp_rst               : IN  STD_LOGIC;
+    dp_clk               : IN  STD_LOGIC;  
+
+    reg_hdr_dat_mosi     : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_hdr_dat_miso     : OUT t_mem_miso;
+
+    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 dp_offload_tx_v3;
+
+
+ARCHITECTURE str OF dp_offload_tx_v3 IS 
+
+  CONSTANT c_dp_field_blk_snk_data_w : NATURAL := field_slv_out_len(field_arr_set_mode(g_hdr_field_arr , "RW"));
+  CONSTANT c_dp_field_blk_src_data_w : NATURAL := g_data_w;
+
+  SIGNAL dbg_c_dp_field_blk_snk_data_w : NATURAL := c_dp_field_blk_snk_data_w;
+  SIGNAL dbg_c_dp_field_blk_src_data_w : NATURAL := c_dp_field_blk_src_data_w;
+  
+  SIGNAL dp_field_blk_snk_in_arr     : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
+  SIGNAL dp_field_blk_snk_out_arr    : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0);
+
+  SIGNAL dp_field_blk_src_out_arr    : t_dp_sosi_arr(g_nof_streams-1 DOWNTO 0);
+  SIGNAL dp_field_blk_src_in_arr     : t_dp_siso_arr(g_nof_streams-1 DOWNTO 0);
+
+  SIGNAL dp_concat_snk_in_2arr       : t_dp_sosi_2arr_2(g_nof_streams-1 DOWNTO 0);
+  SIGNAL dp_concat_snk_out_2arr      : t_dp_siso_2arr_2(g_nof_streams-1 DOWNTO 0);
+
+  SIGNAL reg_hdr_dat_mosi_arr        : t_mem_mosi_arr(g_nof_streams-1 DOWNTO 0);
+  SIGNAL reg_hdr_dat_miso_arr        : t_mem_miso_arr(g_nof_streams-1 DOWNTO 0); 
+
+  SIGNAL mm_fields_slv_out_arr       : t_slv_1024_arr(g_nof_streams-1 DOWNTO 0);
+  SIGNAL field_override_arr          : STD_LOGIC_VECTOR(g_hdr_field_arr'RANGE) := g_hdr_field_sel; --1 override bit per field
+
+         
+BEGIN
+
+  ASSERT c_dp_field_blk_snk_data_w <= c_dp_stream_data_w REPORT "Number of header bits must fit in t_dp_sosi data field." SEVERITY FAILURE;
+  ---------------------------------------------------------------------------------------
+  -- Create header block & concatenate header to offload stream.
+  ---------------------------------------------------------------------------------------
+  p_wire_valid : PROCESS(snk_in_arr, hdr_fields_in_arr)
+  BEGIN
+    FOR i IN 0 TO g_nof_streams-1 LOOP
+      -- default pass on the other snk_in_arr fields as well, especially the sync, bsn and channel can
+      -- be useful to preserve for the packetized output, even though only the sosi.data of the
+      -- packetized output will get transmitted.
+      dp_field_blk_snk_in_arr(i)       <= snk_in_arr(i);
+      -- Prepare packet header as a data block with only one data word, so valid = sop = eop. If
+      -- c_dp_field_blk_snk_data_w > c_dp_field_blk_src_data_w then dp_repack_data in dp_field_blk will
+      -- repack this data word into a multi word header block, else dp_field_blk will pass on the
+      -- dp_field_blk_snk_in_arr as a single word header block.
+      dp_field_blk_snk_in_arr(i).data  <= RESIZE_DP_DATA(hdr_fields_in_arr(i)(field_slv_len(g_hdr_field_arr)-1 DOWNTO 0));
+      dp_field_blk_snk_in_arr(i).valid <= snk_in_arr(i).sop;
+      dp_field_blk_snk_in_arr(i).sop   <= snk_in_arr(i).sop;  -- necessary for single word header block
+      dp_field_blk_snk_in_arr(i).eop   <= snk_in_arr(i).sop;  -- necessary for single word header block
+    END LOOP;
+  END PROCESS;
+
+  gen_dp_field_blk : FOR i IN 0 TO g_nof_streams-1 GENERATE
+
+    -- Both dp_concat inputs must be ready. One of the inputs toggles ready via dp_field_blk.  
+    snk_out_arr(i).ready <= dp_field_blk_snk_out_arr(i).ready AND dp_concat_snk_out_2arr(i)(0).ready;
+    snk_out_arr(i).xon <= src_in_arr(i).xon;
+
+    -- Wire hdr_fields_out_arr 
+    -- MM override bits determine source for each field
+    gen_field_wires: FOR j IN g_hdr_field_arr'RANGE GENERATE
+      hdr_fields_out_arr(i)(field_hi(g_hdr_field_arr, j) DOWNTO field_lo(g_hdr_field_arr, j)) <= mm_fields_slv_out_arr(i)(field_hi(g_hdr_field_arr, j) DOWNTO field_lo(g_hdr_field_arr, j)) 
+                                                                                              WHEN field_override_arr(j) = '1' ELSE 
+                                                                                              hdr_fields_in_arr(i)(field_hi(g_hdr_field_arr, j) DOWNTO field_lo(g_hdr_field_arr, j));
+    END GENERATE;
+
+    ---------------------------------------------------------------------------------------
+    -- mm_fields for MM access to each field
+    ---------------------------------------------------------------------------------------
+    u_mm_fields_slv: ENTITY mm_lib.mm_fields
+    GENERIC MAP(
+      g_field_arr => field_arr_set_mode(g_hdr_field_arr , "RW")
+    )
+    PORT MAP (
+      mm_clk     => mm_clk,
+      mm_rst     => mm_rst,
+  
+      mm_mosi    => reg_hdr_dat_mosi_arr(i),
+      mm_miso    => OPEN, -- Not used
+      
+      slv_clk    => dp_clk,
+      slv_rst    => dp_rst, 
+
+      slv_out    => mm_fields_slv_out_arr(i)(field_slv_len(g_hdr_field_arr)-1 DOWNTO 0)
+    );
+
+
+    -- Create multi-cycle header block from single-cycle wide header SLV
+    u_dp_field_blk : ENTITY work.dp_field_blk
+    GENERIC MAP (
+      g_field_arr      => field_arr_set_mode(g_hdr_field_arr , "RW"),
+      g_field_sel      => g_hdr_field_sel,
+      g_snk_data_w     => c_dp_field_blk_snk_data_w,
+      g_src_data_w     => c_dp_field_blk_src_data_w,
+      g_in_symbol_w    => g_symbol_w,
+      g_out_symbol_w   => g_symbol_w,
+      g_pipeline_ready => g_pipeline_ready
+    )
+    PORT MAP (
+      dp_clk       => dp_clk,
+      dp_rst       => dp_rst,
+
+      mm_clk       => mm_clk,
+      mm_rst       => mm_rst,
+  
+      snk_in       => dp_field_blk_snk_in_arr(i),
+      snk_out      => dp_field_blk_snk_out_arr(i),
+
+      src_out      => dp_field_blk_src_out_arr(i),
+      src_in       => dp_field_blk_src_in_arr(i),
+
+      reg_slv_mosi => reg_hdr_dat_mosi_arr(i),
+      reg_slv_miso => reg_hdr_dat_miso_arr(i)
+    );
+
+    dp_field_blk_src_in_arr(i) <= dp_concat_snk_out_2arr(i)(1);
+
+  END GENERATE;
+
+  -- Prepend the header block to the input block
+  gen_dp_concat : FOR i IN 0 TO g_nof_streams-1 GENERATE
+
+    dp_concat_snk_in_2arr(i)(0) <= snk_in_arr(i);
+    dp_concat_snk_in_2arr(i)(1) <= dp_field_blk_src_out_arr(i);
+
+    u_dp_concat : ENTITY work.dp_concat
+    GENERIC MAP (
+      g_data_w    => g_data_w,
+      g_symbol_w  => g_symbol_w
+    )
+    PORT MAP (
+      rst         => dp_rst,
+      clk         => dp_clk,
+
+      snk_out_arr => dp_concat_snk_out_2arr(i),
+      snk_in_arr  => dp_concat_snk_in_2arr(i),
+
+      src_in      => src_in_arr(i),
+      src_out     => src_out_arr(i)
+    ); 
+  END GENERATE;
+
+  ---------------------------------------------------------------------------------------
+  -- MM control & monitoring
+  ---------------------------------------------------------------------------------------
+  u_common_mem_mux_hdr_dat : ENTITY common_lib.common_mem_mux
+  GENERIC MAP (    
+    g_nof_mosi    => g_nof_streams,
+    g_mult_addr_w => ceil_log2(field_nof_words(g_hdr_field_arr, c_word_w))
+  )
+  PORT MAP (
+    mosi     => reg_hdr_dat_mosi,
+    miso     => reg_hdr_dat_miso,
+    mosi_arr => reg_hdr_dat_mosi_arr,
+    miso_arr => reg_hdr_dat_miso_arr
+  );
+
+END str;
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_fifo_fill_eop.vhd b/libraries/base/dp/tb/vhdl/tb_dp_fifo_fill_eop.vhd
index a6dc8a1a3f9ecb805bd27cf984084b74ac31b1ab..b13ef2a3a54f8fb66878f9347c5d32a808c71717 100644
--- a/libraries/base/dp/tb/vhdl/tb_dp_fifo_fill_eop.vhd
+++ b/libraries/base/dp/tb/vhdl/tb_dp_fifo_fill_eop.vhd
@@ -1,25 +1,26 @@
 -------------------------------------------------------------------------------
 --
--- Copyright (C) 2010
+-- Copyright 2020
 -- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
--- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
 -- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
---
--- This program is free software: you can redistribute it and/or modify
--- it under the terms of the GNU General Public License as published by
--- the Free Software Foundation, either version 3 of the License, or
--- (at your option) any later version.
---
--- This program is distributed in the hope that it will be useful,
--- but WITHOUT ANY WARRANTY; without even the implied warranty of
--- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--- GNU General Public License for more details.
---
--- You should have received a copy of the GNU General Public License
--- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+-- 
+-- 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:
 --   Test bench for dp_fifo_fill_eop
 -- Description:
@@ -33,7 +34,8 @@
 -- > run -all
 -- . signal tb_end will stop the simulation by stopping the clk
 -- . the tb is self checking
--- 
+-------------------------------------------------------------------------------
+
 LIBRARY IEEE, common_lib;
 USE IEEE.std_logic_1164.ALL;
 USE IEEE.numeric_std.ALL;
diff --git a/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd b/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..08566621228bb4e41e719517306f6497d1c6e96e
--- /dev/null
+++ b/libraries/base/dp/tb/vhdl/tb_dp_offload_tx_v3.vhd
@@ -0,0 +1,436 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose:
+-- . Test bench for dp_offload_tx_v3 and dp_offload_rx
+-- Description:
+--                 u_tx                     u_rx
+--                 ___________________      ___________________ 
+--                |dp_offload_tx_v3|    |dp_offload_rx      |
+-- stimuli_src -->|                   |--->|                   |--> verify_snk
+--                | in            out | |  | in            out |
+--                |___________________| |  |___________________|
+--                                      |
+--                               link_offload_sosi
+-- Usage:                                  
+-- > as 10
+-- > run -all
+--
+
+LIBRARY IEEE, common_lib;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_lfsr_sequences_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE work.dp_stream_pkg.ALL;
+USE work.tb_dp_pkg.ALL;
+
+
+ENTITY tb_dp_offload_tx_v3 IS
+  GENERIC (
+    -- general
+    g_flow_control_stimuli   : t_dp_flow_control_enum := e_pulse;  -- always e_active, e_random or e_pulse flow control
+    g_flow_control_verify    : t_dp_flow_control_enum := e_active;  -- always e_active, e_random or e_pulse flow control
+    -- specific
+    g_data_w                 : NATURAL := 64;
+    g_nof_repeat             : NATURAL := 100;
+    g_pkt_len                : NATURAL := 240;
+    g_pkt_gap                : NATURAL := 16
+  );
+END tb_dp_offload_tx_v3;
+
+
+ARCHITECTURE tb OF tb_dp_offload_tx_v3 IS
+
+  CONSTANT c_mm_clk_period : TIME := 1 ns;
+  CONSTANT c_dp_clk_period : TIME := 5 ns;
+
+  -- dp_stream_stimuli
+  CONSTANT c_stimuli_pulse_active     : NATURAL := 3;
+  CONSTANT c_stimuli_pulse_period     : NATURAL := 4;
+
+  -- dp_stream_verify
+  CONSTANT c_verify_pulse_active      : NATURAL := 1;
+  CONSTANT c_verify_pulse_period      : NATURAL := 5;
+
+  CONSTANT c_data_max                 : UNSIGNED(g_data_w-1 DOWNTO 0) := (OTHERS=>'1');
+  CONSTANT c_dsp_max                  : UNSIGNED(g_data_w-1 DOWNTO 0) := (OTHERS=>'1');
+
+  --CONSTANT c_verify_snk_in_cnt_max    : t_dp_sosi_unsigned := c_dp_sosi_unsigned_rst;  -- default 0 is no wrap
+  CONSTANT c_verify_snk_in_cnt_max    : t_dp_sosi_unsigned := TO_DP_SOSI_UNSIGNED('0', '0', '0', '0', c_data_max, c_dsp_max, c_dsp_max, c_unsigned_0, c_unsigned_0, c_unsigned_0, c_unsigned_0);
+  CONSTANT c_verify_snk_in_cnt_gap    : t_dp_sosi_unsigned := c_dp_sosi_unsigned_ones; -- default only accept increment +1
+
+  CONSTANT c_expected_pkt_len         : NATURAL := g_pkt_len;
+  CONSTANT c_sync_period              : NATURAL := 5;
+  CONSTANT c_sync_offset              : NATURAL := 2;
+  
+  CONSTANT c_hdr_len                  : NATURAL := 7;
+  CONSTANT c_wait_last_evt            : NATURAL := 100 + g_nof_repeat * c_hdr_len;
+
+  -----------------------------------------------------------------------------
+  -- Tx offload
+  -----------------------------------------------------------------------------
+  -- From apertif_udp_offload_pkg.vhd:
+  CONSTANT c_udp_offload_nof_hdr_fields : NATURAL := 3+12+4+3; -- 448b; 7 64b words
+  -- Notes: 
+  -- . pre-calculated ip_header_checksum is valid only for UNB0, FN0 targeting IP 10.10.10.10
+  -- . udp_total_length = 176 beamlets * 64b / 8b = 1408B + 14 DP bytes + 8 UDP bytes = 1430B 
+  CONSTANT c_udp_offload_hdr_field_arr : t_common_field_arr(c_udp_offload_nof_hdr_fields-1 DOWNTO 0) := (
+         ( field_name_pad("eth_dst_mac"            ), "RW", 48, field_default(x"001B214368AC") ),
+         ( 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("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(1450) ), 
+         ( 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(29928) ),
+         ( field_name_pad("ip_src_addr"            ), "RW", 32, field_default(x"C0A80009") ),
+         ( field_name_pad("ip_dst_addr"            ), "RW", 32, field_default(x"C0A80001") ),
+         ( 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"       ), "RW", 16, field_default(1430) ),
+         ( field_name_pad("udp_checksum"           ), "RW", 16, field_default(0) ),
+         ( field_name_pad("dp_reserved"            ), "RW", 47, field_default(0) ),
+         ( field_name_pad("dp_sync"                ), "RW",  1, field_default(0) ),
+         ( field_name_pad("dp_bsn"                 ), "RW", 64, field_default(0) ) );
+
+  -- From apertif_unb1_fn_beamformer_udp_offload.vhd:
+  -- Override ('1') only the Ethernet fields so we can use MM defaults there.
+  CONSTANT c_hdr_field_ovr_init : STD_LOGIC_VECTOR(c_udp_offload_nof_hdr_fields-1 DOWNTO 0) := "101"&"111111111111"&"1111"&"100";
+
+  CONSTANT c_NODE_ID                    : STD_LOGIC_VECTOR(7 DOWNTO 0) := TO_UVEC(0, 8);
+
+  SIGNAL id_backplane                   : STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+  SIGNAL id_chip                        : STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+
+  SIGNAL dp_fifo_sc_src_in              : t_dp_siso := c_dp_siso_rdy;
+  SIGNAL dp_fifo_sc_src_out             : t_dp_sosi;
+
+  SIGNAL dp_offload_tx_snk_in_arr       : t_dp_sosi_arr(0 DOWNTO 0);
+  SIGNAL dp_offload_tx_snk_out_arr      : t_dp_siso_arr(0 DOWNTO 0);
+  
+  SIGNAL tx_hdr_fields_in_arr           : t_slv_1024_arr(0 DOWNTO 0);
+  SIGNAL tx_hdr_fields_out_arr          : t_slv_1024_arr(0 DOWNTO 0);
+  
+  SIGNAL reg_dp_offload_tx_hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL reg_dp_offload_tx_hdr_dat_miso : t_mem_miso;
+
+  -----------------------------------------------------------------------------
+  -- Link
+  -----------------------------------------------------------------------------
+  
+  SIGNAL tx_offload_sosi_arr       : t_dp_sosi_arr(0 DOWNTO 0);
+  SIGNAL tx_offload_siso_arr       : t_dp_siso_arr(0 DOWNTO 0);
+
+  SIGNAL link_offload_sosi_arr     : t_dp_sosi_arr(0 DOWNTO 0);
+  SIGNAL link_offload_siso_arr     : t_dp_siso_arr(0 DOWNTO 0);
+
+  -----------------------------------------------------------------------------
+  -- Rx offload
+  -----------------------------------------------------------------------------
+  SIGNAL dp_offload_rx_src_out_arr      : t_dp_sosi_arr(0 DOWNTO 0);
+  SIGNAL dp_offload_rx_src_in_arr       : t_dp_siso_arr(0 DOWNTO 0);
+  
+  SIGNAL rx_hdr_fields_out_arr          : t_slv_1024_arr(0 DOWNTO 0);
+  SIGNAL rx_hdr_fields_raw_arr          : t_slv_1024_arr(0 DOWNTO 0);
+  
+  SIGNAL reg_dp_offload_rx_hdr_dat_mosi : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL reg_dp_offload_rx_hdr_dat_miso : t_mem_miso;
+
+  -----------------------------------------------------------------------------
+  -- Test
+  -----------------------------------------------------------------------------
+  SIGNAL mm_clk                     : STD_LOGIC := '1';
+  SIGNAL mm_rst                     : STD_LOGIC := '1';
+  SIGNAL dp_clk                     : STD_LOGIC := '1';
+  SIGNAL dp_rst                     : STD_LOGIC := '1';
+  SIGNAL tb_end                     : STD_LOGIC := '0';
+  
+  SIGNAL stimuli_src_in             : t_dp_siso := c_dp_siso_rdy;
+  SIGNAL stimuli_src_out            : t_dp_sosi;
+  SIGNAL stimuli_src_out_data       : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
+
+  SIGNAL verify_snk_in_enable       : t_dp_sosi_sl := c_dp_sosi_sl_rst;
+  SIGNAL last_snk_in                : t_dp_sosi;
+  SIGNAL last_snk_in_evt            : STD_LOGIC;
+  SIGNAL verify_last_snk_in_evt     : t_dp_sosi_sl := c_dp_sosi_sl_rst;
+
+  SIGNAL verify_snk_out             : t_dp_siso := c_dp_siso_rdy;
+  SIGNAL verify_snk_in              : t_dp_sosi;
+  SIGNAL verify_snk_in_data         : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
+
+BEGIN
+
+  ------------------------------------------------------------------------------
+  -- Clock & reset
+  ------------------------------------------------------------------------------
+  mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2;
+  mm_rst <= '1', '0' AFTER c_mm_clk_period*7;
+  dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2;
+  dp_rst <= '1', '0' AFTER c_dp_clk_period*7;
+
+  ------------------------------------------------------------------------------
+  -- DATA GENERATION
+  ------------------------------------------------------------------------------
+
+  u_dp_stream_stimuli : ENTITY work.dp_stream_stimuli
+  GENERIC MAP (
+    g_instance_nr    => 0,                        -- only one stream so choose index 0
+    -- flow control
+    g_random_w       => 15,                       -- use different random width for stimuli and for verify to have different random sequences
+    g_pulse_active   => c_stimuli_pulse_active,
+    g_pulse_period   => c_stimuli_pulse_period,
+    g_flow_control   => g_flow_control_stimuli,   -- always active, random or pulse flow control
+    -- initializations
+    g_sync_period    => c_sync_period,
+    g_sync_offset    => c_sync_offset,
+    -- specific
+    g_in_dat_w       => g_data_w,
+    g_nof_repeat     => g_nof_repeat,
+    g_pkt_len        => g_pkt_len,
+    g_pkt_gap        => g_pkt_gap,
+    g_wait_last_evt  => c_wait_last_evt
+  )
+  PORT MAP (
+    rst                 => dp_rst,
+    clk                 => dp_clk,
+
+    -- Generate stimuli
+    src_in              => stimuli_src_in,
+    src_out             => stimuli_src_out,
+
+    -- End of stimuli
+    last_snk_in         => last_snk_in,      -- expected verify_snk_in after end of stimuli
+    last_snk_in_evt     => last_snk_in_evt,  -- trigger verify to verify the last_snk_in
+    tb_end              => tb_end            -- signal end of tb as far as this dp_stream_stimuli is concerned
+  );
+
+
+  ------------------------------------------------------------------------------
+  -- DATA VERIFICATION
+  ------------------------------------------------------------------------------
+
+  -- Select fields that need to be verified
+  -- . during the test
+  verify_snk_in_enable.sync    <= '1';
+  verify_snk_in_enable.bsn     <= '1';
+  verify_snk_in_enable.data    <= '1';
+  verify_snk_in_enable.re      <= '0';
+  verify_snk_in_enable.im      <= '0';
+  verify_snk_in_enable.valid   <= '1';
+  verify_snk_in_enable.sop     <= '1';
+  verify_snk_in_enable.eop     <= '1';
+  verify_snk_in_enable.empty   <= '0';
+  verify_snk_in_enable.channel <= '0';
+  verify_snk_in_enable.err     <= '0';
+
+  -- . after the test
+  verify_last_snk_in_evt.sync    <= last_snk_in_evt;
+  verify_last_snk_in_evt.bsn     <= last_snk_in_evt;   -- thanks to using rx_hdr_fields_raw_arr for bsn field
+  verify_last_snk_in_evt.data    <= last_snk_in_evt;
+  verify_last_snk_in_evt.re      <= '0';
+  verify_last_snk_in_evt.im      <= '0';
+  verify_last_snk_in_evt.valid   <= last_snk_in_evt;
+  verify_last_snk_in_evt.sop     <= last_snk_in_evt;
+  verify_last_snk_in_evt.eop     <= last_snk_in_evt;
+  verify_last_snk_in_evt.empty   <= '0';
+  verify_last_snk_in_evt.channel <= '0';
+  verify_last_snk_in_evt.err     <= '0';
+
+  u_dp_stream_verify : ENTITY work.dp_stream_verify
+  GENERIC MAP (
+    g_instance_nr    => 0,                        -- only one stream so choose index 0
+    -- flow control
+    g_random_w       => 14,                       -- use different random width for stimuli and for verify to have different random sequences
+    g_pulse_active   => c_verify_pulse_active,
+    g_pulse_period   => c_verify_pulse_period,
+    g_flow_control   => g_flow_control_verify,    -- always active, random or pulse flow control
+    -- initializations
+    g_sync_period    => c_sync_period,
+    g_sync_offset    => c_sync_offset,
+    g_snk_in_cnt_max => c_verify_snk_in_cnt_max,
+    g_snk_in_cnt_gap => c_verify_snk_in_cnt_gap,
+    -- specific
+    g_in_dat_w       => g_data_w,
+    g_pkt_len        => c_expected_pkt_len
+  )
+  PORT MAP (
+    rst                        => dp_rst,
+    clk                        => dp_clk,
+
+    -- Verify data
+    snk_out                    => verify_snk_out,
+    snk_in                     => verify_snk_in,
+
+    -- During stimuli
+    verify_snk_in_enable       => verify_snk_in_enable,  -- enable verify to verify that the verify_snk_in fields are incrementing
+
+    -- End of stimuli
+    expected_snk_in            => last_snk_in,            -- expected verify_snk_in after end of stimuli
+    verify_expected_snk_in_evt => verify_last_snk_in_evt  -- trigger verify to verify the last_snk_in
+  );
+
+  ------------------------------------------------------------------------------
+  -- DUT offload Tx
+  ------------------------------------------------------------------------------
+  stimuli_src_in <= c_dp_siso_rdy;
+  
+  -- Use FIFO to mimic apertif_unb1_fn_beamformer_udp_offload.vhd, without FIFO dp_stream_stimuli
+  -- would handle the back pressure
+  u_dp_fifo_sc : ENTITY work.dp_fifo_sc
+  GENERIC MAP (
+    g_data_w         => g_data_w,
+    g_bsn_w          => 64,
+    g_use_sync       => TRUE,
+    g_use_bsn        => TRUE,
+    g_fifo_size      => 1024
+  )
+  PORT MAP (
+    rst         => dp_rst,
+    clk         => dp_clk,
+
+    snk_out     => OPEN,     -- stimuli_src_in
+    snk_in      => stimuli_src_out,
+
+    src_in      => dp_fifo_sc_src_in,
+    src_out     => dp_fifo_sc_src_out
+  );
+  
+  dp_offload_tx_snk_in_arr(0) <= dp_fifo_sc_src_out;
+  dp_fifo_sc_src_in           <= dp_offload_tx_snk_out_arr(0);
+
+  -- Extract the chip and backplane numbers from c_NODE_ID
+  id_backplane <= RESIZE_UVEC(c_NODE_ID(7 DOWNTO 3), c_byte_w);
+  id_chip      <= RESIZE_UVEC(c_NODE_ID(2 DOWNTO 0), c_byte_w);
+
+  -- Wire the hardwired header fields to DP signals and c_NODE_ID
+  tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "eth_src_mac" ) DOWNTO field_lo(c_udp_offload_hdr_field_arr, "eth_src_mac"     )) <= x"00228608" & id_backplane & id_chip;
+  tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "udp_src_port") DOWNTO field_lo(c_udp_offload_hdr_field_arr, "udp_src_port"    )) <= x"D0" & c_NODE_ID;
+  tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "udp_dst_port") DOWNTO field_lo(c_udp_offload_hdr_field_arr, "udp_dst_port"    )) <= x"D0" & c_NODE_ID;
+  tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "ip_src_addr" ) DOWNTO field_lo(c_udp_offload_hdr_field_arr, "ip_src_addr"     )) <= x"0A63" & id_backplane & INCR_UVEC(id_chip, 1);
+                                                                                                               
+  tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "dp_sync"     ) DOWNTO field_lo(c_udp_offload_hdr_field_arr, "dp_sync"         )) <= slv(dp_offload_tx_snk_in_arr(0).sync);
+  tx_hdr_fields_in_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "dp_bsn"      ) DOWNTO field_lo(c_udp_offload_hdr_field_arr, "dp_bsn"          )) <=     dp_offload_tx_snk_in_arr(0).bsn(63 DOWNTO 0); 
+
+  u_tx : ENTITY work.dp_offload_tx_v3
+  GENERIC MAP (
+    g_nof_streams    => 1,
+    g_data_w         => g_data_w,
+    g_symbol_w       => g_data_w,
+    g_hdr_field_arr  => c_udp_offload_hdr_field_arr,
+    g_hdr_field_sel  => c_hdr_field_ovr_init
+  ) 
+  PORT MAP (
+    mm_rst                => mm_rst,
+    mm_clk                => mm_clk,
+    
+    dp_rst                => dp_rst,
+    dp_clk                => dp_clk,
+
+    reg_hdr_dat_mosi      => reg_dp_offload_tx_hdr_dat_mosi,
+    reg_hdr_dat_miso      => reg_dp_offload_tx_hdr_dat_miso,
+
+    snk_in_arr            => dp_offload_tx_snk_in_arr,
+    snk_out_arr           => dp_offload_tx_snk_out_arr,
+
+    src_out_arr           => tx_offload_sosi_arr,
+    src_in_arr            => tx_offload_siso_arr,
+
+    hdr_fields_in_arr     => tx_hdr_fields_in_arr,
+    hdr_fields_out_arr    => tx_hdr_fields_out_arr
+  );
+
+  ------------------------------------------------------------------------------
+  -- Link
+  ------------------------------------------------------------------------------
+
+  p_link_offload : PROCESS(tx_offload_sosi_arr, link_offload_siso_arr)
+  BEGIN
+    -- Model active packet fields of tr_10GbE Rx sosi output interface
+    link_offload_sosi_arr(0)       <= c_dp_sosi_rst;
+    link_offload_sosi_arr(0).data  <= tx_offload_sosi_arr(0).data;
+    link_offload_sosi_arr(0).empty <= tx_offload_sosi_arr(0).empty;
+    link_offload_sosi_arr(0).valid <= tx_offload_sosi_arr(0).valid;
+    link_offload_sosi_arr(0).sop   <= tx_offload_sosi_arr(0).sop;
+    link_offload_sosi_arr(0).eop   <= tx_offload_sosi_arr(0).eop;
+    
+    tx_offload_siso_arr <= (OTHERS=>c_dp_siso_rdy);
+  END PROCESS;
+  
+  ------------------------------------------------------------------------------
+  -- DUT offload Rx
+  ------------------------------------------------------------------------------
+
+  u_rx : ENTITY work.dp_offload_rx
+  GENERIC MAP (
+    g_nof_streams         => 1,
+    g_data_w              => g_data_w,
+    g_hdr_field_arr       => c_udp_offload_hdr_field_arr,
+    g_remove_crc          => FALSE,
+    g_crc_nof_words       => 0 
+  )
+  PORT MAP (
+    mm_rst                => mm_rst,
+    mm_clk                => mm_clk,
+    
+    dp_rst                => dp_rst,
+    dp_clk                => dp_clk,
+  
+    reg_hdr_dat_mosi      => reg_dp_offload_rx_hdr_dat_mosi,
+    reg_hdr_dat_miso      => reg_dp_offload_rx_hdr_dat_miso,
+  
+    snk_in_arr            => link_offload_sosi_arr,
+    snk_out_arr           => link_offload_siso_arr,
+               
+    src_out_arr           => dp_offload_rx_src_out_arr,
+    src_in_arr            => dp_offload_rx_src_in_arr,
+  
+    hdr_fields_out_arr    => rx_hdr_fields_out_arr,
+    hdr_fields_raw_arr    => rx_hdr_fields_raw_arr
+  );
+  
+  p_restore_sync_bsn : PROCESS(dp_offload_rx_src_out_arr, rx_hdr_fields_out_arr)
+  BEGIN
+    verify_snk_in      <= dp_offload_rx_src_out_arr(0);
+    verify_snk_in.sync <=          sl(rx_hdr_fields_out_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "dp_sync") DOWNTO field_lo(c_udp_offload_hdr_field_arr, "dp_sync" )));
+    verify_snk_in.bsn  <= RESIZE_UVEC(rx_hdr_fields_raw_arr(0)(field_hi(c_udp_offload_hdr_field_arr, "dp_bsn" ) DOWNTO field_lo(c_udp_offload_hdr_field_arr, "dp_bsn"  )), c_dp_stream_bsn_w);
+  END PROCESS;
+
+  dp_offload_rx_src_in_arr    <= (OTHERS=>c_dp_siso_rdy);
+  dp_offload_rx_src_in_arr(0) <= verify_snk_out;
+  
+  ------------------------------------------------------------------------------
+  -- Auxiliary
+  ------------------------------------------------------------------------------
+
+  -- Map to slv to ease monitoring in wave window
+  stimuli_src_out_data <= stimuli_src_out.data(g_data_w-1 DOWNTO 0);
+  verify_snk_in_data   <= verify_snk_in.data(g_data_w-1 DOWNTO 0);
+
+END tb;
diff --git a/libraries/io/nw_10GbE/hdllib.cfg b/libraries/io/nw_10GbE/hdllib.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..51c46a705a0d9f85106860cc0590e7764976a39b
--- /dev/null
+++ b/libraries/io/nw_10GbE/hdllib.cfg
@@ -0,0 +1,27 @@
+hdl_lib_name = nw_10GbE
+hdl_library_clause_name = nw_10GbE_lib
+hdl_lib_uses_synth = common dp technology tech_mac_10g tr_10GbE 
+hdl_lib_uses_sim = 
+hdl_lib_technology = 
+
+synth_files =
+    src/vhdl/nw_arp_request.vhd
+    src/vhdl/nw_ping_response.vhd
+    src/vhdl/nw_10GbE.vhd
+
+test_bench_files = 
+    tb/vhdl/tb_nw_10GbE.vhd
+    tb/vhdl/tb_tb_nw_10GbE.vhd
+    tb/vhdl/tb_nw_ping_response.vhd
+    tb/vhdl/tb_nw_arp_request.vhd
+
+#regression_test_vhdl = 
+#    tb/vhdl/tb_nw_10GbE.vhd
+#    tb/vhdl/tb_tb_nw_10GbE.vhd
+
+
+[modelsim_project_file]
+
+
+[quartus_project_file]
+
diff --git a/libraries/io/nw_10GbE/src/vhdl/nw_10GbE.vhd b/libraries/io/nw_10GbE/src/vhdl/nw_10GbE.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..2df5755b77df0eb5972e90bcb37344756cd6b1a9
--- /dev/null
+++ b/libraries/io/nw_10GbE/src/vhdl/nw_10GbE.vhd
@@ -0,0 +1,291 @@
+-- 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: Adds basic networking capabilities to tr_10GbE by sending ARP request
+-- packets on a predefined interval as well as respond to PING requests.
+--   To avoid that the packet transmission will get a gap that will abort it.
+--   The average DP data rate depends on dp_clk and on the DP data valid.
+-- NOTE: When connected to a PC make sure you can handle backpressure for 
+--       a large amount of clock cycles (can be > 16k). This backpressure 
+--       is due to the possibility of receiving pause frames from the PC.
+--       If your design cannot handle the backpressure from PC, you should
+--       disable it on the PC side. This can be done with ethtool:
+--       # ethtool -A ethX autoneg off rx off tx off
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, dp_lib, technology_lib, tech_mac_10g_lib, tr_10GbE_lib;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
+USE common_lib.common_interface_layers_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE tech_mac_10g_lib.tech_mac_10g_component_pkg.ALL;
+
+ENTITY nw_10GbE IS
+  GENERIC (
+    g_technology             : NATURAL := c_tech_select_default;
+    g_sim                    : BOOLEAN;
+    g_sim_level              : NATURAL := 1; -- 0 = use IP; 1 = use fast serdes model
+    g_nof_macs               : NATURAL;
+    g_direction              : STRING := "TX_RX";  -- "TX_RX", "TX_ONLY", "RX_ONLY"
+    g_use_mdio               : BOOLEAN := FALSE;
+    g_mdio_epcs_dis          : BOOLEAN := FALSE; -- TRUE disables EPCS on init; e.g. to target a 10GbE card in PC that does not support it 
+    g_tx_fifo_fill           : NATURAL := 10;    -- Release tx packet only when sufficiently data is available such that no data gaps are introduced. 
+    g_tx_fifo_size           : NATURAL := 256;   -- 2 * 32b * 256 = 2 M9K (DP interface has 64b data, so at least 2 M9K needed)
+    g_rx_fifo_size           : NATURAL := 256;   -- 2 * 32b * 256 = 2 M9K (DP interface has 64b data, so at least 2 M9K needed)
+    g_word_alignment_padding : BOOLEAN := FALSE;
+    g_arp_period_s           : NATURAL := 30;
+    g_ip_hdr_field_arr       : t_common_field_arr
+  );
+  PORT (
+    -- Transceiver PLL reference clock
+    tr_ref_clk_644   : IN  STD_LOGIC := '0';   -- 644.531250 MHz for 10GBASE-R
+    tr_ref_clk_312   : IN  STD_LOGIC := '0';   -- 312.5      MHz for 10GBASE-R
+    tr_ref_clk_156   : IN  STD_LOGIC := '0';   -- 156.25     MHz for 10GBASE-R or for XAUI
+    tr_ref_rst_156   : IN  STD_LOGIC := '0';   --                for 10GBASE-R or for XAUI
+    
+    -- Calibration & reconfig clock
+    cal_rec_clk         : IN  STD_LOGIC := '0';   -- for XAUI;
+    
+    -- MM interface
+    mm_rst              : IN  STD_LOGIC;
+    mm_clk              : IN  STD_LOGIC;
+    
+    reg_mac_mosi        : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_mac_miso        : OUT t_mem_miso;
+
+    xaui_mosi           : IN  t_mem_mosi := c_mem_mosi_rst;
+    xaui_miso           : OUT t_mem_miso;
+    
+    reg_eth10g_mosi     : IN  t_mem_mosi := c_mem_mosi_rst;  -- ETH10G (link status register)
+    reg_eth10g_miso     : OUT t_mem_miso; 
+    
+    mdio_mosi_arr       : IN  t_mem_mosi_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS=>c_mem_mosi_rst);
+    mdio_miso_arr       : OUT t_mem_miso_arr(g_nof_macs-1 DOWNTO 0);
+
+    reg_10gbase_r_24_mosi   : IN  t_mem_mosi := c_mem_mosi_rst; 
+    reg_10gbase_r_24_miso   : OUT t_mem_miso;
+
+    -- DP interface
+    dp_rst              : IN  STD_LOGIC := '0';
+    dp_clk              : IN  STD_LOGIC := '0';
+    dp_pps              : IN  STD_LOGIC := '0';
+
+    snk_out_arr         : OUT t_dp_siso_arr(g_nof_macs-1 DOWNTO 0);
+    snk_in_arr          : IN  t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS=>c_dp_sosi_rst);
+
+    src_in_arr          : IN  t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
+    src_out_arr         : OUT t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0);
+    
+    -- Serial XAUI IO
+    xaui_tx_arr         : OUT t_xaui_arr(g_nof_macs-1 DOWNTO 0);
+    xaui_rx_arr         : IN  t_xaui_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
+
+    -- Serial IO
+    serial_tx_arr       : OUT STD_LOGIC_VECTOR(g_nof_macs-1 downto 0);
+    serial_rx_arr       : IN  STD_LOGIC_VECTOR(g_nof_macs-1 downto 0) := (OTHERS=>'0');
+  
+    -- MDIO interface
+    mdio_rst            : OUT STD_LOGIC;
+    mdio_mdc_arr        : OUT STD_LOGIC_VECTOR(g_nof_macs-1 DOWNTO 0);       
+    mdio_mdat_in_arr    : IN  STD_LOGIC_VECTOR(g_nof_macs-1 DOWNTO 0) := (OTHERS=>'0');
+    mdio_mdat_oen_arr   : OUT STD_LOGIC_VECTOR(g_nof_macs-1 DOWNTO 0);
+  
+    hdr_fields_in_arr   : IN  t_slv_1024_arr(g_nof_macs-1 DOWNTO 0)
+  );
+END nw_10GbE;
+
+ARCHITECTURE str OF nw_10GbE IS
+
+  CONSTANT c_nof_mux_streams : NATURAL := 3;
+
+  SIGNAL nw_arp_request_src_out_arr : t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL nw_arp_request_src_in_arr  : t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
+  
+  SIGNAL nw_ping_response_src_out_arr : t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL nw_ping_response_src_in_arr  : t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
+  
+  SIGNAL dp_mux_snk_in_2arr  : t_dp_sosi_2arr_3(g_nof_macs-1 DOWNTO 0) := (OTHERS => (OTHERS => c_dp_sosi_rst));
+  SIGNAL dp_mux_snk_out_2arr : t_dp_siso_2arr_3(g_nof_macs-1 DOWNTO 0);
+
+  SIGNAL tr_10GbE_snk_in_arr  : t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0);
+  SIGNAL tr_10GbE_snk_out_arr : t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
+  SIGNAL tr_10GbE_src_out_arr : t_dp_sosi_arr(g_nof_macs-1 DOWNTO 0);
+  SIGNAL tr_10GbE_src_in_arr  : t_dp_siso_arr(g_nof_macs-1 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
+
+  SIGNAL eth_src_mac_arr : t_slv_48_arr(g_nof_macs-1 DOWNTO 0); 
+  SIGNAL ip_src_addr_arr : t_slv_32_arr(g_nof_macs-1 DOWNTO 0); 
+  SIGNAL ip_dst_addr_arr : t_slv_32_arr(g_nof_macs-1 DOWNTO 0); 
+
+BEGIN
+
+  src_out_arr <= tr_10GbE_src_out_arr;
+  tr_10GbE_src_in_arr <= src_in_arr;
+
+  gen_nof_macs : FOR I in 0 TO g_nof_macs-1 GENERATE
+
+    -- Wire hdr_fields_in_arr  
+    eth_src_mac_arr(I) <= hdr_fields_in_arr(I)(field_hi(g_ip_hdr_field_arr, "eth_src_mac") DOWNTO field_lo(g_ip_hdr_field_arr, "eth_src_mac"));
+    ip_src_addr_arr(I) <= hdr_fields_in_arr(I)(field_hi(g_ip_hdr_field_arr, "ip_src_addr") DOWNTO field_lo(g_ip_hdr_field_arr, "ip_src_addr"));
+    ip_dst_addr_arr(I) <= hdr_fields_in_arr(I)(field_hi(g_ip_hdr_field_arr, "ip_dst_addr") DOWNTO field_lo(g_ip_hdr_field_arr, "ip_dst_addr"));
+
+    ---------------------------------------------------------------------------------------
+    -- ARP request 
+    ---------------------------------------------------------------------------------------
+    u_nw_arp_request : ENTITY work.nw_arp_request
+    GENERIC MAP (
+      g_period_s => g_arp_period_s
+    )
+    PORT MAP (
+      dp_pps => dp_pps,
+      dp_clk => dp_clk,
+      dp_rst => dp_rst,
+
+      src_out => nw_arp_request_src_out_arr(I),
+      src_in  => nw_arp_request_src_in_arr(I),
+
+      arp_sha => eth_src_mac_arr(I), 
+      arp_spa => ip_src_addr_arr(I),  
+      arp_tpa => ip_dst_addr_arr(I)
+    );
+
+    ---------------------------------------------------------------------------------------
+    -- PING response
+    ---------------------------------------------------------------------------------------
+    u_nw_ping_response : ENTITY work.nw_ping_response
+    GENERIC MAP (
+      g_technology => g_technology
+    )
+    PORT MAP (
+      clk => dp_clk,
+      rst => dp_rst,
+
+      snk_in  => tr_10GbE_src_out_arr(I),
+
+      src_in  => nw_ping_response_src_in_arr(I),
+      src_out => nw_ping_response_src_out_arr(I),
+    
+      eth_src_mac => eth_src_mac_arr(I)
+    );
+
+    ---------------------------------------------------------------------------------------
+    -- dp_mux to multiplex the three possible data streams
+    ---------------------------------------------------------------------------------------
+    dp_mux_snk_in_2arr(I)(0) <= snk_in_arr(I);
+    dp_mux_snk_in_2arr(I)(1) <= nw_ping_response_src_out_arr(I);
+    dp_mux_snk_in_2arr(I)(2) <= nw_arp_request_src_out_arr(I);
+
+    snk_out_arr(I)                 <= dp_mux_snk_out_2arr(I)(0);
+    nw_ping_response_src_in_arr(I) <= dp_mux_snk_out_2arr(I)(1);
+    nw_arp_request_src_in_arr(I)   <= dp_mux_snk_out_2arr(I)(2);
+
+    u_dp_mux : ENTITY dp_lib.dp_mux
+    GENERIC MAP (
+      g_nof_input => c_nof_mux_streams,
+      g_sel_ctrl_invert => TRUE,
+      g_fifo_size => array_init(0,c_nof_mux_streams), --no FIFO used but must match g_nof_input
+      g_fifo_fill => array_init(0,c_nof_mux_streams) --no FIFO used but must match g_nof_input
+    )
+    PORT MAP (
+      clk => dp_clk,
+      rst => dp_rst,
+
+      snk_in_arr  => dp_mux_snk_in_2arr(I),
+      snk_out_arr => dp_mux_snk_out_2arr(I),
+   
+      src_out => tr_10GbE_snk_in_arr(I),
+      src_in  => tr_10GbE_snk_out_arr(I)
+    );
+
+  END GENERATE;
+
+  -------------
+  -- tr_10GbE
+  -------------
+  u_tr_10GbE: ENTITY tr_10GbE_lib.tr_10GbE
+  GENERIC MAP (
+    g_technology             => g_technology, 
+    g_sim                    => g_sim, 
+    g_sim_level              => g_sim_level, 
+    g_nof_macs               => g_nof_macs, 
+    g_direction              => g_direction, 
+    g_use_mdio               => g_use_mdio, 
+    g_mdio_epcs_dis          => g_mdio_epcs_dis, 
+    g_tx_fifo_fill           => g_tx_fifo_fill, 
+    g_tx_fifo_size           => g_tx_fifo_size, 
+    g_rx_fifo_size           => g_rx_fifo_size, 
+    g_word_alignment_padding => g_word_alignment_padding 
+  )
+  PORT MAP (
+    -- Transceiver PLL reference clock
+    tr_ref_clk_644      => tr_ref_clk_644,
+    tr_ref_clk_312      => tr_ref_clk_312,  -- 312.5      MHz for 10GBASE-R
+    tr_ref_clk_156      => tr_ref_clk_156,  -- 156.25     MHz for 10GBASE-R or for XAUI
+    tr_ref_rst_156      => tr_ref_rst_156,  --                for 10GBASE-R or for XAUI
+
+    -- Calibration & reconfig clock
+    cal_rec_clk         => cal_rec_clk,   -- for XAUI;
+
+    -- MM interface
+    mm_rst              => mm_rst,
+    mm_clk              => mm_clk,
+
+    reg_mac_mosi        => reg_mac_mosi,
+    reg_mac_miso        => reg_mac_miso,
+
+    xaui_mosi           => xaui_mosi, 
+    xaui_miso           => xaui_miso,  
+
+    reg_eth10g_mosi     => reg_eth10g_mosi,
+    reg_eth10g_miso     => reg_eth10g_miso,
+
+    mdio_mosi_arr       => mdio_mosi_arr,  
+    mdio_miso_arr       => mdio_miso_arr, 
+
+    reg_10gbase_r_24_mosi => reg_10gbase_r_24_mosi,
+    reg_10gbase_r_24_miso => reg_10gbase_r_24_miso,            
+  
+    -- DP interface
+    dp_rst              => dp_rst,
+    dp_clk              => dp_clk,
+
+    src_out_arr         => tr_10GbE_src_out_arr,
+    src_in_arr          => tr_10GbE_src_in_arr,
+
+    snk_out_arr         => tr_10GbE_snk_out_arr,
+    snk_in_arr          => tr_10GbE_snk_in_arr,
+
+    -- Serial XAUI IO
+    xaui_tx_arr         => xaui_tx_arr, 
+    xaui_rx_arr         => xaui_rx_arr, 
+
+    -- Serial IO
+    serial_tx_arr       => serial_tx_arr,
+    serial_rx_arr       => serial_rx_arr,
+
+    -- MDIO interface
+    mdio_rst            => mdio_rst,          
+    mdio_mdc_arr        => mdio_mdc_arr,      
+    mdio_mdat_in_arr    => mdio_mdat_in_arr,  
+    mdio_mdat_oen_arr   => mdio_mdat_oen_arr 
+  );
+
+END str;
diff --git a/libraries/io/nw_10GbE/src/vhdl/nw_arp_request.vhd b/libraries/io/nw_10GbE/src/vhdl/nw_arp_request.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..0b1cf79bcdf78a9c2d1a00407bad000069b48014
--- /dev/null
+++ b/libraries/io/nw_10GbE/src/vhdl/nw_arp_request.vhd
@@ -0,0 +1,155 @@
+-------------------------------------------------------------------------------
+--
+-- 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: R. van der Walle
+-- Purpose: Generate ARP request packets at a predefined interval.
+-- Description:
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, dp_lib, technology_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 common_lib.common_network_total_header_pkg.ALL;
+USE common_lib.common_interface_layers_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+
+ENTITY nw_arp_request IS
+  GENERIC (
+    g_period_s  : NATURAL := 30
+  );
+  PORT (
+    dp_pps  : IN STD_LOGIC;
+    dp_clk  : IN STD_LOGIC;
+    dp_rst  : IN STD_LOGIC;
+    
+    src_in  : IN  t_dp_siso := c_dp_siso_rst;
+    src_out : OUT t_dp_sosi := c_dp_sosi_rst;
+
+    arp_sha : IN STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0);
+    arp_spa : IN STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0);
+    arp_tpa : IN STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0)
+
+  );
+END nw_arp_request;
+
+ARCHITECTURE rtl of nw_arp_request IS
+
+  CONSTANT c_data_w : NATURAL := c_xgmii_data_w;
+  CONSTANT c_nof_hdr_fields : NATURAL := 12;
+  CONSTANT c_hdr_field_sel  : STD_LOGIC_VECTOR(c_nof_hdr_fields-1 DOWNTO 0) := (OTHERS => '0');
+  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(c_network_eth_bc_mac) ), --broadcast address
+                                                                                  ( field_name_pad("eth_src_mac"       ), "RW", 48, field_default(0) ), --same as arp_sha
+                                                                                  ( field_name_pad("eth_type"          ), "RW", 16, field_default(x"0806") ), -- ARP type
+                                                                                  ( field_name_pad("arp_htype"         ), "RW", 16, field_default(1) ),       -- eth type
+                                                                                  ( field_name_pad("arp_ptype"         ), "RW", 16, field_default(x"0800") ), -- IP type
+                                                                                  ( field_name_pad("arp_hlen"          ), "RW",  8, field_default(6) ), -- Mac length is 6 bytes
+                                                                                  ( field_name_pad("arp_plen"          ), "RW",  8, field_default(4) ), -- IP length is 4 bytes
+                                                                                  ( field_name_pad("arp_operation"     ), "RW", 16, field_default(1) ), -- operation is request
+                                                                                  ( field_name_pad("arp_sha"           ), "RW", 48, field_default(0) ), --set later
+                                                                                  ( field_name_pad("arp_spa"           ), "RW", 32, field_default(0) ), --set later
+                                                                                  ( field_name_pad("arp_tha"           ), "RW", 48, field_default(0) ), --set to 0
+                                                                                  ( field_name_pad("arp_tpa"           ), "RW", 32, field_default(0) )); -- set later
+
+  CONSTANT c_dp_field_blk_snk_data_w : NATURAL := field_slv_len(c_hdr_field_arr);
+  CONSTANT c_dp_field_blk_src_data_w : NATURAL := c_data_w;
+
+  SIGNAL pps_cnt : NATURAL := 0;
+  SIGNAL trigger : BOOLEAN := FALSE;
+
+  SIGNAL dp_field_blk_snk_in      : t_dp_sosi := c_dp_sosi_rst;
+  SIGNAL nxt_dp_field_blk_snk_in  : t_dp_sosi := c_dp_sosi_rst;
+  SIGNAL dp_field_blk_snk_out     : t_dp_siso := c_dp_siso_rdy;
+
+BEGIN
+
+  p_field_wires : PROCESS (arp_sha, arp_spa, arp_tpa)
+  BEGIN
+    -- Set defaults
+    loop_field_wires: FOR i IN c_hdr_field_arr'RANGE LOOP
+      nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, i) DOWNTO field_lo(c_hdr_field_arr, i)) <= c_hdr_field_arr(i).default(c_hdr_field_arr(i).size-1 DOWNTO 0);
+    END LOOP;
+    -- Overwrite fields comming from inputs
+    nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, "eth_src_mac") DOWNTO field_lo(c_hdr_field_arr, "eth_src_mac")) <= arp_sha;
+    nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, "arp_sha")     DOWNTO field_lo(c_hdr_field_arr, "arp_sha")) <= arp_sha;
+    nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, "arp_spa")     DOWNTO field_lo(c_hdr_field_arr, "arp_spa")) <= arp_spa;
+    nxt_dp_field_blk_snk_in.data(field_hi(c_hdr_field_arr, "arp_tpa")     DOWNTO field_lo(c_hdr_field_arr, "arp_tpa")) <= arp_tpa;
+  END PROCESS;
+     
+  -- pps counter process setting sop, eop and valid
+  p_dp_pps : PROCESS (dp_clk, dp_rst)
+  BEGIN
+    IF dp_rst = '1' THEN
+      trigger <= FALSE;
+      pps_cnt <= 0;
+      dp_field_blk_snk_in <= c_dp_sosi_rst;
+    ELSIF RISING_EDGE(dp_clk) THEN
+
+      dp_field_blk_snk_in <= nxt_dp_field_blk_snk_in;
+      IF trigger AND dp_field_blk_snk_out.ready = '1' AND dp_field_blk_snk_out.xon = '1' THEN
+        trigger <= FALSE;
+        dp_field_blk_snk_in.sop   <= '1';
+        dp_field_blk_snk_in.eop   <= '1';
+        dp_field_blk_snk_in.valid <= '1';
+      END IF;
+
+      IF dp_pps = '1' THEN
+        IF pps_cnt < g_period_s-1 THEN
+          pps_cnt <= pps_cnt + 1;
+        ELSE
+          pps_cnt <= 0;
+          trigger <= TRUE;
+        END IF;
+      END IF;
+
+    END IF;
+  END PROCESS;
+
+  -- dp_field_blk to convert the ARP packet SLV to multi-cycle
+  u_dp_field_blk : ENTITY dp_lib.dp_field_blk
+  GENERIC MAP (
+    g_field_arr      => c_hdr_field_arr,
+    g_field_sel      => c_hdr_field_sel,
+    g_snk_data_w     => c_dp_field_blk_snk_data_w,
+    g_src_data_w     => c_dp_field_blk_src_data_w,
+    g_in_symbol_w    => c_byte_w,
+    g_out_symbol_w   => c_byte_w
+  )
+  PORT MAP (
+    dp_clk       => dp_clk,
+    dp_rst       => dp_rst,
+
+    mm_clk       => '0',
+    mm_rst       => '0',
+
+    snk_in       => dp_field_blk_snk_in,
+    snk_out      => dp_field_blk_snk_out,
+
+    src_out      => src_out,
+    src_in       => src_in
+
+  );
+
+
+END rtl;
diff --git a/libraries/io/nw_10GbE/src/vhdl/nw_ping_response.vhd b/libraries/io/nw_10GbE/src/vhdl/nw_ping_response.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9ecaa256899c7fbafa32bf0ad8754e4b09ea9bb4
--- /dev/null
+++ b/libraries/io/nw_10GbE/src/vhdl/nw_ping_response.vhd
@@ -0,0 +1,240 @@
+-------------------------------------------------------------------------------
+--
+-- 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: R. van der Walle
+-- Purpose: generate PING response packet if a PING request is received. 
+-- Description: A response header is derived from the incoming request header.
+-- . The payload of the response is created by pipelining the request packet.
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, dp_lib, technology_lib, tech_mac_10g_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 common_lib.common_network_total_header_pkg.ALL;
+USE common_lib.common_interface_layers_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+USE tech_mac_10g_lib.tech_mac_10g_component_pkg.ALL;
+
+ENTITY nw_ping_response IS
+  GENERIC (
+    g_technology : NATURAL := c_tech_select_default
+  );
+  PORT (
+    clk     : IN STD_LOGIC;
+    rst     : IN STD_LOGIC;
+
+    snk_in  : IN  t_dp_sosi := c_dp_sosi_rst;
+
+    src_in  : IN  t_dp_siso := c_dp_siso_rdy;
+    src_out : OUT t_dp_sosi := c_dp_sosi_rst;
+
+    eth_src_mac : IN STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0)
+  );
+END nw_ping_response;
+
+ARCHITECTURE rtl of nw_ping_response IS
+  CONSTANT c_data_w          : NATURAL := c_xgmii_data_w;
+  CONSTANT c_dp_fifo_empty_w : NATURAL := c_tech_mac_10g_empty_w;
+  CONSTANT c_dp_fifo_size    : NATURAL := 16;
+
+  CONSTANT c_cin_w : NATURAL := 4;
+  CONSTANT c_pipeline : NATURAL := c_network_total_header_64b_nof_words + 5; -- Header length and 5 more pipeline cycles to allow for the other states
+
+  TYPE t_state IS (s_idle, s_capture, s_check, s_sum, s_output, s_wait);
+  
+  TYPE t_reg IS RECORD
+    state         : t_state;
+    word_cnt      : NATURAL RANGE 0 TO c_network_total_header_64b_nof_words;
+    hdr_words_arr : t_network_total_header_64b_arr;
+    hdr_fields    : t_network_total_header;
+    hdr_response  : t_network_total_header_64b_arr;
+    ip_checksum   : STD_LOGIC_VECTOR(c_halfword_w -1 DOWNTO 0);
+    icmp_checksum : STD_LOGIC_VECTOR(c_halfword_w -1 DOWNTO 0);
+    ip_sum        : UNSIGNED(c_halfword_w + c_cin_w -1 DOWNTO 0);
+    src_out       : t_dp_sosi;
+  END RECORD;
+
+  SIGNAL r, rin : t_reg;
+
+  CONSTANT c_r_rst : t_reg := ( state => s_idle, 
+                                word_cnt => 0,
+                                hdr_words_arr => (OTHERS=>(OTHERS=>'0')),
+                                hdr_fields => c_network_total_header_ones,
+                                hdr_response =>  (OTHERS=>(OTHERS=>'0')),
+                                ip_checksum => (OTHERS => '0'),
+                                icmp_checksum => (OTHERS => '0'),
+                                ip_sum => (OTHERS => '0'),
+                                src_out => c_dp_sosi_rst );
+
+  SIGNAL dp_pipeline_src_out : t_dp_sosi;
+  SIGNAL dp_fifo_sc_src_out : t_dp_sosi;
+  SIGNAL dp_fifo_sc_rd_emp : STD_LOGIC;
+
+BEGIN
+
+-- Combinational Process
+  p_comb : PROCESS(r, rst, snk_in, dp_pipeline_src_out, dp_fifo_sc_rd_emp)
+    VARIABLE v : t_reg;
+  BEGIN
+    v := r;
+   
+    CASE r.state IS
+
+      WHEN s_idle => -- Wait for valid SOP
+        IF snk_in.sop = '1' AND snk_in.valid = '1' THEN
+          v.state := s_capture;
+          v.hdr_words_arr(r.word_cnt) := snk_in.data(c_data_w-1 DOWNTO 0);
+          v.word_cnt := r.word_cnt + 1;
+        END IF;
+
+      WHEN s_capture => -- Capture header
+        IF snk_in.valid = '1' AND r.word_cnt < c_network_total_header_64b_nof_words THEN
+          v.word_cnt := r.word_cnt + 1;
+          v.hdr_words_arr(r.word_cnt) := snk_in.data(c_data_w-1 DOWNTO 0);
+        ELSIF snk_in.eop = '1' AND snk_in.valid = '1' THEN
+          v := c_r_rst; 
+        ELSIF r.word_cnt >= c_network_total_header_64b_nof_words THEN
+          v.word_cnt := 0;
+          v.state := s_check;
+          v.hdr_fields.eth  := func_network_total_header_no_align_extract_eth(  r.hdr_words_arr);
+          v.hdr_fields.ip   := func_network_total_header_no_align_extract_ip(   r.hdr_words_arr);
+          v.hdr_fields.icmp := func_network_total_header_no_align_extract_icmp( r.hdr_words_arr);
+        END IF;
+
+      WHEN s_check => -- Check if packet is ICMP echo request, create response header if it is the case.
+        IF TO_UINT(r.hdr_fields.eth.eth_type)=c_network_eth_type_ip AND 
+           TO_UINT(r.hdr_fields.ip.protocol)=c_network_ip_protocol_icmp AND
+           TO_UINT(r.hdr_fields.icmp.msg_type)=c_network_icmp_msg_type_request THEN
+          v.hdr_response := func_network_total_header_no_align_response_icmp(r.hdr_words_arr, eth_src_mac);
+          v.state := s_sum;
+        ELSE
+          v := c_r_rst;
+        END IF;
+
+      WHEN s_sum => -- Sum halfwords of headers for checksum
+        v.state := s_output;
+        v.ip_sum := r.ip_sum 
+                  + UNSIGNED(r.hdr_response(1)(c_halfword_w-1 DOWNTO 0))                   -- ip_version, ip_header_length, ip_services
+                  + UNSIGNED(r.hdr_response(2)(c_halfword_w*4 -1 DOWNTO c_halfword_w *3))  -- ip_total_length
+		              + UNSIGNED(r.hdr_response(2)(c_halfword_w*3 -1 DOWNTO c_halfword_w *2))  -- ip_identification
+		              + UNSIGNED(r.hdr_response(2)(c_halfword_w*2 -1 DOWNTO c_halfword_w))     -- ip_flags, ip_fragment_offset
+ 		              + UNSIGNED(r.hdr_response(2)(c_halfword_w   -1 DOWNTO 0))                -- ip_time_to_live, ip_protocol
+                  + UNSIGNED(r.hdr_response(3)(c_halfword_w*3 -1 DOWNTO c_halfword_w *2))  -- ip_src_addr(1/2)
+		              + UNSIGNED(r.hdr_response(3)(c_halfword_w*2 -1 DOWNTO c_halfword_w))     -- ip_src_addr(2/2)
+		              + UNSIGNED(r.hdr_response(3)(c_halfword_w   -1 DOWNTO 0))                -- ip_dst_addr(1/2)
+                  + UNSIGNED(r.hdr_response(4)(c_halfword_w*4 -1 DOWNTO c_halfword_w *3)); -- ip_dst_addr(2/2)
+
+
+      WHEN s_output => -- Send out ICMP response
+        v.src_out := dp_pipeline_src_out;
+        IF dp_pipeline_src_out.valid = '1' THEN
+          CASE r.word_cnt IS
+            WHEN 0 =>
+              -- Also perform final checksum calculation
+              IF dp_pipeline_src_out.sop = '1' THEN -- Wait for SOP
+                v.src_out.data(c_data_w-1 DOWNTO 0) := r.hdr_response(r.word_cnt);
+                v.ip_checksum := NOT(STD_LOGIC_VECTOR(r.ip_sum(c_halfword_w-1 DOWNTO 0)+r.ip_sum(r.ip_sum'HIGH DOWNTO c_halfword_w))); -- checksum = inverted (sum + carry) 
+                v.icmp_checksum := TO_UVEC((2048 + TO_UINT(r.hdr_fields.icmp.checksum)), c_halfword_w); -- checksum = original checksum + 0x0800 (incremental update)
+                v.word_cnt := r.word_cnt+1;
+              ELSE
+                v.src_out := c_dp_sosi_rst;
+              END IF;
+            WHEN 1 TO 2 =>
+              v.src_out.data(c_data_w-1 DOWNTO 0) := r.hdr_response(r.word_cnt);
+              v.word_cnt := r.word_cnt+1;
+            WHEN 3 =>
+              v.src_out.data(c_data_w-1 DOWNTO 0) := r.hdr_response(r.word_cnt);
+              v.src_out.data(c_halfword_w*4 -1 DOWNTO c_halfword_w *3) := r.ip_checksum;
+              v.word_cnt := r.word_cnt+1;
+            WHEN 4 =>
+              v.src_out.data(c_data_w-1 DOWNTO 0) := r.hdr_response(r.word_cnt);
+              v.src_out.data(c_halfword_w*2 -1 DOWNTO c_halfword_w) := r.icmp_checksum;
+              v.word_cnt := r.word_cnt+1;
+            WHEN OTHERS => 
+              IF dp_pipeline_src_out.eop = '1' THEN
+                v.state := s_wait;
+              END IF;
+          END CASE;
+        END IF;
+
+      WHEN s_wait =>
+            v.src_out := c_dp_sosi_rst;
+        IF dp_fifo_sc_rd_emp = '1' THEN -- Wait until ping response has left the fifo
+          v := c_r_rst;
+        END IF;
+         
+    END CASE;
+
+    IF rst = '1' THEN
+      v := c_r_rst;
+    END IF;
+
+    rin <= v;
+  END PROCESS;
+
+  -- Sequential process
+  p_regs : PROCESS(clk)
+  BEGIN
+    IF RISING_EDGE(clk) THEN
+      r <= rin;
+    END IF;
+  END PROCESS;
+
+  -- Pipeline packet payload
+  u_dp_pipeline : ENTITY dp_lib.dp_pipeline
+  GENERIC MAP (
+    g_pipeline => c_pipeline
+  )
+  PORT MAP (
+    clk => clk,
+    rst => rst,
+    snk_in => snk_in,
+    src_out => dp_pipeline_src_out
+  );
+
+  -- Store response packet until ready
+  u_dp_fifo_sc : ENTITY dp_lib.dp_fifo_sc
+  GENERIC MAP (
+    g_technology  => g_technology,
+    g_data_w      => c_data_w,
+    g_empty_w     => c_dp_fifo_empty_w,
+    g_use_empty   => TRUE,
+    g_fifo_size   => c_dp_fifo_size
+  )
+  PORT MAP (
+    rst      => rst,
+    clk      => clk,
+ 
+    rd_emp   => dp_fifo_sc_rd_emp,
+ 
+    snk_out  => OPEN,
+    snk_in   => r.src_out,
+  
+    src_in   => src_in, 
+    src_out  => dp_fifo_sc_src_out
+  );   
+  src_out <= dp_fifo_sc_src_out;
+
+END rtl;
diff --git a/libraries/io/nw_10GbE/tb/vhdl/tb_nw_10GbE.vhd b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_10GbE.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..cdfbd201328f82057cbace3528bb93958cdad93c
--- /dev/null
+++ b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_10GbE.vhd
@@ -0,0 +1,411 @@
+-------------------------------------------------------------------------------
+--
+-- 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: R. van der Walle
+-- Purpose: Testbench for tb_nw_10GbE.
+-- Description:
+--   The tb is self checking based on:
+--   . proc_tech_mac_10g_rx_packet() for expected header and data type
+--   . tx_pkt_cnt=rx_pkt_cnt > 0 must be true at the tb_end.
+--
+--   The tb finishes using severity failure because the simulation can not
+--   finish by stopping the clocks and applying the resets due to that the IP
+--   keeps on toggling internally.
+-- Usage:
+--   > as 10
+--   > run -all
+--
+-- Remarks:
+-- . c_tx_rx_loopback:
+--   The tb uses a single DUT and c_tx_rx_loopback to model the link.
+--   The g_direction = "TX_RX" is verified properly by c_tx_rx_loopback =
+--   TRUE. Internally "RX_ONLY" is equivalent to "TX_RX" so there
+--   c_tx_rx_loopback = TRUE is also suitable. For TX_ONLY the MAC Tx is
+--   internally loopbacked to the MAC Rx, so there the external loopback is
+--   not used and set to c_tx_rx_loopback = FALSE.
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, technology_lib, tech_pll_lib, tech_mac_10g_lib, 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.common_interface_layers_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
+USE common_lib.common_network_total_header_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+USE tech_mac_10g_lib.tech_mac_10g_component_pkg.ALL;
+USE tech_mac_10g_lib.tb_tech_mac_10g_pkg.ALL;
+USE tech_pll_lib.tech_pll_component_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+
+ENTITY tb_nw_10GbE IS
+  -- Test bench control parameters
+  GENERIC (
+    g_technology              : NATURAL := c_tech_select_default;
+    g_tb_end                  : BOOLEAN := TRUE;   -- when TRUE then tb_end ends this simulation, else a higher multi-testbench will end the simulation
+    g_no_dut                  : BOOLEAN := FALSE;  -- default FALSE to verify the DUT, else use TRUE to verify the tb itself without the DUT
+    g_dp_clk_period           : TIME := 5 ns;      -- must be ~< 9000/(9000-c_tx_fifo_fill) * g_ref_clk_156_period
+    g_sim_level               : NATURAL := 0;      -- 0 = use IP; 1 = use fast serdes model
+    g_nof_channels            : NATURAL := 1;
+    g_direction               : STRING := "TX_RX";  -- "TX_RX", "TX_ONLY", "RX_ONLY"
+    g_ref_clk_644_period      : TIME := tech_pll_clk_644_period;  -- for 10GBASE-R
+    g_ref_clk_156_period      : TIME := 6.4 ns;                   -- for XAUI
+    g_data_type               : NATURAL := c_tb_tech_mac_10g_data_type_symbols;
+    g_verify_link_recovery    : BOOLEAN := TRUE
+  );
+  PORT (
+    tb_end : OUT STD_LOGIC
+  );
+END tb_nw_10GbE;
+
+ARCHITECTURE tb OF tb_nw_10GbE IS
+
+  CONSTANT c_sim                : BOOLEAN := TRUE;  -- tr_xaui_align_dly has time delay ~ 1 sec, so not suitable for simulation
+  
+  CONSTANT cal_clk_period       : TIME := 25 ns;    --  40 MHz
+  
+  CONSTANT phy_delay            : TIME := sel_a_b(g_sim_level=0, 0 ns, 0 ns);
+  CONSTANT c_tx_rx_loopback     : BOOLEAN := g_direction/="TX_ONLY";
+  
+  CONSTANT c_tx_fifo_fill       : NATURAL := 100;
+   
+  CONSTANT c_pkt_length_arr1    : t_nat_natural_arr := array_init(0, 50, 1) & (1472, 1473) & 9000;  -- frame longer than 1518-46 = 1472 is received with rx_sosi.err = 8
+                                                                                                    -- jumbo frame is 9018-46 = 8972
+  CONSTANT c_pkt_length_arr2    : t_nat_natural_arr := array_init(46, 10, 139) & 1472;
+  CONSTANT c_pkt_length_arr     : t_nat_natural_arr := c_pkt_length_arr1 & c_pkt_length_arr2;
+  CONSTANT c_nof_pkt1           : NATURAL := c_pkt_length_arr1'LENGTH;
+  CONSTANT c_nof_pkt2           : NATURAL := c_pkt_length_arr2'LENGTH;
+  CONSTANT c_nof_pkt            : NATURAL := sel_a_b(g_verify_link_recovery, c_nof_pkt1 + c_nof_pkt2, c_nof_pkt1);
+
+  CONSTANT c_dst_mac            : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"10FA01020300";
+  CONSTANT c_src_mac            : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"123456789ABC";  -- = 12-34-56-78-9A-BC
+  CONSTANT c_src_mac_tx         : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := c_src_mac;
+  --CONSTANT c_src_mac_tx         : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"100056789ABC";  -- = 10-00-56-78-9A-BC
+  CONSTANT c_ethertype          : STD_LOGIC_VECTOR(c_network_eth_type_slv'RANGE) := X"10FA";
+  CONSTANT c_etherlen           : STD_LOGIC_VECTOR(c_network_eth_type_slv'RANGE) := "0000000000010000";
+
+  -- Packet headers
+  CONSTANT c_eth_header_ethertype : t_network_eth_header := (c_dst_mac, c_src_mac_tx, c_ethertype);
+  CONSTANT c_eth_header_etherlen  : t_network_eth_header := (c_dst_mac, c_src_mac_tx, c_etherlen);
+  
+  SIGNAL total_header      : t_network_total_header := c_network_total_header_ones;  -- default fill all fields with value 1
+  
+  CONSTANT c_ip_hdr_field_arr : t_common_field_arr(3+12-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac"       ), "RW", 48, field_default(x"ffffffffffff") ),
+                                                                         ( field_name_pad("eth_src_mac"       ), "RW", 48, field_default(x"e840f2acff78") ),
+                                                                         ( field_name_pad("eth_type"          ), "RW", 16, field_default(x"0800") ),
+                                                                         ( 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(x"54") ), 
+                                                                         ( field_name_pad("ip_identification" ), "RW", 16, field_default(x"3daf") ),
+                                                                         ( 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(x"40") ),
+                                                                         ( field_name_pad("ip_protocol"       ), "RW",  8, field_default(1) ),
+                                                                         ( field_name_pad("ip_header_checksum"), "RW", 16, field_default(x"e580") ),
+                                                                         ( field_name_pad("ip_src_addr"       ), "RW", 32, field_default(x"0a570224") ),
+                                                                         ( field_name_pad("ip_dst_addr"       ), "RW", 32, field_default(x"0a5700a8") ) );
+  -- Clocks and reset
+  SIGNAL tx_end_arr        : STD_LOGIC_VECTOR(g_nof_channels-1 DOWNTO 0);
+  SIGNAL tx_end            : STD_LOGIC;
+  SIGNAL rx_end            : STD_LOGIC;
+  SIGNAL cal_clk           : STD_LOGIC := '1';  -- calibration clock
+  SIGNAL mm_clk            : STD_LOGIC;         -- memory-mapped bus clock
+  SIGNAL mm_rst            : STD_LOGIC;         -- reset synchronous with mm_clk
+  SIGNAL dp_clk            : STD_LOGIC := '1';  -- data path clock
+  SIGNAL dp_pps            : STD_LOGIC := '0';  -- data path clock
+  SIGNAL dp_rst            : STD_LOGIC;         -- reset synchronous with dp_clk
+  
+  -- External reference clocks
+  SIGNAL tr_ref_clk_644    : STD_LOGIC := '1';  -- 10GBASE-R
+  SIGNAL tr_ref_clk_312    : STD_LOGIC;         -- 10GBASE-R
+  SIGNAL tr_ref_clk_156    : STD_LOGIC := '1';  -- 10GBASE-R or XAUI
+  SIGNAL tr_ref_rst_156    : STD_LOGIC;         -- 10GBASE-R or XAUI
+    
+  -- MAC 10G control interface
+  SIGNAL mm_init           : STD_LOGIC;
+  SIGNAL mac_mosi_wrdata   : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- for channel 0, 32 bit
+  SIGNAL mac_mosi          : t_mem_mosi;
+  SIGNAL mac_miso          : t_mem_miso;
+  SIGNAL mac_miso_rdval    : STD_LOGIC;                              -- for channel 0
+  SIGNAL mac_miso_rddata   : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- for channel 0, 32 bit
+  
+  -- MAC 10G transmit interface
+  SIGNAL tx_en             : STD_LOGIC := '1';
+  SIGNAL tx_siso_arr       : t_dp_siso_arr(g_nof_channels-1 DOWNTO 0);
+  SIGNAL tx_sosi_arr       : t_dp_sosi_arr(g_nof_channels-1 DOWNTO 0);
+  SIGNAL tx_sosi_data      : STD_LOGIC_VECTOR(c_tech_mac_10g_data_w-1 DOWNTO 0);  -- for channel 0, 64 bit
+  
+  -- MAC 10G receive interface
+  SIGNAL rx_siso_arr       : t_dp_siso_arr(g_nof_channels-1 DOWNTO 0);
+  SIGNAL rx_sosi_arr       : t_dp_sosi_arr(g_nof_channels-1 DOWNTO 0);
+  SIGNAL rx_sosi_data      : STD_LOGIC_VECTOR(c_tech_mac_10g_data_w-1 DOWNTO 0);  -- for channel 0, 64 bit
+
+  -- PHY XAUI serial I/O
+  SIGNAL xaui_tx_arr       : t_xaui_arr(g_nof_channels-1 DOWNTO 0);
+  SIGNAL xaui_rx_arr       : t_xaui_arr(g_nof_channels-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
+
+  -- PHY 10GBASE-R serial IO
+  SIGNAL serial_tx_arr     : STD_LOGIC_VECTOR(g_nof_channels-1 downto 0);
+  SIGNAL serial_rx_arr     : STD_LOGIC_VECTOR(g_nof_channels-1 downto 0) := (OTHERS=>'0');
+
+  -- Model a serial link fault
+  SIGNAL link_fault_arr    : STD_LOGIC_VECTOR(g_nof_channels-1 downto 0);
+  
+  -- Verification
+  SIGNAL tx_pkt_cnt_arr    : t_natural_arr(g_nof_channels-1 downto 0) := (OTHERS=>0);
+  SIGNAL rx_pkt_cnt_arr    : t_natural_arr(g_nof_channels-1 downto 0) := (OTHERS=>0);
+  SIGNAL rx_toggle_arr     : STD_LOGIC_VECTOR(g_nof_channels-1 downto 0) := (OTHERS=>'0');  -- toggle after every received packet
+  
+BEGIN
+
+  cal_clk <= NOT cal_clk AFTER cal_clk_period/2;  -- Calibration clock
+  
+  dp_clk  <= NOT dp_clk  AFTER g_dp_clk_period/2;   -- DP clock
+  dp_rst  <= '1', '0' AFTER g_dp_clk_period*10;
+
+  -- debug signals to ease monitoring in wave window
+  mac_mosi_wrdata <= mac_mosi.wrdata(c_word_w-1 DOWNTO 0);
+  mac_miso_rddata <= mac_miso.rddata(c_word_w-1 DOWNTO 0);
+  mac_miso_rdval <= '1' WHEN mac_mosi.rd='1' AND mac_miso.waitrequest='0' ELSE '0';  -- c_rd_latency = 1
+  
+  tx_sosi_data <= tx_sosi_arr(0).data(c_tech_mac_10g_data_w-1 DOWNTO 0);
+  rx_sosi_data <= rx_sosi_arr(0).data(c_tech_mac_10g_data_w-1 DOWNTO 0);
+  
+  -- Use signal to leave unused fields 'X'
+  total_header.eth <= c_eth_header_ethertype;
+
+  -- Generate reference clocks
+  gen_ref_clocks_xaui : IF g_technology=c_tech_stratixiv GENERATE
+    tr_ref_clk_644 <= 'X';
+    tr_ref_clk_312 <= 'X';
+    tr_ref_clk_156 <= NOT tr_ref_clk_156 AFTER g_ref_clk_156_period/2;
+    tr_ref_rst_156 <= '1', '0' AFTER g_ref_clk_156_period*5;
+  END GENERATE;
+    
+  gen_ref_clocks_10gbase_r : IF g_technology/=c_tech_stratixiv GENERATE
+    tr_ref_clk_644 <= NOT tr_ref_clk_644 AFTER g_ref_clk_644_period/2;
+  
+    pll : ENTITY tech_pll_lib.tech_pll_xgmii_mac_clocks
+    GENERIC MAP (
+      g_technology => g_technology
+    )
+    PORT MAP (
+      refclk_644 => tr_ref_clk_644,
+      rst_in     => mm_rst,
+      clk_156    => tr_ref_clk_156,
+      clk_312    => tr_ref_clk_312,
+      rst_156    => tr_ref_rst_156,
+      rst_312    => OPEN
+    );
+  END GENERATE;
+  
+  -- Setup all MACs in series
+  u_mm_setup : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_setup
+  GENERIC MAP (
+    g_technology    => g_technology,
+    g_nof_macs      => g_nof_channels,
+    g_src_mac       => c_src_mac
+  )
+  PORT MAP (
+    tb_end    => rx_end,
+    mm_clk    => mm_clk,
+    mm_rst    => mm_rst,
+    mm_init   => mm_init,
+    mac_mosi  => mac_mosi,
+    mac_miso  => mac_miso
+  );  
+  
+  gen_transmitter : FOR I IN 0 TO g_nof_channels-1 GENERATE
+    -- Packet transmitter
+    u_transmitter : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_transmitter
+    GENERIC MAP (
+      g_data_type            => g_data_type,
+      g_pkt_length_arr1      => c_pkt_length_arr1,
+      g_pkt_length_arr2      => c_pkt_length_arr2,
+      g_verify_link_recovery => g_verify_link_recovery
+    )
+    PORT MAP (
+      mm_init        => mm_init,
+      total_header   => total_header,
+      tx_clk         => dp_clk,
+      tx_siso        => tx_siso_arr(I),
+      tx_sosi        => tx_sosi_arr(I),
+      link_fault     => link_fault_arr(I),
+      tx_end         => tx_end_arr(I)
+    );
+  END GENERATE;
+
+  no_dut : IF g_no_dut=TRUE GENERATE
+    rx_sosi_arr <= tx_sosi_arr;
+    tx_siso_arr <= rx_siso_arr;
+  END GENERATE;
+
+  gen_dut : IF g_no_dut=FALSE GENERATE
+    u_nw_10GbE : ENTITY work.nw_10GbE
+    GENERIC MAP (
+      g_technology             => g_technology,
+      g_sim                    => c_sim,
+      g_sim_level              => g_sim_level, -- 0 = use IP; 1 = use fast serdes model
+      g_nof_macs               => g_nof_channels,
+      g_direction              => g_direction,
+      g_use_mdio               => TRUE,
+      g_mdio_epcs_dis          => TRUE,  -- TRUE disables Enhanced PCS on init; e.g. to target a 10GbE card in PC that does not support it 
+      g_tx_fifo_fill           => c_tx_fifo_fill,
+      g_tx_fifo_size           => 256,
+      g_word_alignment_padding => TRUE,
+      g_ip_hdr_field_arr       => c_ip_hdr_field_arr 
+    )
+    PORT MAP (
+      -- Transceiver PLL reference clock
+      tr_ref_clk_644      => tr_ref_clk_644,   -- 644.531250 MHz for 10GBASE-R
+      tr_ref_clk_312      => tr_ref_clk_312,   -- 312.5      MHz for 10GBASE-R
+      tr_ref_clk_156      => tr_ref_clk_156,   -- 156.25     MHz for 10GBASE-R or for XAUI
+      tr_ref_rst_156      => tr_ref_rst_156,   --                for 10GBASE-R or for XAUI
+
+      -- Calibration & reconfig clock
+      cal_rec_clk         => cal_clk,
+      
+      -- MM interface
+      mm_rst              => mm_rst,
+      mm_clk              => mm_clk,
+      
+      reg_mac_mosi        => mac_mosi,
+      reg_mac_miso        => mac_miso,
+  
+      xaui_mosi           => c_mem_mosi_rst,
+      xaui_miso           => OPEN,
+      
+      mdio_mosi_arr       => (OTHERS=>c_mem_mosi_rst),
+      mdio_miso_arr       => OPEN,
+  
+      -- DP interface
+      dp_rst              => dp_rst,
+      dp_clk              => dp_clk,
+      dp_pps              => dp_pps,
+  
+      snk_out_arr         => tx_siso_arr,
+      snk_in_arr          => tx_sosi_arr,
+  
+      src_in_arr          => rx_siso_arr,
+      src_out_arr         => rx_sosi_arr,
+  
+      -- Serial XAUI interface
+      xaui_tx_arr         => xaui_tx_arr,
+      xaui_rx_arr         => xaui_rx_arr,
+  
+      -- Serial IO
+      serial_tx_arr       => serial_tx_arr,
+      serial_rx_arr       => serial_rx_arr,
+    
+      -- MDIO interface
+      mdio_rst            => OPEN,
+      mdio_mdc_arr        => OPEN,
+      mdio_mdat_in_arr    => (OTHERS=>'0'),
+      mdio_mdat_oen_arr   => OPEN,
+
+      hdr_fields_in_arr   => (OTHERS => (OTHERS => '0')) 
+    );
+  END GENERATE;
+  
+  gen_link_connect : FOR I IN 0 TO g_nof_channels-1 GENERATE
+    u_link_connect : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_link_connect
+    GENERIC MAP (
+      g_loopback    => c_tx_rx_loopback,
+      g_link_delay  => phy_delay
+    )
+    PORT MAP (
+      link_fault   => link_fault_arr(I), -- when '1' then forces rx_serial_arr(0)='0'
+      
+      -- 10GBASE-R serial layer connect
+      serial_tx    => serial_tx_arr(I),
+      serial_rx    => serial_rx_arr(I),  -- connects to delayed tx_serial when g_loopback=TRUE
+      
+      -- XAUI serial layer connect
+      xaui_tx      => xaui_tx_arr(I),
+      xaui_rx      => xaui_rx_arr(I)     -- connects to delayed xaui_tx when g_loopback=TRUE
+    );
+  END GENERATE;
+  
+  gen_receiver : FOR I IN 0 TO g_nof_channels-1 GENERATE
+    u_receiver : ENTITY tech_mac_10g_lib.tb_tech_mac_10_receiver
+    GENERIC MAP (
+      g_data_type  => g_data_type
+    )
+    PORT MAP (
+      mm_init        => mm_init,
+      total_header   => total_header,
+      rx_clk         => dp_clk,
+      rx_sosi        => rx_sosi_arr(I),
+      rx_siso        => rx_siso_arr(I),
+      rx_toggle      => rx_toggle_arr(I)
+    );
+  END GENERATE;
+  
+  gen_verify_rx_at_eop : FOR I IN 0 TO g_nof_channels-1 GENERATE
+    u_verify_rx_at_eop : ENTITY tech_mac_10g_lib.tb_tech_mac_10_verify_rx_at_eop
+    GENERIC MAP (
+      g_no_padding     => g_no_dut,
+      g_pkt_length_arr => c_pkt_length_arr
+    )
+    PORT MAP (
+      tx_clk      => dp_clk,
+      tx_sosi     => tx_sosi_arr(I),
+      rx_clk      => dp_clk,
+      rx_sosi     => rx_sosi_arr(I)
+    );  
+  END GENERATE;
+  
+  gen_verify_rx_pkt_cnt : FOR I IN 0 TO g_nof_channels-1 GENERATE
+    u_verify_rx_pkt_cnt : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_verify_rx_pkt_cnt
+    GENERIC MAP (
+      g_nof_pkt   => c_nof_pkt
+    )
+    PORT MAP (
+      tx_clk      => dp_clk,
+      tx_sosi     => tx_sosi_arr(I),
+      rx_clk      => dp_clk,
+      rx_sosi     => rx_sosi_arr(I),
+      tx_pkt_cnt  => tx_pkt_cnt_arr(I),
+      rx_pkt_cnt  => rx_pkt_cnt_arr(I),
+      rx_end      => rx_end
+    );
+  END GENERATE;
+
+  -- Stop the simulation
+  tx_end <= andv(tx_end_arr);
+  
+  u_simulation_end : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_simulation_end
+  GENERIC MAP (
+    g_tb_end            => g_tb_end,
+    g_nof_clk_to_rx_end => 1000
+  )
+  PORT MAP (
+    clk       => dp_clk,
+    tx_end    => tx_end,
+    rx_end    => rx_end,
+    tb_end    => tb_end
+  );
+  
+END tb;
diff --git a/libraries/io/nw_10GbE/tb/vhdl/tb_nw_arp_request.vhd b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_arp_request.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..950aedd237ca96781c34831b29d3124098ea8cb4
--- /dev/null
+++ b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_arp_request.vhd
@@ -0,0 +1,101 @@
+-------------------------------------------------------------------------------
+--
+-- 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: R. van der Walle
+-- Purpose: Verify nw_arp_request.vhd 
+-- Description:
+-- Usage:
+-- > as 10
+-- > run -all  -- signal tb_end will stop the simulation by stopping the clk
+-------------------------------------------------------------------------------
+  
+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.tb_common_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 dp_lib.tb_dp_pkg.ALL;
+
+ENTITY tb_nw_arp_request IS
+GENERIC (
+  g_test_backpressure : BOOLEAN := TRUE
+        );
+END tb_nw_arp_request;
+
+ARCHITECTURE tb OF tb_nw_arp_request IS
+
+  SIGNAL tb_end             : STD_LOGIC := '0';
+  SIGNAL clk                : STD_LOGIC := '1';
+  SIGNAL dp_pps             : STD_LOGIC := '1';
+  SIGNAL rst                : STD_LOGIC := '1';
+
+  SIGNAL src_in  : t_dp_siso := c_dp_siso_rst;
+  SIGNAL src_out : t_dp_sosi := c_dp_sosi_rst;
+
+  SIGNAL arp_sha : STD_LOGIC_VECTOR(c_network_eth_mac_addr_w-1 DOWNTO 0) := x"AABBCCDDEEFF";
+  SIGNAL arp_spa : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0) := x"A1A2A3A4";
+  SIGNAL arp_tpa : STD_LOGIC_VECTOR(c_network_ip_addr_w-1 DOWNTO 0) := x"B1B2B3B4";
+
+BEGIN
+
+  clk <= (NOT clk) OR tb_end AFTER clk_period/2;
+  rst <= '1', '0' AFTER clk_period*7;
+  src_in.xon <= '1';
+
+  p_stimuli : PROCESS
+  BEGIN
+    IF g_test_backpressure THEN 
+      src_in.ready <= '0';
+    ELSE
+      src_in.ready <= '1';
+    END IF;
+    dp_pps <= '0';
+    proc_common_wait_some_cycles(clk, 10);
+    dp_pps <= '1';
+    proc_common_wait_some_cycles(clk, 1);
+    dp_pps <= '0';
+    proc_common_wait_some_cycles(clk, 10);
+    src_in.ready <= '1';
+    proc_common_wait_until_evt(clk, src_out.eop);
+    tb_end <= '1';
+  END PROCESS;
+
+  dut: ENTITY work.nw_arp_request
+  GENERIC MAP(
+    g_period_s  =>  1
+  )
+  PORT MAP(
+    dp_pps  => dp_pps, 
+    dp_clk  => clk, 
+    dp_rst  => rst, 
+               
+    src_in  => src_in, 
+    src_out => src_out, 
+                      
+    arp_sha => arp_sha, 
+    arp_spa => arp_spa, 
+    arp_tpa => arp_tpa 
+  );
+
+END tb;
diff --git a/libraries/io/nw_10GbE/tb/vhdl/tb_nw_ping_response.vhd b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_ping_response.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..0f38f4ae42540a7d0a57eb17e156bf3d5bbe9795
--- /dev/null
+++ b/libraries/io/nw_10GbE/tb/vhdl/tb_nw_ping_response.vhd
@@ -0,0 +1,257 @@
+-------------------------------------------------------------------------------
+--
+-- 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: R. van der Walle
+-- Purpose: Verify nw_ping_response.vhd 
+-- Description:
+-- Usage:
+-- > as 10
+-- > run -all  -- signal tb_end will stop the simulation by stopping the clk
+-------------------------------------------------------------------------------
+  
+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_lfsr_sequences_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE dp_lib.tb_dp_pkg.ALL;
+
+ENTITY tb_nw_ping_response IS
+END tb_nw_ping_response;
+
+ARCHITECTURE tb OF tb_nw_ping_response IS
+
+  CONSTANT c_data_w : NATURAL := 64;
+  
+  CONSTANT c_nof_ping_packet_fields : NATURAL := 21;
+  CONSTANT c_nof_udp_packet_fields : NATURAL := 20;
+  
+  CONSTANT c_ping_packet : t_common_field_arr(c_nof_ping_packet_fields-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac"       ), "RW", 48, field_default(x"ffffffffffff") ),
+                                                                                        ( field_name_pad("eth_src_mac"       ), "RW", 48, field_default(x"e840f2acff78") ),
+                                                                                        ( field_name_pad("eth_type"          ), "RW", 16, field_default(x"0800") ),
+                                                                                        ( 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(x"54") ), 
+                                                                                        ( field_name_pad("ip_identification" ), "RW", 16, field_default(x"3daf") ),
+                                                                                        ( 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(x"40") ),
+                                                                                        ( field_name_pad("ip_protocol"       ), "RW",  8, field_default(1) ),
+                                                                                        ( field_name_pad("ip_header_checksum"), "RW", 16, field_default(x"e580") ),
+                                                                                        ( field_name_pad("ip_src_addr"       ), "RW", 32, field_default(x"0a570224") ),
+                                                                                        ( field_name_pad("ip_dst_addr"       ), "RW", 32, field_default(x"0a5700a8") ),
+                                                                                        ( field_name_pad("icmp_type"         ), "RW",  8, field_default(8) ), 
+                                                                                        ( field_name_pad("icmp_code"         ), "RW",  8, field_default(0) ), 
+                                                                                        ( field_name_pad("icmp_checksum"     ), "RW", 16, field_default(x"117B") ),
+                                                                                        ( field_name_pad("icmp_identifier"   ), "RW", 16, field_default(x"7052") ),
+                                                                                        ( field_name_pad("icmp_seq_number"   ), "RW", 16, field_default(x"0001") ),
+                                                                                        ( field_name_pad("icmp_payload"      ), "RW", 160, field_default(x"123456789ABCDEF01234123456789ABCDEF01234") ) );
+  
+  
+  CONSTANT c_udp_packet : t_common_field_arr(c_nof_udp_packet_fields-1 DOWNTO 0) := ( ( field_name_pad("eth_dst_mac"       ), "RW", 48, field_default(x"00074306C700") ),
+                                                                                      ( 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("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(810) ), 
+                                                                                      ( 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(x"C0A80001") ),
+                                                                                      ( 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"  ), "RW", 16, field_default(790) ),
+                                                                                      ( field_name_pad("udp_checksum"      ), "RW", 16, field_default(0) ),
+                                                                                      ( field_name_pad("udp_payload"       ), "RW", 160, field_default(x"123456789ABCDEF01234123456789ABCDEF01234") ) );
+  
+  CONSTANT c_ping_packet_len : NATURAL := field_slv_out_len(c_ping_packet);
+  CONSTANT c_udp_packet_len  : NATURAL := field_slv_out_len(c_udp_packet);
+  
+  CONSTANT c_ping_packet_slv : STD_LOGIC_VECTOR(c_ping_packet_len -1 DOWNTO 0) := field_map_defaults(c_ping_packet);
+  CONSTANT c_udp_packet_slv  : STD_LOGIC_VECTOR(c_udp_packet_len  -1 DOWNTO 0) := field_map_defaults(c_udp_packet);
+                  
+  CONSTANT c_ping_packet_field_sel : STD_LOGIC_VECTOR(c_nof_ping_packet_fields-1 DOWNTO 0) := (OTHERS => '0');
+  CONSTANT c_udp_packet_field_sel : STD_LOGIC_VECTOR(c_nof_udp_packet_fields-1 DOWNTO 0) := (OTHERS => '0');
+
+  CONSTANT c_nof_ping_responses : NATURAL := 20;
+
+  SIGNAL tb_end             : STD_LOGIC := '0';
+  SIGNAL clk                : STD_LOGIC := '1';
+  SIGNAL rst                : STD_LOGIC := '1';
+  SIGNAL ping_dp_field_blk_snk_in  : t_dp_sosi;
+  SIGNAL ping_dp_field_blk_snk_out : t_dp_siso;
+  SIGNAL ping_dp_field_blk_src_out : t_dp_sosi;
+  SIGNAL ping_dp_field_blk_src_in  : t_dp_siso;
+  
+  SIGNAL udp_dp_field_blk_snk_in  : t_dp_sosi;
+  SIGNAL udp_dp_field_blk_snk_out : t_dp_siso;
+  SIGNAL udp_dp_field_blk_src_out : t_dp_sosi;
+  SIGNAL udp_dp_field_blk_src_in  : t_dp_siso;
+
+  SIGNAL nw_ping_response_snk_in  : t_dp_sosi;
+  SIGNAL nw_ping_response_src_in  : t_dp_siso;
+  SIGNAL nw_ping_response_src_out : t_dp_sosi;
+
+  SIGNAL cnt : NATURAL := 0;
+
+BEGIN
+
+  clk <= (NOT clk) OR tb_end AFTER clk_period/2;
+  rst <= '1', '0' AFTER clk_period*7;
+
+  p_packets : PROCESS(clk)
+  BEGIN
+    IF RISING_EDGE(clk) THEN
+        
+      ping_dp_field_blk_snk_in.data(c_ping_packet_len-1  DOWNTO 0 ) <= c_ping_packet_slv;
+      ping_dp_field_blk_snk_in.valid <= ping_dp_field_blk_snk_out.ready;
+      ping_dp_field_blk_snk_in.sop <= ping_dp_field_blk_snk_out.ready;
+      ping_dp_field_blk_snk_in.eop <= ping_dp_field_blk_snk_out.ready;
+      
+      udp_dp_field_blk_snk_in.data(c_udp_packet_len-1  DOWNTO 0 ) <= c_udp_packet_slv;
+      udp_dp_field_blk_snk_in.valid <= udp_dp_field_blk_snk_out.ready;
+      udp_dp_field_blk_snk_in.sop <= udp_dp_field_blk_snk_out.ready;
+      udp_dp_field_blk_snk_in.eop <= udp_dp_field_blk_snk_out.ready;
+
+    END IF;
+  END PROCESS;
+
+  p_stimuli : PROCESS(clk)
+  VARIABLE start : BOOLEAN := FALSE;
+  BEGIN
+    IF RISING_EDGE(clk) THEN
+      IF cnt = 5 THEN
+        nw_ping_response_snk_in.valid <= '0';
+        nw_ping_response_snk_in.sop <= '0';
+        nw_ping_response_snk_in.eop <= '0';
+        IF ping_dp_field_blk_src_out.sop = '1' THEN
+          start := TRUE;
+        END IF;
+        IF start AND ping_dp_field_blk_src_out.valid = '1' THEN
+          nw_ping_response_snk_in <= ping_dp_field_blk_src_out;
+        END IF;
+        IF udp_dp_field_blk_src_out.eop = '1' THEN
+          cnt <= 0;
+          start := FALSE;
+        END IF;
+
+      ELSE
+        nw_ping_response_snk_in.valid <= '0';
+        nw_ping_response_snk_in.sop <= '0';
+        nw_ping_response_snk_in.eop <= '0';
+        IF udp_dp_field_blk_src_out.sop = '1' THEN
+          start := TRUE;
+        END IF;
+        IF start AND udp_dp_field_blk_src_out.valid = '1' THEN
+          nw_ping_response_snk_in <= udp_dp_field_blk_src_out;
+        END IF;
+        IF ping_dp_field_blk_src_out.eop = '1' THEN
+          cnt <= cnt +1;
+          start := FALSE;
+        END IF;
+      END IF;
+    END IF;
+  END PROCESS;
+ 
+  p_tb_end : PROCESS
+  BEGIN
+    FOR I IN 0 TO 2*c_nof_ping_responses LOOP
+      proc_common_wait_until_evt(clk, nw_ping_response_src_out.eop);
+    END LOOP;
+    tb_end <= '1';
+  END PROCESS;
+
+  nw_ping_response_src_in.xon <= '1';
+  nw_ping_response_src_in.ready <= '1';
+  dut : ENTITY work.nw_ping_response
+    PORT MAP (
+      clk => clk,
+      rst => rst,
+
+      snk_in => nw_ping_response_snk_in,
+
+      src_in  => nw_ping_response_src_in,
+      src_out => nw_ping_response_src_out,
+
+      eth_src_mac => x"14dda9ec2e0f"
+
+    );
+  
+  ping_dp_field_blk_src_in.ready <= '1';
+  ping_dp_field_blk_src_in.xon <= '1';
+  udp_dp_field_blk_src_in.ready <= '1';
+  udp_dp_field_blk_src_in.xon <= '1';
+
+  u_ping_dp_field_blk : ENTITY dp_lib.dp_field_blk
+    GENERIC MAP (
+      g_field_arr      => c_ping_packet,
+      g_field_sel      => c_ping_packet_field_sel,
+      g_snk_data_w     => c_ping_packet_len,
+      g_src_data_w     => c_data_w,
+      g_in_symbol_w    => c_byte_w,
+      g_out_symbol_w   => c_byte_w
+    )
+    PORT MAP (
+      dp_clk       => clk,
+      dp_rst       => rst,
+
+      mm_clk       => '0',
+      mm_rst       => '0',
+  
+      snk_in       => ping_dp_field_blk_snk_in,
+      snk_out      => ping_dp_field_blk_snk_out,
+
+      src_out      => ping_dp_field_blk_src_out,
+      src_in       => ping_dp_field_blk_src_in
+    );
+
+  u_udp_dp_field_blk : ENTITY dp_lib.dp_field_blk
+    GENERIC MAP (
+      g_field_arr      => c_udp_packet,
+      g_field_sel      => c_udp_packet_field_sel,
+      g_snk_data_w     => c_udp_packet_len,
+      g_src_data_w     => c_data_w,
+      g_in_symbol_w    => c_byte_w,
+      g_out_symbol_w   => c_byte_w
+    )
+    PORT MAP (
+      dp_clk       => clk,
+      dp_rst       => rst,
+
+      mm_clk       => '0',
+      mm_rst       => '0',
+  
+      snk_in       => udp_dp_field_blk_snk_in,
+      snk_out      => udp_dp_field_blk_snk_out,
+
+      src_out      => udp_dp_field_blk_src_out,
+      src_in       => udp_dp_field_blk_src_in
+    );
+END tb;
diff --git a/libraries/io/nw_10GbE/tb/vhdl/tb_tb_nw_10GbE.vhd b/libraries/io/nw_10GbE/tb/vhdl/tb_tb_nw_10GbE.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..34d1c7abcda9693cb9d6558de44adef524361a79
--- /dev/null
+++ b/libraries/io/nw_10GbE/tb/vhdl/tb_tb_nw_10GbE.vhd
@@ -0,0 +1,86 @@
+-------------------------------------------------------------------------------
+--
+-- 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: R. van der Walle
+-- Purpose: Multi testbench for nw_10GbE the 10G Ethernet IO module
+-- Description:
+--   The multi-tb finishes when all instances have signaled tb_end.
+-- Usage:
+--   > as 5
+--   > run -all
+-------------------------------------------------------------------------------
+  
+LIBRARY IEEE, technology_lib, tech_pll_lib, tech_mac_10g_lib;
+USE IEEE.std_logic_1164.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+USE tech_mac_10g_lib.tb_tech_mac_10g_pkg.ALL;
+USE tech_pll_lib.tech_pll_component_pkg.ALL;
+
+ENTITY tb_tb_nw_10GbE IS
+END tb_tb_nw_10GbE;
+
+ARCHITECTURE tb OF tb_tb_nw_10GbE IS
+  CONSTANT c_644       : TIME := tech_pll_clk_644_period;
+  CONSTANT c_156       : TIME := 6.4 ns;
+  CONSTANT c_data_type : NATURAL := c_tb_tech_mac_10g_data_type_symbols;
+  
+  CONSTANT c_tb_end_vec : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS=>'1');
+  SIGNAL   tb_end_vec   : STD_LOGIC_VECTOR(7 DOWNTO 0) := c_tb_end_vec;  -- sufficiently long to fit all tb instances
+  SIGNAL   tb_end       : STD_LOGIC := '0';
+BEGIN
+
+-- g_technology              : NATURAL := c_tech_select_default;
+-- g_tb_end                  : BOOLEAN := TRUE;   -- when TRUE then tb_end ends this simulation, else a higher multi-testbench will end the simulation
+-- g_no_dut                  : BOOLEAN := FALSE;  -- default FALSE to verify the DUT, else use TRUE to verify the tb itself without the DUT
+-- g_dp_clk_period           : TIME :=  5 ns;     -- 200 MHz
+-- g_sim_level               : NATURAL := 1;      -- 0 = use IP; 1 = use fast serdes model
+-- g_nof_channels            : NATURAL := 1;
+-- g_direction               : STRING := "TX_RX";  -- "TX_RX", "TX_ONLY", "RX_ONLY"
+-- g_ref_clk_644_period      : TIME := tech_pll_clk_644_period;  -- for 10GBASE-R
+-- g_ref_clk_156_period      : TIME := 6.4 ns;                   -- for XAUI
+-- g_data_type               : NATURAL := c_tb_tech_mac_10g_data_type_symbols;
+-- g_verify_link_recovery    : BOOLEAN := TRUE;
+
+  u_no_dut                     : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE,  TRUE, 5   ns, 0, 1, "TX_RX",   c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(0));
+  u_nw_10GbE                   : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5   ns, 0, 1, "TX_RX",   c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(1));
+  u_nw_10GbE_tx_only           : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5   ns, 0, 1, "TX_ONLY", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(2));
+  u_nw_10GbE_rx_only           : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5   ns, 0, 1, "RX_ONLY", c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(3));
+  u_nw_10GbE_dp_clk_6_5ns      : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 6.5 ns, 0, 1, "TX_RX",   c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(4));
+  gen_2_channels : IF c_tech_select_default = c_tech_stratixiv GENERATE
+    u_nw_10GbE_nof_channels_is_2 : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5   ns, 0, 2, "TX_RX",   c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(5));
+  END GENERATE;
+  -- For arria10, nof_channels need to be 1, 4, 12, 24, 48.
+  gen_24_channels : IF c_tech_select_default /= c_tech_stratixiv GENERATE
+  u_nw_10GbE_nof_channels_is_24 : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5   ns, 0, 24, "TX_RX",   c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(5));
+  END GENERATE;
+  u_nw_10GbE_sim_level_is_1    : ENTITY work.tb_nw_10GbE GENERIC MAP (c_tech_select_default, FALSE, FALSE, 5   ns, 1, 1, "TX_RX",   c_644, c_156, c_data_type, TRUE) PORT MAP (tb_end_vec(6));
+  
+  tb_end <= '1' WHEN tb_end_vec=c_tb_end_vec ELSE '0';
+  
+  p_tb_end : PROCESS
+  BEGIN
+    WAIT UNTIL tb_end='1';
+    WAIT FOR 1 ns;
+    REPORT "Multi tb simulation finished." SEVERITY FAILURE;
+    WAIT;
+  END PROCESS;
+END tb;