diff --git a/libraries/technology/eth_10g/tb_tech_eth_10g.vhd b/libraries/technology/eth_10g/tb_tech_eth_10g.vhd
index d643609e24855084f92e4e31c58f8e20795ab221..7b3ecee18d5ecc692330aa0e10a1140027d588dc 100644
--- a/libraries/technology/eth_10g/tb_tech_eth_10g.vhd
+++ b/libraries/technology/eth_10g/tb_tech_eth_10g.vhd
@@ -49,7 +49,7 @@ ENTITY tb_tech_eth_10g IS
     g_technology              : NATURAL := c_tech_select_default;
     g_tech_pll_clk_644_period : TIME := tech_pll_clk_644_period;
     g_data_type               : NATURAL := c_tb_tech_mac_10g_data_type_symbols;
-    g_verify_link_recovery    : BOOLEAN := TRUE;
+    g_verify_link_recovery    : BOOLEAN := FALSE;--TRUE;
     g_link_status_check       : STD_LOGIC_VECTOR(c_tech_mac_10g_link_status_w-1 DOWNTO 0) := "11";
     g_use_rx_serial_in        : BOOLEAN := FALSE 
   );
@@ -62,9 +62,9 @@ END tb_tech_eth_10g;
 
 ARCHITECTURE tb OF tb_tech_eth_10g IS
 
-  CONSTANT mm_clk_period            : TIME := 20 ns;    --  50 MHz
   CONSTANT phy_delay                : TIME :=  0 ns;
   
+  CONSTANT c_phy_loopback       : BOOLEAN := NOT g_use_rx_serial_in;
   CONSTANT c_st_loopback        : BOOLEAN := FALSE;  -- default FALSE to verify the DUT, else use TRUE to verify the tb itself without the DUT
   CONSTANT c_rl                 : NATURAL := 1;
   CONSTANT c_nof_tx_not_valid   : NATURAL := 0;  -- when > 0 then pull tx valid low for c_nof_tx_not_valid beats during tx
@@ -74,7 +74,7 @@ ARCHITECTURE tb OF tb_tech_eth_10g IS
   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 := c_nof_pkt1 + c_nof_pkt2;
+  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
@@ -90,6 +90,7 @@ ARCHITECTURE tb OF tb_tech_eth_10g IS
   SIGNAL total_header      : t_network_total_header := c_network_total_header_ones;  -- default fill all fields with value 1
   
   -- Clocks and reset
+  SIGNAL rx_end            : STD_LOGIC := '0';
   SIGNAL tb_end            : STD_LOGIC := '0';
   SIGNAL mm_clk            : STD_LOGIC := '0';  -- memory-mapped bus clock
   SIGNAL mm_rst            : STD_LOGIC;         -- reset synchronous with mm_clk
@@ -100,15 +101,14 @@ ARCHITECTURE tb OF tb_tech_eth_10g IS
 
   -- 10G MAC control interface
   SIGNAL mm_init           : STD_LOGIC := '1';
-  SIGNAL mm_mosi_wrdata    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- 32 bit;
   SIGNAL mm_mosi           : t_mem_mosi;
+  SIGNAL mm_mosi_wrdata    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- 32 bit;
   SIGNAL mm_miso           : t_mem_miso;
   SIGNAL mm_miso_rdval     : STD_LOGIC;
   SIGNAL mm_miso_rddata    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- 32 bit;
   
   -- 10G MAC transmit interface
   -- . The tb is the ST source
-  SIGNAL tx_en             : STD_LOGIC := '1';
   SIGNAL tx_siso           : t_dp_siso;
   SIGNAL tx_siso_arr       : t_dp_siso_arr(0 DOWNTO 0);
   SIGNAL tx_sosi           : t_dp_sosi;
@@ -125,155 +125,61 @@ ARCHITECTURE tb OF tb_tech_eth_10g IS
 
   -- 10G PHY serial interface
   SIGNAL tx_serial_arr       : STD_LOGIC_VECTOR(0 DOWNTO 0);
-  SIGNAL tx_serial_arr_dly   : STD_LOGIC_VECTOR(0 DOWNTO 0);
   SIGNAL rx_serial_arr       : STD_LOGIC_VECTOR(0 DOWNTO 0);
   
   -- Model a serial link fault
   SIGNAL link_fault          : STD_LOGIC;
 
   -- Verification
-  SIGNAL expected_sosi_arr : t_dp_sosi_arr(0 TO c_nof_pkt-1);
-
-  SIGNAL tx_pkt_cnt     : NATURAL := 0;
-  SIGNAL rx_pkt_cnt     : NATURAL := 0;
+  SIGNAL tx_pkt_cnt        : NATURAL := 0;
+  SIGNAL rx_pkt_cnt        : NATURAL := 0;
+  SIGNAL rx_toggle         : STD_LOGIC;  -- toggle after every received packet
   
 BEGIN
 
-  -- run 50 us
-  mm_clk         <= NOT mm_clk         AFTER mm_clk_period/2;          -- MM clock
-  
-  mm_rst <= '1', '0' AFTER mm_clk_period*10;
-
   -- debug signals to ease monitoring in wave window  
-  tx_sosi_data <= tx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0);
-  rx_sosi_data <= rx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0);
-  
   mm_mosi_wrdata <= mm_mosi.wrdata(c_word_w-1 DOWNTO 0);
   mm_miso_rddata <= mm_miso.rddata(c_word_w-1 DOWNTO 0);
   mm_miso_rdval <= '1' WHEN mm_mosi.rd='1' AND mm_miso.waitrequest='0' ELSE '0';  -- c_rd_latency = 1
-                   
+  
+  tx_sosi_data <= tx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0);
+  rx_sosi_data <= rx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0);
+  
   -- Use signal to leave unused fields 'X'
   total_header.eth <= c_eth_header_ethertype;
 
-  p_mm_setup : PROCESS
-  BEGIN
-    mm_init  <= '1';
-    mm_mosi.wr <= '0';
-    mm_mosi.rd <= '0';
-
-    -- wait until after reset release
-    proc_common_wait_until_low(mm_clk, mm_rst);
-    proc_common_wait_some_cycles(mm_clk, 10);
-
-    proc_tech_mac_10g_setup(g_technology,
-                            c_src_mac,
-                            mm_clk, mm_miso, mm_mosi);
-    mm_init <= '0';
-    WAIT;
-  END PROCESS;
-
+  u_mm_setup : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_setup
+  GENERIC MAP (
+    g_technology    => g_technology,
+    g_src_mac       => c_src_mac
+  )
+  PORT MAP (
+    tb_end    => tb_end,
+    mm_clk    => mm_clk,
+    mm_rst    => mm_rst,
+    mm_init   => mm_init,
+    mm_mosi   => mm_mosi,
+    mm_miso   => mm_miso
+  );
   
-  p_ff_transmitter : PROCESS
-  BEGIN
-    link_fault <= '0';
-    
-    -- . Avalon ST
-    tx_sosi  <= c_dp_sosi_rst;
-
-    WHILE mm_init/='0' LOOP
-      WAIT UNTIL rising_edge(clk_156);
-    END LOOP;
-    proc_common_wait_some_cycles(clk_156, 10);
-
-    -- Loopback txp->rxp so use promiscuous mode or use DST_MAC = c_src_mac to send to itself
-    
-    -- TX frame:
-    -- . I=0 is empty payload, so only 4 words of the ETH header with 46 padding zeros, so empty = 2
-    -- . For I=1 to 46 the payload length remains 46 with padding zeros, so empty = 2
-    -- . For I>46 the payload length is I and empty = 4 - (I mod 4)
-    
-    FOR I IN 0 TO c_nof_pkt1-1 LOOP
-      proc_tech_mac_10g_tx_packet(total_header, c_pkt_length_arr1(I), g_data_type, c_rl, c_nof_tx_not_valid, clk_156, tx_en, tx_siso, tx_sosi);
-      proc_common_wait_some_cycles(clk_156, 0);
-    END LOOP;
-
-    proc_common_wait_some_cycles(clk_156, c_pkt_length_arr1(c_nof_pkt1-1)/c_tech_mac_10g_symbols_per_beat);
-    proc_common_wait_some_cycles(clk_156, 100);
-    
-    IF g_verify_link_recovery=TRUE THEN
-      -- Model a link fault to verify Rx recovery
-      link_fault <= '1';
-      proc_common_wait_some_cycles(clk_156, 1000);
-      link_fault <= '0';
-    
-      FOR I IN 0 TO c_nof_pkt2-1 LOOP
-        proc_tech_mac_10g_tx_packet(total_header, c_pkt_length_arr2(I), g_data_type, c_rl, c_nof_tx_not_valid, clk_156, tx_en, tx_siso, tx_sosi);
-        proc_common_wait_some_cycles(clk_156, 0);
-      END LOOP;
-    
-      proc_common_wait_some_cycles(clk_156, c_pkt_length_arr2(c_nof_pkt2-1)/c_tech_mac_10g_symbols_per_beat);
-      proc_common_wait_some_cycles(clk_156, 100);
-    END IF;
+  -- 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,
+    clk_156        => clk_156,
+    tx_siso        => tx_siso,
+    tx_sosi        => tx_sosi,
+    link_fault     => link_fault,
+    tx_end         => rx_end
+  );
     
-    tb_end <= '1';
-    WAIT;
-  END PROCESS;
-
-  
-  p_ff_receiver : PROCESS
-  BEGIN
-    -- . Avalon ST
-    rx_siso <= c_dp_siso_hold;
-
-    WHILE mm_init/='0' LOOP
-      WAIT UNTIL rising_edge(clk_156);
-    END LOOP;
-
-    -- Receive forever
-    WHILE TRUE LOOP
-      proc_tech_mac_10g_rx_packet(total_header, g_data_type, clk_156, rx_sosi, rx_siso);
-    END LOOP;
-
-    WAIT;
-  END PROCESS;
-  
-  
-  p_ff_store_tx_sosi_at_eop : PROCESS(clk_156)
-    VARIABLE vI : NATURAL := 0;
-  BEGIN
-    IF rising_edge(clk_156) THEN
-      IF tx_sosi.eop='1' THEN
-        expected_sosi_arr(vI) <= tx_sosi;
-        vI := vI +1;
-      END IF;
-    END IF;
-  END PROCESS;
-
-  p_ff_verify_rx_sosi_at_eop : PROCESS(clk_156)
-    VARIABLE vI   : NATURAL := 0;
-    VARIABLE vLow : NATURAL := 0;
-  BEGIN
-    IF rising_edge(clk_156) THEN
-      IF rx_sosi.eop='1' THEN
-          -- frame shorter than 64 get padded so em 
-        IF c_pkt_length_arr(vI) < 64 - 14 - 20 - 8 - 4 THEN  -- = minimum frame 64 - ETH 14 - IP 20 - UDP 8 - CRC 4
-          -- frame shorter than 64 get padded so empty after stripping the Rx CRC is fixed 4, which becomes 6 due to pre header padding for UDP word align
-          IF TO_UINT(rx_sosi.empty) /= 6 THEN
-            REPORT "RX: Wrong padded empty" SEVERITY ERROR;
-          END IF;
-        ELSE
-          IF rx_sosi.empty /= expected_sosi_arr(vI).empty THEN
-            REPORT "RX: Wrong empty" SEVERITY ERROR;
-          ELSE
-            vLow := TO_UINT(rx_sosi.empty)*8;
-            ASSERT rx_sosi.data(63 DOWNTO vLow) = expected_sosi_arr(vI).data(63 DOWNTO vLow)  REPORT "RX: Wrong data at eop" SEVERITY ERROR;
-          END IF;
-        END IF;
-        vI := vI +1;
-      END IF;
-    END IF;
-  END PROCESS;
-
   -- Rewire DP to DP array type.
   tx_sosi_arr(0) <= tx_sosi;
   tx_siso        <= tx_siso_arr(0);
@@ -295,6 +201,11 @@ BEGIN
     rst_312    => OPEN
   );
     
+  no_dut : IF c_st_loopback=TRUE GENERATE
+    rx_sosi <= tx_sosi;
+    tx_siso <= rx_siso;
+  END GENERATE;
+
   gen_dut : IF c_st_loopback=FALSE GENERATE
     dut : ENTITY work.tech_eth_10g
     GENERIC MAP (
@@ -334,47 +245,71 @@ BEGIN
     );
   END GENERATE;
 
-  no_dut : IF c_st_loopback=TRUE GENERATE
-    rx_sosi <= tx_sosi;
-    tx_siso <= rx_siso;
-  END GENERATE;
-
-  -- Loopback serial
-  tx_serial_arr_dly <= TRANSPORT tx_serial_arr AFTER phy_delay;
-  tx_serial_out <= tx_serial_arr_dly(0);
+  u_link_connect : ENTITY tech_mac_10g_lib.tb_tech_mac_10g_link_connect
+  GENERIC MAP (
+    g_loopback    => c_phy_loopback,  -- default TRUE for loopback tx to rx, else use FALSE to connect tx-tx, rx-rx between two tb devices
+    g_link_delay  => phy_delay
+  )
+  PORT MAP (
+    -- Serial layer connect
+    link_fault    => link_fault,      -- when '1' then forces rx_serial_arr(0)='0'
+    tx_serial_arr => tx_serial_arr,
+    rx_serial_arr => rx_serial_arr,   -- connects to delayed tx_serial_arr(0) when g_loopback=TRUE else to rx_serial_in
+    
+    -- . external connect
+    tx_serial_out => tx_serial_out,   -- connects to delayed tx_serial_arr(0)
+    rx_serial_in  => rx_serial_in     -- used when g_loopback=FALSE
+  );
+  
+  -- Packet receiver
+  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,
+    clk_156        => clk_156,
+    rx_sosi        => rx_sosi,
+    rx_siso        => rx_siso,
+    rx_toggle      => rx_toggle
+  );
   
-  p_rx_serial : PROCESS(tx_serial_arr_dly, rx_serial_in, link_fault)
-  BEGIN
-    IF g_use_rx_serial_in=FALSE THEN
-      rx_serial_arr <= tx_serial_arr_dly;
-    ELSE
-      rx_serial_arr(0) <= rx_serial_in;
-    END IF;
-    IF link_fault='1' THEN
-      rx_serial_arr(0) <= '0';
-    END IF;
-  END PROCESS;
-
   -- Verification
-  tx_pkt_cnt <= tx_pkt_cnt + 1 WHEN tx_sosi.sop='1' AND rising_edge(clk_156);
-  rx_pkt_cnt <= rx_pkt_cnt + 1 WHEN rx_sosi.eop='1' AND rising_edge(clk_156);
+  u_verify_rx_at_eop : ENTITY tech_mac_10g_lib.tb_tech_mac_10_verify_rx_at_eop
+  GENERIC MAP (
+    g_no_padding     => FALSE,
+    g_pkt_length_arr => c_pkt_length_arr
+  )
+  PORT MAP (
+    tx_clk_156     => clk_156,
+    tx_sosi        => tx_sosi,
+    rx_clk_156     => clk_156,
+    rx_sosi        => rx_sosi
+  );  
+
+  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_156     => clk_156,
+    tx_sosi        => tx_sosi,
+    rx_clk_156     => clk_156,
+    rx_sosi        => rx_sosi,
+    tx_pkt_cnt     => tx_pkt_cnt,
+    rx_pkt_cnt     => rx_pkt_cnt,
+    rx_end         => rx_end
+  );
   
   p_tb_end : PROCESS  
   BEGIN
-    WAIT UNTIL tb_end='1';
-    
-    -- Verify that all transmitted packets have been received
-    IF tx_pkt_cnt=0 THEN
-      REPORT "No packets were transmitted." SEVERITY ERROR;
-    ELSIF rx_pkt_cnt=0 THEN
-      REPORT "No packets were received." SEVERITY ERROR;
-    ELSIF tx_pkt_cnt/=rx_pkt_cnt THEN
-      REPORT "Not all transmitted packets were received." SEVERITY ERROR;
-    END IF;
+    WAIT UNTIL rx_end='1';
     proc_common_wait_some_cycles(clk_156, 100);
     --proc_common_wait_some_cycles(clk_156, 10000);  -- uncomment to simulate somewhat longer without tx packet data
     
     -- Stop the simulation
+    tb_end <= '1';
     ASSERT FALSE REPORT "Simulation finished." SEVERITY FAILURE;
     WAIT;
   END PROCESS;
diff --git a/libraries/technology/mac_10g/hdllib.cfg b/libraries/technology/mac_10g/hdllib.cfg
index 853302e9b317a8f2fa1a646ac5929b91cd730054..bfb3906b3b06722b25beba1f9aef6ee8b92cf55e 100644
--- a/libraries/technology/mac_10g/hdllib.cfg
+++ b/libraries/technology/mac_10g/hdllib.cfg
@@ -14,6 +14,12 @@ synth_files =
 
 test_bench_files =
     tb_tech_mac_10g_pkg.vhd
+    tb_tech_mac_10g_setup.vhd
+    tb_tech_mac_10g_transmitter.vhd
+    tb_tech_mac_10g_receiver.vhd
+    tb_tech_mac_10g_link_connect.vhd
+    tb_tech_mac_10g_verify_rx_at_eop.vhd
+    tb_tech_mac_10g_verify_rx_pkt_cnt.vhd
     tb_tech_mac_10g.vhd
     tb_tb_tech_mac_10g.vhd
 
diff --git a/libraries/technology/mac_10g/tb_tech_mac_10g.vhd b/libraries/technology/mac_10g/tb_tech_mac_10g.vhd
index 33f1d4af4bafcc893e98207574441c8dc8367b35..2bc36de41d984dd53efa9d12839ba704fe8fd889 100644
--- a/libraries/technology/mac_10g/tb_tech_mac_10g.vhd
+++ b/libraries/technology/mac_10g/tb_tech_mac_10g.vhd
@@ -23,9 +23,9 @@
 -- 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.
+--   . rx_pkt_cnt = tx_pkt_cnt > 0 must be true at the tb_end.
 -- Usage:
---   > do wave_tb_tech_mac_10g.do
+--   > as 10
 --   > run -all
 
 LIBRARY IEEE, technology_lib, common_lib, dp_lib;
@@ -58,13 +58,11 @@ END tb_tech_mac_10g;
 
 ARCHITECTURE tb OF tb_tech_mac_10g IS
 
-  CONSTANT mm_clk_period        : TIME := 20 ns;    --  50 MHz
   CONSTANT clk_156_period       : TIME :=  6.4 ns;  -- 156.25 MHz
   CONSTANT phy_delay            : TIME :=  0 ns;
   
   CONSTANT c_rl                 : NATURAL := 1;
   CONSTANT c_nof_tx_not_valid   : NATURAL := 0;  -- when > 0 then pull tx valid low for c_nof_tx_not_valid beats during tx
-  --CONSTANT c_pkt_length_arr     : t_nat_natural_arr := (0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 1472, 1473, 9000);
   CONSTANT c_pkt_length_arr     : 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_nof_pkt            : NATURAL := c_pkt_length_arr'LENGTH;
@@ -98,15 +96,14 @@ ARCHITECTURE tb OF tb_tech_mac_10g IS
 
   -- 10G MAC control interface
   SIGNAL mm_init           : STD_LOGIC := '1';
-  SIGNAL mm_mosi_wrdata    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- 32 bit;
   SIGNAL mm_mosi           : t_mem_mosi;
+  SIGNAL mm_mosi_wrdata    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- 32 bit;
   SIGNAL mm_miso           : t_mem_miso;
   SIGNAL mm_miso_rdval     : STD_LOGIC;
   SIGNAL mm_miso_rddata    : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);  -- 32 bit;
   
   -- 10G MAC transmit interface
   -- . The tb is the ST source
-  SIGNAL tx_en             : STD_LOGIC := '1';
   SIGNAL tx_siso           : t_dp_siso;
   SIGNAL tx_sosi           : t_dp_sosi;
   SIGNAL tx_sosi_data      : STD_LOGIC_VECTOR(c_tech_mac_10g_data_w-1 DOWNTO 0);  -- 64 bit
@@ -115,7 +112,6 @@ ARCHITECTURE tb OF tb_tech_mac_10g IS
   -- . The tb is the ST sink
   SIGNAL rx_siso           : t_dp_siso;
   SIGNAL rx_sosi           : t_dp_sosi;
-  SIGNAL rx_sosi_reg       : t_dp_sosi;
   SIGNAL rx_sosi_data      : STD_LOGIC_VECTOR(c_tech_mac_10g_data_w-1 DOWNTO 0);  -- 64 bit
 
   -- 10G MAC XGMII interface
@@ -124,15 +120,12 @@ ARCHITECTURE tb OF tb_tech_mac_10g IS
   SIGNAL xgmii_rx_data     : STD_LOGIC_VECTOR(c_xgmii_w-1 DOWNTO 0);  -- 72 bit
 
   -- Verification
-  SIGNAL expected_sosi_arr : t_dp_sosi_arr(0 TO c_nof_pkt-1);
-
-  SIGNAL tx_pkt_cnt     : NATURAL := 0;
-  SIGNAL rx_pkt_cnt     : NATURAL := 0;
-  SIGNAL rx_toggle      : STD_LOGIC := '0';  -- toggle after every received packet
+  SIGNAL tx_pkt_cnt        : NATURAL := 0;
+  SIGNAL rx_pkt_cnt        : NATURAL := 0;
+  SIGNAL rx_toggle         : STD_LOGIC;  -- toggle after every received packet
   
 BEGIN
 
-  mm_clk  <= NOT mm_clk  OR tb_end AFTER mm_clk_period/2;   -- MM clock
   clk_156 <= NOT clk_156 OR tb_end AFTER clk_156_period/2;
   clk_312 <= NOT clk_312 OR tb_end AFTER clk_156_period/4;
   tx_ref_clk_156 <= clk_156;               -- mac_10g tx reference clock
@@ -140,123 +133,50 @@ BEGIN
   rx_phy_clk_156 <= clk_156;               -- use clk_156 to model PHY
   rx_phy_clk_312 <= clk_312;
   
-  mm_rst <= '1', '0' AFTER mm_clk_period*10;
   tx_rst <= '1', '0' AFTER clk_156_period*10;
   rx_rst <= '1', '0' AFTER clk_156_period*10;
 
   -- debug signals to ease monitoring in wave window  
-  tx_sosi_data <= tx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0);
-  rx_sosi_data <= rx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0);
-  
   mm_mosi_wrdata <= mm_mosi.wrdata(c_word_w-1 DOWNTO 0);
   mm_miso_rddata <= mm_miso.rddata(c_word_w-1 DOWNTO 0);
   mm_miso_rdval <= '1' WHEN mm_mosi.rd='1' AND mm_miso.waitrequest='0' ELSE '0';  -- c_rd_latency = 1
-                   
-  -- Use signal to leave unused fields 'X'
-  total_header.eth <= c_eth_header_ethertype;
-
-  p_mm_setup : PROCESS
-  BEGIN
-    mm_init  <= '1';
-    mm_mosi.wr <= '0';
-    mm_mosi.rd <= '0';
-
-    -- wait until after reset release
-    proc_common_wait_until_low(mm_clk, mm_rst);
-    proc_common_wait_some_cycles(mm_clk, 10);
-
-    proc_tech_mac_10g_setup(g_technology,
-                            c_src_mac,
-                            mm_clk, mm_miso, mm_mosi);
-    mm_init <= '0';
-    WAIT;
-  END PROCESS;
-
   
-  p_ff_transmitter : PROCESS
-  BEGIN
-    -- . Avalon ST
-    tx_sosi  <= c_dp_sosi_rst;
-
-    WHILE mm_init/='0' LOOP
-      WAIT UNTIL rising_edge(tx_ref_clk_156);
-    END LOOP;
-    proc_common_wait_some_cycles(tx_ref_clk_156, 10);
-
-    -- Loopback txp->rxp so use promiscuous mode or use DST_MAC = c_src_mac to send to itself
-    
-    -- TX frame:
-    -- . I=0 is empty payload, so only 4 words of the ETH header with 46 padding zeros, so empty = 2
-    -- . For I=1 to 46 the payload length remains 46 with padding zeros, so empty = 2
-    -- . For I>46 the payload length is I and empty = 4 - (I mod 4)
-    
-    FOR I IN 0 TO c_nof_pkt-1 LOOP
-      proc_tech_mac_10g_tx_packet(total_header, c_pkt_length_arr(I), g_data_type, c_rl, c_nof_tx_not_valid, tx_ref_clk_156, tx_en, tx_siso, tx_sosi);
-      proc_common_wait_some_cycles(tx_ref_clk_156, 0);
-    END LOOP;
-
-    proc_common_wait_some_cycles(tx_ref_clk_156, c_pkt_length_arr(c_nof_pkt-1)/c_tech_mac_10g_symbols_per_beat);
-    proc_common_wait_some_cycles(tx_ref_clk_156, 100);
-    rx_end <= '1';
-    WAIT;
-  END PROCESS;
-
+  tx_sosi_data <= tx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0);
+  rx_sosi_data <= rx_sosi.data(c_tech_mac_10g_data_w-1 DOWNTO 0);
   
-  p_ff_receiver : PROCESS
-  BEGIN
-    -- . Avalon ST
-    rx_siso <= c_dp_siso_hold;
-
-    WHILE mm_init/='0' LOOP
-      WAIT UNTIL rising_edge(rx_phy_clk_156);
-    END LOOP;
+  -- Use signal to leave unused fields 'X'
+  total_header.eth <= c_eth_header_ethertype;
 
-    -- Receive forever
-    WHILE TRUE LOOP
-      proc_tech_mac_10g_rx_packet(total_header, g_data_type, rx_phy_clk_156, rx_sosi, rx_siso);
-      rx_toggle <= NOT rx_toggle;
-    END LOOP;
+  u_mm_setup : ENTITY work.tb_tech_mac_10g_setup
+  GENERIC MAP (
+    g_technology    => g_technology,
+    g_src_mac       => c_src_mac
+  )
+  PORT MAP (
+    tb_end    => tb_end,
+    mm_clk    => mm_clk,
+    mm_rst    => mm_rst,
+    mm_init   => mm_init,
+    mm_mosi   => mm_mosi,
+    mm_miso   => mm_miso
+  );
 
-    WAIT;
-  END PROCESS;
-  
+  -- Packet transmitter
+  u_transmitter : ENTITY work.tb_tech_mac_10g_transmitter
+  GENERIC MAP (
+    g_data_type       => g_data_type,
+    g_pkt_length_arr1 => c_pkt_length_arr
+  )
+  PORT MAP (
+    mm_init        => mm_init,
+    total_header   => total_header,
+    clk_156        => tx_ref_clk_156,
+    tx_siso        => tx_siso,
+    tx_sosi        => tx_sosi,
+    link_fault     => OPEN,
+    tx_end         => rx_end
+  );
   
-  p_ff_store_tx_sosi_at_eop : PROCESS(tx_ref_clk_156)
-    VARIABLE vI : NATURAL := 0;
-  BEGIN
-    IF rising_edge(tx_ref_clk_156) THEN
-      IF tx_sosi.eop='1' THEN
-        expected_sosi_arr(vI) <= tx_sosi;
-        vI := vI +1;
-      END IF;
-    END IF;
-  END PROCESS;
-
-  p_ff_verify_rx_sosi_at_eop : PROCESS(rx_phy_clk_156)
-    VARIABLE vI   : NATURAL := 0;
-    VARIABLE vLow : NATURAL := 0;
-  BEGIN
-    IF rising_edge(rx_phy_clk_156) THEN
-      rx_sosi_reg <= rx_sosi;  -- use rx_sosi_reg for verification at eop to account for once cycle latency in expected_sosi_arr()
-      IF rx_sosi_reg.eop='1' THEN
-        IF g_no_dut=FALSE AND c_pkt_length_arr(vI) < 64 - 14 - 20 - 8 - 4 THEN  -- = minimum frame 64 - ETH 14 - IP 20 - UDP 8 - CRC 4
-          -- frame shorter than 64 get padded by MAC so empty after stripping the Rx CRC is fixed 4, which becomes 6 due to pre header padding for UDP word align
-          IF TO_UINT(rx_sosi_reg.empty) /= 6 THEN
-            REPORT "RX: Wrong padded empty" SEVERITY ERROR;
-          END IF;
-        ELSE
-          IF rx_sosi_reg.empty /= expected_sosi_arr(vI).empty THEN
-            REPORT "RX: Wrong empty" SEVERITY ERROR;
-          ELSE
-            vLow := TO_UINT(rx_sosi_reg.empty)*8;
-            ASSERT rx_sosi_reg.data(63 DOWNTO vLow) = expected_sosi_arr(vI).data(63 DOWNTO vLow)  REPORT "RX: Wrong data at eop" SEVERITY ERROR;
-          END IF;
-        END IF;
-        vI := vI +1;
-      END IF;
-    END IF;
-  END PROCESS;
-
   no_dut : IF g_no_dut=TRUE GENERATE
     -- ST loopback
     rx_sosi <= tx_sosi;
@@ -267,7 +187,6 @@ BEGIN
     dut : ENTITY work.tech_mac_10g
     GENERIC MAP (
       g_technology          => g_technology,
-      --g_pre_header_padding  => FALSE
       g_pre_header_padding  => TRUE
     )
     PORT MAP (
@@ -298,28 +217,65 @@ BEGIN
   END GENERATE;
 
   -- Loopback XGMII
-  xgmii_rx_data <= TRANSPORT xgmii_tx_data AFTER phy_delay;
+  u_link_connect : ENTITY work.tb_tech_mac_10g_link_connect
+  GENERIC MAP (
+    g_loopback    => TRUE,
+    g_link_delay  => phy_delay
+  )
+  PORT MAP (
+    -- XGMII layer connect
+    xgmii_tx_data => xgmii_tx_data,
+    xgmii_rx_data => xgmii_rx_data
+  );
 
-  -- Verification
-  tx_pkt_cnt <= tx_pkt_cnt + 1 WHEN tx_sosi.sop='1' AND rising_edge(tx_ref_clk_156);
-  rx_pkt_cnt <= rx_pkt_cnt + 1 WHEN rx_sosi.eop='1' AND rising_edge(rx_phy_clk_156);
+  -- Packet receiver
+  u_receiver : ENTITY work.tb_tech_mac_10_receiver
+  GENERIC MAP (
+    g_data_type       => g_data_type
+  )
+  PORT MAP (
+    mm_init        => mm_init,
+    total_header   => total_header,
+    clk_156        => rx_phy_clk_156,
+    rx_sosi        => rx_sosi,
+    rx_siso        => rx_siso,
+    rx_toggle      => rx_toggle
+  );
   
+  -- Verification
+  u_verify_rx_at_eop : ENTITY work.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_156     => tx_ref_clk_156,
+    tx_sosi        => tx_sosi,
+    rx_clk_156     => rx_phy_clk_156,
+    rx_sosi        => rx_sosi
+  );
+    
+  u_verify_rx_pkt_cnt : ENTITY work.tb_tech_mac_10g_verify_rx_pkt_cnt
+  GENERIC MAP (
+    g_nof_pkt     => c_nof_pkt
+  )
+  PORT MAP (
+    tx_clk_156     => tx_ref_clk_156,
+    tx_sosi        => tx_sosi,
+    rx_clk_156     => rx_phy_clk_156,
+    rx_sosi        => rx_sosi,
+    tx_pkt_cnt     => tx_pkt_cnt,
+    rx_pkt_cnt     => rx_pkt_cnt,
+    rx_end         => rx_end
+  );
+
+  -- Stop the simulation
   p_tb_end : PROCESS  
   BEGIN
     WAIT UNTIL rx_end='1';
-    
-    -- Verify that all transmitted packets have been received
-    IF tx_pkt_cnt=0 THEN
-      REPORT "No packets were transmitted." SEVERITY ERROR;
-    ELSIF rx_pkt_cnt=0 THEN
-      REPORT "No packets were received." SEVERITY ERROR;
-    ELSIF tx_pkt_cnt/=rx_pkt_cnt THEN
-      REPORT "Not all transmitted packets were received." SEVERITY ERROR;
-    END IF;
     proc_common_wait_some_cycles(clk_156, 100);
-    
-    -- Stop the simulation
     tb_end <= '1';
+    ASSERT FALSE REPORT "Simulation finished." SEVERITY NOTE;
     WAIT;
   END PROCESS;
   
diff --git a/libraries/technology/mac_10g/tb_tech_mac_10g_link_connect.vhd b/libraries/technology/mac_10g/tb_tech_mac_10g_link_connect.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a56f0dbd838e41d4fd666cbd746a684b80019296
--- /dev/null
+++ b/libraries/technology/mac_10g/tb_tech_mac_10g_link_connect.vhd
@@ -0,0 +1,83 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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: Reusable test bench link connection for the tech_mac_10g
+-- Description:
+-- . Support XGMII layer connect
+-- . Support serial layer connect with optional link_fault
+-- . Support link delay
+
+LIBRARY IEEE, common_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_interface_layers_pkg.ALL;
+
+
+ENTITY tb_tech_mac_10g_link_connect IS
+  GENERIC (
+    g_loopback    : BOOLEAN := TRUE;  -- default TRUE for loopback tx to rx, else use FALSE to connect tx-tx, rx-rx between two tb devices
+    g_link_delay  : TIME :=  0 ns
+  );
+  PORT (
+    -- XGMII layer connect
+    xgmii_tx_data : IN  STD_LOGIC_VECTOR(c_xgmii_w-1 DOWNTO 0) := (OTHERS=>'X');  -- 72 bit
+    xgmii_rx_data : OUT STD_LOGIC_VECTOR(c_xgmii_w-1 DOWNTO 0);                   -- 72 bit
+    
+    -- Serial layer connect
+    link_fault    : IN  STD_LOGIC := '0';              -- when '1' then forces rx_serial_arr(0)='0'
+    tx_serial_arr : IN  STD_LOGIC_VECTOR(0 DOWNTO 0) := (OTHERS=>'X');
+    rx_serial_arr : OUT STD_LOGIC_VECTOR(0 DOWNTO 0);  -- connects to delayed tx_serial_arr(0) when g_loopback=TRUE else to rx_serial_in
+    
+    -- . external connect
+    tx_serial_out : OUT STD_LOGIC;                     -- connects to delayed tx_serial_arr(0)
+    rx_serial_in  : IN  STD_LOGIC := 'X'               -- used when g_loopback=FALSE
+  );
+END tb_tech_mac_10g_link_connect;
+
+
+ARCHITECTURE tb OF tb_tech_mac_10g_link_connect IS
+  
+  SIGNAL tx_serial_arr_dly   : STD_LOGIC_VECTOR(0 DOWNTO 0);
+
+BEGIN
+  -----------------------------------------------------------------------------
+  -- XGMII layer link
+  -----------------------------------------------------------------------------
+  xgmii_rx_data <= TRANSPORT xgmii_tx_data AFTER g_link_delay;
+
+  -----------------------------------------------------------------------------
+  -- Serial layer link
+  -----------------------------------------------------------------------------
+  tx_serial_arr_dly <= TRANSPORT tx_serial_arr AFTER g_link_delay;
+  tx_serial_out <= tx_serial_arr_dly(0);
+  
+  p_rx_serial : PROCESS(tx_serial_arr_dly, rx_serial_in, link_fault)
+  BEGIN
+    IF g_loopback=TRUE THEN
+      rx_serial_arr    <= tx_serial_arr_dly;
+    ELSE
+      rx_serial_arr(0) <= rx_serial_in;
+    END IF;
+    IF link_fault='1' THEN
+      rx_serial_arr(0) <= '0';
+    END IF;
+  END PROCESS;
+END tb;
diff --git a/libraries/technology/mac_10g/tb_tech_mac_10g_receiver.vhd b/libraries/technology/mac_10g/tb_tech_mac_10g_receiver.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..2d358352c2e3aedba69d1a6093fceabc66ddd262
--- /dev/null
+++ b/libraries/technology/mac_10g/tb_tech_mac_10g_receiver.vhd
@@ -0,0 +1,73 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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: Reusable test bench stimuli for tech_mac_10g receiver
+-- Description:
+
+LIBRARY IEEE, technology_lib, common_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_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 WORK.tb_tech_mac_10g_pkg.ALL;
+
+
+ENTITY tb_tech_mac_10_receiver IS
+  GENERIC (
+    --   g_data_type = c_tb_tech_mac_10g_data_type_symbols  = 0
+    --   g_data_type = c_tb_tech_mac_10g_data_type_counter  = 1
+    g_data_type             : NATURAL := c_tb_tech_mac_10g_data_type_counter
+  );
+  PORT (
+    mm_init        : IN  STD_LOGIC;
+    total_header   : IN  t_network_total_header;
+    clk_156        : IN  STD_LOGIC;
+    rx_sosi        : IN  t_dp_sosi;
+    rx_siso        : OUT t_dp_siso;
+    rx_toggle      : OUT STD_LOGIC  -- toggle after every received packet
+  );
+END tb_tech_mac_10_receiver;
+
+
+ARCHITECTURE tb OF tb_tech_mac_10_receiver IS
+  SIGNAL i_rx_toggle   : STD_LOGIC := '0';
+BEGIN
+  rx_toggle <= i_rx_toggle;
+  
+  p_ff_receiver : PROCESS
+  BEGIN
+    -- . Avalon ST
+    rx_siso <= c_dp_siso_hold;
+
+    WHILE mm_init/='0' LOOP
+      WAIT UNTIL rising_edge(clk_156);
+    END LOOP;
+
+    -- Receive forever
+    WHILE TRUE LOOP
+      proc_tech_mac_10g_rx_packet(total_header, g_data_type, clk_156, rx_sosi, rx_siso);
+      i_rx_toggle <= NOT i_rx_toggle;
+    END LOOP;
+
+    WAIT;
+  END PROCESS;
+END tb;
diff --git a/libraries/technology/mac_10g/tb_tech_mac_10g_setup.vhd b/libraries/technology/mac_10g/tb_tech_mac_10g_setup.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..eb0369b9e41b3e5b801b646ce139ab2fa6a84c76
--- /dev/null
+++ b/libraries/technology/mac_10g/tb_tech_mac_10g_setup.vhd
@@ -0,0 +1,85 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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: Reusable test bench stimuli to setup tech_mac_10g via MM
+-- Description:
+
+LIBRARY IEEE, technology_lib, 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_network_layers_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE technology_lib.technology_select_pkg.ALL;
+USE WORK.tb_tech_mac_10g_pkg.ALL;
+
+
+ENTITY tb_tech_mac_10g_setup IS
+  GENERIC (
+    g_technology    : NATURAL := c_tech_select_default;
+    g_src_mac       : STD_LOGIC_VECTOR(c_network_eth_mac_slv'RANGE) := X"123456789ABC"  -- = 12-34-56-78-9A-BC
+  );
+  PORT (
+    tb_end     : IN  STD_LOGIC := '0';
+    mm_clk     : OUT STD_LOGIC;
+    mm_rst     : OUT STD_LOGIC;
+    mm_init    : OUT STD_LOGIC;
+    mm_mosi    : OUT t_mem_mosi;
+    mm_miso    : IN  t_mem_miso
+  );
+END tb_tech_mac_10g_setup;
+
+
+ARCHITECTURE tb OF tb_tech_mac_10g_setup IS
+
+  CONSTANT mm_clk_period        : TIME := 20 ns;    --  50 MHz
+
+  -- Clocks and reset
+  SIGNAL i_mm_clk          : STD_LOGIC := '0';  -- memory-mapped bus clock
+  SIGNAL i_mm_rst          : STD_LOGIC;         -- reset synchronous with mm_clk
+    
+BEGIN
+
+  mm_clk <= i_mm_clk;
+  mm_rst <= i_mm_rst;
+  
+  i_mm_clk <= NOT i_mm_clk OR tb_end AFTER mm_clk_period/2;   -- MM clock  
+  i_mm_rst <= '1', '0' AFTER mm_clk_period*10;
+
+  p_mm_setup : PROCESS
+  BEGIN
+    mm_init  <= '1';
+    mm_mosi.wr <= '0';
+    mm_mosi.rd <= '0';
+
+    -- wait until after reset release
+    proc_common_wait_until_low(i_mm_clk, i_mm_rst);
+    proc_common_wait_some_cycles(i_mm_clk, 10);
+
+    proc_tech_mac_10g_setup(g_technology,
+                            g_src_mac,
+                            i_mm_clk, mm_miso, mm_mosi);
+    mm_init <= '0';
+    WAIT;
+  END PROCESS;
+
+END tb;
diff --git a/libraries/technology/mac_10g/tb_tech_mac_10g_transmitter.vhd b/libraries/technology/mac_10g/tb_tech_mac_10g_transmitter.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..16510cfde03df0a6b9296ac89ba014846509cbaa
--- /dev/null
+++ b/libraries/technology/mac_10g/tb_tech_mac_10g_transmitter.vhd
@@ -0,0 +1,126 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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: Reusable test bench stimuli for tech_mac_10g transmitter
+-- Description:
+--   The packet transmission starts after mm_init goes low. The
+--   g_pkt_length_arr1 contains the array of packet lengths for the packets
+--   that will be transmitted. The packet data depends on g_data_type and can
+--   be counter data that counts per word or per symbol.
+--   If g_verify_link_recovery=TRUE then link_fault will be active for some
+--   time during which no packets are transmitted. This link_fault can be used
+--   to disable the rx path.
+--   After link_fault is deasserted again the second series of packets defined
+--   by g_pkt_length_arr2 will be transmitted to verify that the link has 
+--   recovered from the link_fault.
+--   Some time after all packets have been transmitted the tx_end will go high.
+--  
+
+LIBRARY IEEE, common_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_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 WORK.tech_mac_10g_component_pkg.ALL;
+USE WORK.tb_tech_mac_10g_pkg.ALL;
+
+
+ENTITY tb_tech_mac_10g_transmitter IS
+  GENERIC (
+    --   g_data_type = c_tb_tech_mac_10g_data_type_symbols  = 0
+    --   g_data_type = c_tb_tech_mac_10g_data_type_counter  = 1
+    g_data_type             : NATURAL := c_tb_tech_mac_10g_data_type_counter;
+    g_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
+    g_pkt_length_arr2       : t_nat_natural_arr := array_init(46, 10, 139) & 1472;
+    g_verify_link_recovery  : BOOLEAN := FALSE
+  );
+  PORT (
+    mm_init        : IN  STD_LOGIC;
+    total_header   : IN  t_network_total_header;
+    clk_156        : IN  STD_LOGIC;
+    tx_siso        : IN  t_dp_siso;
+    tx_sosi        : OUT t_dp_sosi;
+    link_fault     : OUT STD_LOGIC;
+    tx_end         : OUT STD_LOGIC
+  );
+END tb_tech_mac_10g_transmitter;
+
+
+ARCHITECTURE tb OF tb_tech_mac_10g_transmitter IS
+
+  CONSTANT c_rl                 : NATURAL := 1;
+  CONSTANT c_nof_tx_not_valid   : NATURAL := 0;  -- when > 0 then pull tx valid low for c_nof_tx_not_valid beats during tx
+  
+  CONSTANT c_nof_pkt1           : NATURAL := g_pkt_length_arr1'LENGTH;
+  CONSTANT c_nof_pkt2           : NATURAL := g_pkt_length_arr2'LENGTH;
+
+  SIGNAL tx_en                  : STD_LOGIC := '1';
+
+BEGIN
+
+  p_ff_transmitter : PROCESS
+  BEGIN
+    tx_end <= '0';
+    link_fault <= '0';
+    tx_sosi <= c_dp_sosi_rst;
+
+    proc_common_wait_until_low(clk_156, mm_init);
+    proc_common_wait_some_cycles(clk_156, 10);
+
+    -- Loopback txp->rxp so use promiscuous mode or use DST_MAC = c_src_mac to send to itself
+    
+    -- TX frame:g_pkt_length_arr1
+    -- . I=0 is empty payload, so only 4 words of the ETH header with 46 padding zeros, so empty = 2
+    -- . For I=1 to 46 the payload length remains 46 with padding zeros, so empty = 2
+    -- . For I>46 the payload length is I and empty = 4 - (I mod 4)
+    
+    FOR I IN 0 TO c_nof_pkt1-1 LOOP
+      proc_tech_mac_10g_tx_packet(total_header, g_pkt_length_arr1(I), g_data_type, c_rl, c_nof_tx_not_valid, clk_156, tx_en, tx_siso, tx_sosi);
+      proc_common_wait_some_cycles(clk_156, 0);
+    END LOOP;
+
+    proc_common_wait_some_cycles(clk_156, g_pkt_length_arr1(c_nof_pkt1-1)/c_tech_mac_10g_symbols_per_beat);
+    proc_common_wait_some_cycles(clk_156, 100);
+    
+    IF g_verify_link_recovery=TRUE THEN
+      -- Model a link fault to verify Rx recovery
+      link_fault <= '1';
+      proc_common_wait_some_cycles(clk_156, 1000);
+      -- Remove the link fault and wait for tx_siso.xon to recover
+      link_fault <= '0';
+      proc_common_wait_some_cycles(clk_156, 500);
+    
+      FOR I IN 0 TO c_nof_pkt2-1 LOOP
+        proc_tech_mac_10g_tx_packet(total_header, g_pkt_length_arr2(I), g_data_type, c_rl, c_nof_tx_not_valid, clk_156, tx_en, tx_siso, tx_sosi);
+        proc_common_wait_some_cycles(clk_156, 0);
+      END LOOP;
+    
+      proc_common_wait_some_cycles(clk_156, g_pkt_length_arr2(c_nof_pkt2-1)/c_tech_mac_10g_symbols_per_beat);
+      proc_common_wait_some_cycles(clk_156, 100);
+    END IF;
+    
+    tx_end <= '1';
+    WAIT;
+  END PROCESS;
+  
+END tb;
diff --git a/libraries/technology/mac_10g/tb_tech_mac_10g_verify_rx_at_eop.vhd b/libraries/technology/mac_10g/tb_tech_mac_10g_verify_rx_at_eop.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..088c3775de684998e62bb57005336314987f443c
--- /dev/null
+++ b/libraries/technology/mac_10g/tb_tech_mac_10g_verify_rx_at_eop.vhd
@@ -0,0 +1,93 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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: Reusable test bench verification for the tech_mac_10g
+-- Description:
+--   Based on the transmitted data at eop verify the received data at eop.
+
+LIBRARY IEEE, technology_lib, common_lib, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_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 WORK.tb_tech_mac_10g_pkg.ALL;
+
+
+ENTITY tb_tech_mac_10_verify_rx_at_eop IS
+  GENERIC (
+    g_no_padding     : BOOLEAN := FALSE;  -- default FALSE to verify the data from MAC that is padded to minimal length, else use TRUE to verify the data of any length
+    g_pkt_length_arr : t_nat_natural_arr
+  );
+  PORT (
+    tx_clk_156     : IN  STD_LOGIC;
+    tx_sosi        : IN  t_dp_sosi;
+    rx_clk_156     : IN  STD_LOGIC;
+    rx_sosi        : IN  t_dp_sosi
+  );
+END tb_tech_mac_10_verify_rx_at_eop;
+
+ARCHITECTURE tb OF tb_tech_mac_10_verify_rx_at_eop IS
+
+  CONSTANT c_nof_pkt       : NATURAL := g_pkt_length_arr'LENGTH;
+  
+  SIGNAL expected_sosi_arr : t_dp_sosi_arr(0 TO c_nof_pkt-1);
+  SIGNAL rx_sosi_reg       : t_dp_sosi;
+   
+BEGIN
+  
+  p_ff_store_tx_at_eop : PROCESS(tx_clk_156)
+    VARIABLE vI : NATURAL := 0;
+  BEGIN
+    IF rising_edge(tx_clk_156) THEN
+      IF tx_sosi.eop='1' THEN
+        expected_sosi_arr(vI) <= tx_sosi;
+        vI := vI +1;
+      END IF;
+    END IF;
+  END PROCESS;
+
+  p_ff_verify_rx_at_eop : PROCESS(rx_clk_156)
+    VARIABLE vI   : NATURAL := 0;
+    VARIABLE vLow : NATURAL := 0;
+  BEGIN
+    IF rising_edge(rx_clk_156) THEN
+      rx_sosi_reg <= rx_sosi;  -- use rx_sosi_reg for verification at eop to account for once cycle latency in expected_sosi_arr()
+      IF rx_sosi_reg.eop='1' THEN
+        IF g_no_padding=FALSE AND g_pkt_length_arr(vI) < 64 - 14 - 20 - 8 - 4 THEN  -- = minimum frame 64 - ETH 14 - IP 20 - UDP 8 - CRC 4
+          -- frame shorter than 64 get padded by MAC so empty after stripping the Rx CRC is fixed 4, which becomes 6 due to pre header padding for UDP word align
+          IF TO_UINT(rx_sosi_reg.empty) /= 6 THEN
+            REPORT "RX at eop: Wrong padded empty" SEVERITY ERROR;
+          END IF;
+        ELSE
+          IF rx_sosi_reg.empty /= expected_sosi_arr(vI).empty THEN
+            REPORT "RX at eop: Wrong empty" SEVERITY ERROR;
+          ELSE
+            vLow := TO_UINT(rx_sosi_reg.empty)*8;
+            ASSERT rx_sosi_reg.data(63 DOWNTO vLow) = expected_sosi_arr(vI).data(63 DOWNTO vLow)  REPORT "RX at eop: Wrong data" SEVERITY ERROR;
+          END IF;
+        END IF;
+        vI := vI +1;
+      END IF;
+    END IF;
+  END PROCESS;
+
+END tb;
diff --git a/libraries/technology/mac_10g/tb_tech_mac_10g_verify_rx_pkt_cnt.vhd b/libraries/technology/mac_10g/tb_tech_mac_10g_verify_rx_pkt_cnt.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..7bdfe3715468a7a69c3fa2d89233e40c35008f46
--- /dev/null
+++ b/libraries/technology/mac_10g/tb_tech_mac_10g_verify_rx_pkt_cnt.vhd
@@ -0,0 +1,80 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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: Reusable test bench verification for the tech_mac_10g
+-- Description:
+-- . Verify that > 0 packets were transmitted and that all were received
+
+
+LIBRARY IEEE, dp_lib;
+USE IEEE.std_logic_1164.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+
+
+ENTITY tb_tech_mac_10g_verify_rx_pkt_cnt IS
+  GENERIC (
+    g_nof_pkt     : NATURAL
+  );
+  PORT (
+    tx_clk_156     : IN  STD_LOGIC;
+    tx_sosi        : IN  t_dp_sosi;
+    rx_clk_156     : IN  STD_LOGIC;
+    rx_sosi        : IN  t_dp_sosi;
+    tx_pkt_cnt     : OUT NATURAL;
+    rx_pkt_cnt     : OUT NATURAL;
+    rx_end         : IN  STD_LOGIC
+  );
+END tb_tech_mac_10g_verify_rx_pkt_cnt;
+
+
+ARCHITECTURE tb OF tb_tech_mac_10g_verify_rx_pkt_cnt IS
+
+  SIGNAL i_tx_pkt_cnt     : NATURAL := 0;
+  SIGNAL i_rx_pkt_cnt     : NATURAL := 0;
+  
+BEGIN
+
+  tx_pkt_cnt <= i_tx_pkt_cnt;
+  rx_pkt_cnt <= i_rx_pkt_cnt;  
+
+  -- Verification
+  i_tx_pkt_cnt <= i_tx_pkt_cnt + 1 WHEN tx_sosi.sop='1' AND rising_edge(tx_clk_156);
+  i_rx_pkt_cnt <= i_rx_pkt_cnt + 1 WHEN rx_sosi.eop='1' AND rising_edge(rx_clk_156);
+  
+  p_verify_pkt_cnt : PROCESS  
+  BEGIN
+    WAIT UNTIL rx_end='1';
+    
+    -- Verify that all transmitted packets have been received
+    IF i_tx_pkt_cnt=0 THEN
+      REPORT "No packets were transmitted." SEVERITY ERROR;
+    ELSIF i_tx_pkt_cnt/=g_nof_pkt THEN
+      REPORT "Not all packets were transmitted." SEVERITY ERROR;
+    ELSIF i_rx_pkt_cnt=0 THEN
+      REPORT "No packets were received." SEVERITY ERROR;
+    ELSIF i_tx_pkt_cnt/=i_rx_pkt_cnt THEN
+      REPORT "Not all transmitted packets were received." SEVERITY ERROR;
+    END IF;
+    
+    WAIT;
+  END PROCESS;
+  
+END tb;