diff --git a/libraries/io/eth/hdllib.cfg b/libraries/io/eth/hdllib.cfg
index caeb990a2db4a10e44694b0e95de3c5de0ec6006..11d97855c2d2c66fc69d0db9120c34e4d56095d3 100644
--- a/libraries/io/eth/hdllib.cfg
+++ b/libraries/io/eth/hdllib.cfg
@@ -1,6 +1,6 @@
 hdl_lib_name = eth
 hdl_library_clause_name = eth_lib
-hdl_lib_uses_synth = dp common tech_tse
+hdl_lib_uses_synth = dp common diag tech_tse
 hdl_lib_uses_sim = 
 hdl_lib_technology = 
 
@@ -22,6 +22,7 @@ synth_files =
     src/vhdl/eth_control.vhd
     src/vhdl/eth_ihl_to_20.vhd
     src/vhdl/eth.vhd
+    src/vhdl/eth_tester_pkg.vhd
     src/vhdl/eth_tester_tx.vhd
     src/vhdl/eth_tester_rx.vhd
     src/vhdl/eth_tester.vhd
@@ -32,6 +33,7 @@ test_bench_files =
     tb/vhdl/tb_eth_crc_ctrl.vhd
     tb/vhdl/tb_eth_hdr.vhd
     tb/vhdl/tb_eth.vhd
+    tb/vhdl/tb_eth_tester_pkg.vhd
     tb/vhdl/tb_eth_tester.vhd
     tb/vhdl/tb_tb_eth.vhd
     tb/vhdl/tb_tb_eth_tester.vhd
diff --git a/libraries/io/eth/src/vhdl/eth_tester_pkg.vhd b/libraries/io/eth/src/vhdl/eth_tester_pkg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..24568275536e99554e753fb22938cc7dc2600c4b
--- /dev/null
+++ b/libraries/io/eth/src/vhdl/eth_tester_pkg.vhd
@@ -0,0 +1,147 @@
+-------------------------------------------------------------------------------
+--
+-- 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: E. Kooistra
+-- Purpose: This package contains ethe_tester specific constants and functions
+-- Description: See [1]
+-- References:
+-- . [1] https://support.astron.nl/confluence/display/L2M/L3+SDP+Decision%3A+SDP+Parameter+definitions
+--
+LIBRARY IEEE, common_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
+
+PACKAGE eth_tester_pkg is
+
+  -- hdr_field_sel bit selects where the hdr_field value is set:
+  -- . 0 = data path controlled, value is set in data path, so field_default() is not used.
+  -- . 1 = MM controlled, value is set via MM or by the field_default(), so any data path setting in
+  --       eth_tester.vhd is not used.
+  -- Remarks:
+  -- . For constant values it is convenient to use MM controlled, because then the field_default()
+  --   is used that can be set here in c_eth_tester_hdr_field_arr.
+  -- . For reserved values it is convenient to use MM controlled, because then in future they
+  --   could still be changed via MM without having to recompile the FW.
+  -- . Typically only use data path controlled if the value has to be set dynamically, so dependent
+  --   on the state of the FW.
+  -- . If a data path controlled field is not set in the FW, then it defaults to 0 by declaring
+  --   hdr_fields_in_arr with all 0. Hence e.g. udp_checksum = 0 can be achieve via data path
+  --   and default hdr_fields_in_arr = 0 or via MM controlled and field_default(0).
+  CONSTANT c_eth_tester_nof_hdr_fields    : NATURAL := 1+3+12+4+3;
+  CONSTANT c_eth_tester_hdr_field_sel     : STD_LOGIC_VECTOR(c_eth_tester_nof_hdr_fields-1 DOWNTO 0) := "1"&"101"&"111011111001"&"0100"&"100";
+
+  -- Default use destination MAC/IP/UDP = 0, so these have to be MM programmed before
+  -- eth_tester packets can be send.
+  CONSTANT c_eth_tester_hdr_field_arr : t_common_field_arr(c_eth_tester_nof_hdr_fields-1 DOWNTO 0) := (
+      ( field_name_pad("word_align"                              ), "RW", 16, field_default(0) ),  -- Tx TSE IP will strip these 2 padding bytes
+      ( field_name_pad("eth_dst_mac"                             ), "RW", 48, field_default(0) ),  -- c_eth_tester_eth_dst_mac
+      ( 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(0) ),  -- depends on BG block size, so set by data path
+      ( field_name_pad("ip_identification"                       ), "RW", 16, field_default(0) ),
+      ( field_name_pad("ip_flags"                                ), "RW",  3, field_default(2) ),
+      ( field_name_pad("ip_fragment_offset"                      ), "RW", 13, field_default(0) ),
+      ( field_name_pad("ip_time_to_live"                         ), "RW",  8, field_default(127) ),
+      ( field_name_pad("ip_protocol"                             ), "RW",  8, field_default(17) ),
+      ( field_name_pad("ip_header_checksum"                      ), "RW", 16, field_default(0) ),
+      ( field_name_pad("ip_src_addr"                             ), "RW", 32, field_default(0) ),
+      ( field_name_pad("ip_dst_addr"                             ), "RW", 32, field_default(0) ),  -- c_eth_tester_ip_dst_addr
+
+      ( field_name_pad("udp_src_port"                            ), "RW", 16, field_default(0) ),
+      ( field_name_pad("udp_dst_port"                            ), "RW", 16, field_default(0) ),  -- c_eth_tester_udp_dst_port
+      ( field_name_pad("udp_total_length"                        ), "RW", 16, field_default(0) ),  -- depends on BG block size, so set by data path
+      ( field_name_pad("udp_checksum"                            ), "RW", 16, field_default(0) ),
+
+      ( field_name_pad("dp_reserved"                             ), "RW", 31, field_default(0) ),
+      ( field_name_pad("dp_sync"                                 ), "RW",  1, field_default(0) ),
+      ( field_name_pad("dp_bsn"                                  ), "RW", 64, field_default(0) )
+  );
+  CONSTANT c_eth_tester_reg_hdr_dat_addr_w : NATURAL := ceil_log2(field_nof_words(c_eth_tester_hdr_field_arr, c_word_w));
+
+  CONSTANT c_eth_tester_app_hdr_len  : NATURAL :=  12;  -- octets
+
+  CONSTANT c_eth_tester_eth_src_mac_47_16 : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"00228608";  -- 00:22:86:08:pp:qq = UNB_ETH_SRC_MAC_BASE in libraries/unb_osy/unbos_eth.h
+  CONSTANT c_eth_tester_ip_src_addr_31_16 : STD_LOGIC_VECTOR(15 DOWNTO 0) := x"0A63";    -- 10.99.xx.yy = g_base_ip in ctrl_unb2#_board.vhd used in libraries/unb_osy/unbos_eth.c
+  CONSTANT c_eth_tester_udp_src_port_15_8 : STD_LOGIC_VECTOR( 7 DOWNTO 0) := x"E0";  -- TBC, 7:0 = gn_id (= ID[7:0] = backplane[5:0] & node[1:0])
+
+  TYPE t_eth_tester_app_header IS RECORD
+    dp_reserved : STD_LOGIC_VECTOR(30 DOWNTO 0);
+    dp_sync     : STD_LOGIC;
+    dp_bsn      : STD_LOGIC_VECTOR(63 DOWNTO 0);
+  END RECORD;
+
+  TYPE t_eth_tester_header IS RECORD
+    eth : t_network_eth_header;
+    ip  : t_network_ip_header;
+    udp : t_network_udp_header;
+    app : t_eth_tester_app_header;
+  END RECORD;
+
+  FUNCTION func_eth_tester_map_header(hdr_fields_raw : STD_LOGIC_VECTOR) RETURN t_eth_tester_header;
+
+END eth_tester_pkg;
+
+
+PACKAGE BODY eth_tester_pkg IS
+
+  FUNCTION func_eth_tester_map_header(hdr_fields_raw : STD_LOGIC_VECTOR) RETURN t_eth_tester_header IS
+    VARIABLE v : t_eth_tester_header;
+  BEGIN
+    -- eth header
+    v.eth.dst_mac        := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "eth_dst_mac") DOWNTO field_lo(c_eth_tester_hdr_field_arr, "eth_dst_mac"));
+    v.eth.src_mac        := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "eth_src_mac") DOWNTO field_lo(c_eth_tester_hdr_field_arr, "eth_src_mac"));
+    v.eth.eth_type       := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "eth_type")    DOWNTO field_lo(c_eth_tester_hdr_field_arr, "eth_type"));
+
+    -- ip header
+    v.ip.version         := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_version")         DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_version"));
+    v.ip.header_length   := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_header_length")   DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_header_length"));
+    v.ip.services        := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_services")        DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_services"));
+    v.ip.total_length    := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_total_length")    DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_total_length"));
+    v.ip.identification  := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_identification")  DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_identification"));
+    v.ip.flags           := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_flags")           DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_flags"));
+    v.ip.fragment_offset := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_fragment_offset") DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_fragment_offset"));
+    v.ip.time_to_live    := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_time_to_live")    DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_time_to_live"));
+    v.ip.protocol        := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_protocol")        DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_protocol"));
+    v.ip.header_checksum := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_header_checksum") DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_header_checksum"));
+    v.ip.src_ip_addr     := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_src_addr")        DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_src_addr"));
+    v.ip.dst_ip_addr     := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "ip_dst_addr")        DOWNTO field_lo(c_eth_tester_hdr_field_arr, "ip_dst_addr"));
+
+    -- udp header
+    v.udp.src_port       := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "udp_src_port")     DOWNTO field_lo(c_eth_tester_hdr_field_arr, "udp_src_port"));
+    v.udp.dst_port       := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "udp_dst_port")     DOWNTO field_lo(c_eth_tester_hdr_field_arr, "udp_dst_port"));
+    v.udp.total_length   := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "udp_total_length") DOWNTO field_lo(c_eth_tester_hdr_field_arr, "udp_total_length"));
+    v.udp.checksum       := hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "udp_checksum")     DOWNTO field_lo(c_eth_tester_hdr_field_arr, "udp_checksum"));
+
+    -- app header
+    v.app.dp_reserved    :=    hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "dp_reserved") DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_reserved"));
+    v.app.dp_sync        := sl(hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "dp_sync")     DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_sync")));
+    v.app.dp_bsn         :=    hdr_fields_raw(field_hi(c_eth_tester_hdr_field_arr, "dp_bsn")      DOWNTO field_lo(c_eth_tester_hdr_field_arr, "dp_bsn"));
+    RETURN v;
+  END func_eth_tester_map_header;
+
+END eth_tester_pkg;
+
diff --git a/libraries/io/eth/tb/vhdl/tb_eth_tester_pkg.vhd b/libraries/io/eth/tb/vhdl/tb_eth_tester_pkg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..7c4e0d8f7686ea3a1cb76d937840c32ecd95fce7
--- /dev/null
+++ b/libraries/io/eth/tb/vhdl/tb_eth_tester_pkg.vhd
@@ -0,0 +1,46 @@
+-------------------------------------------------------------------------------
+--
+-- 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: E. Kooistra
+-- Purpose: This package contains eth_tester specific constants and functions
+--          for use in a test bench
+-- Description: See [1]
+-- References:
+-- . [1] https://support.astron.nl/confluence/display/L2M/L3+SDP+Decision%3A+SDP+Parameter+definitions
+--
+LIBRARY IEEE, common_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_field_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
+
+PACKAGE tb_eth_tester_pkg is
+
+  CONSTANT c_eth_tester_eth_dst_mac       : STD_LOGIC_VECTOR(47 DOWNTO 0) := x"001B217176B9";  -- 001B217176B9 = DOP36-enp2s0
+  CONSTANT c_eth_tester_ip_dst_addr       : STD_LOGIC_VECTOR(31 DOWNTO 0) := x"0A6300FE";  -- 0A6300FE = '10.99.0.254' = DOP36-enp2s0
+  CONSTANT c_eth_tester_udp_dst_port      : STD_LOGIC_VECTOR(15 DOWNTO 0) := TO_UVEC(6001, 16);  -- 0x1771 = 6001
+
+END tb_eth_tester_pkg;
+
+
+PACKAGE BODY tb_eth_tester_pkg IS
+END tb_eth_tester_pkg;
+