diff --git a/modules/wrsw_txtsu/Manifest.py b/modules/wrsw_txtsu/Manifest.py
new file mode 100644
index 0000000000000000000000000000000000000000..4fd0e54eb661c418142977533abcc49beab0773a
--- /dev/null
+++ b/modules/wrsw_txtsu/Manifest.py
@@ -0,0 +1,3 @@
+files = ["xwrsw_txtsu.vhd",
+				  "wrsw_txtsu_wb.vhd",
+				  "wrsw_txtsu_pkg.vhd"]
diff --git a/modules/wrsw_txtsu/wrsw_txtsu.wb b/modules/wrsw_txtsu/wrsw_txtsu.wb
new file mode 100644
index 0000000000000000000000000000000000000000..a9587a84e9993973fe7c88dd4f859387380da4c6
--- /dev/null
+++ b/modules/wrsw_txtsu/wrsw_txtsu.wb
@@ -0,0 +1,72 @@
+-- -*- Mode: LUA; tab-width: 2 -*-
+
+peripheral {
+	 name = "Shared TX Timestamping Unit (TXTSU)";
+   prefix="txtsu";
+
+	 hdl_entity="wrsw_txtsu_wb";
+	 
+-- TXTSU shared FIFO
+
+	 fifo_reg {
+			size = 256; -- or more. We'll see :)
+			direction = CORE_TO_BUS;
+			prefix = "tsf";
+			name = "Timestamp FIFO";
+			description = "This FIFO holds the TX packet timestamps gathered from all switch endpoints. Each entry contains a single timestamp value consisting of 2 numbers:\
+			               - VAL_R - the timestamp taken at rising clock edge. This is the main timestamp value\
+            				 - VAL_F - few LSBs of timestamp taken at falling clock edge. It's used in conjunction with VAL_R to determine if the timestamp has been taken\
+                           		 properly (there was no metastability/setup/hold violation)\
+										 Entries also contain information required to identify the endpoint and frame for which the timestamp was taken:\
+                     - FID - Frame identifier assigned by the NIC\
+                     - PID - TXTSU port ID to which came the timestamp. Used to distinguish the timestamps for broadcast/multicast frames";
+
+			flags_bus = {FIFO_FULL, FIFO_EMPTY, FIFO_COUNT};
+			flags_dev = {FIFO_FULL, FIFO_EMPTY};
+			
+			field {
+				 name = "Rising edge timestamp";
+				 descritpion = "Timestamp value taken on rising clock edge (full word)";
+				 prefix = "val_r";
+				 type = SLV;
+				 size = 28;
+			};
+
+			field {
+				 name = "Falling edge timestamp";
+				 description = "Timestamp value taken on falling clock edge (few LSBs)";
+				 prefix = "val_f";
+				 type = SLV;
+				 size = 4;
+			};
+
+
+			field {
+				 name ="Physical port ID";
+				 description = "Identifier of the TXTSU port to which came the timestamp. There may be multiple timestamps sharing the same FID value for broadcast/multicast packets.";
+				 prefix = "pid";
+				 type = SLV;
+				 size = 5;
+				 align= 16;
+			};
+		
+		
+			field {
+				 name = "Frame ID";
+				 description = "OOB Frame Identifier. Used to associate the timestamp value with transmitted packet.";
+				 prefix = "fid";
+				 type = SLV;
+				 size = 16;
+				 align = 16;
+		};
+	};
+
+-- TXTSU interrupts
+	irq {
+		 name = "TXTSU fifo not-empty";
+		 description = "Interrupt active when TXTSU shared FIFO contains any timestamps.";
+		 prefix = "nempty";
+		 trigger = LEVEL_1;
+	};
+
+};
\ No newline at end of file
diff --git a/modules/wrsw_txtsu/wrsw_txtsu_pkg.vhd b/modules/wrsw_txtsu/wrsw_txtsu_pkg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..985dc63fdfd4bf2a808adc007a09589b891cc52e
--- /dev/null
+++ b/modules/wrsw_txtsu/wrsw_txtsu_pkg.vhd
@@ -0,0 +1,15 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+package wrsw_txtsu_pkg is
+
+  type t_txtsu_timestamp is record
+    valid: std_logic;
+    tsval : std_logic_vector(31 downto 0);
+    port_id: std_logic_vector(5 downto 0);
+    frame_id: std_logic_vector(15 downto 0);
+  end record;
+
+  type t_txtsu_timestamp_array is array(integer range <>) of t_txtsu_timestamp;
+
+end wrsw_txtsu_pkg;
diff --git a/modules/wrsw_txtsu/wrsw_txtsu_wb.vhd b/modules/wrsw_txtsu/wrsw_txtsu_wb.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..97fae79120f0ee22f38682e97df75db5db6743c0
--- /dev/null
+++ b/modules/wrsw_txtsu/wrsw_txtsu_wb.vhd
@@ -0,0 +1,441 @@
+---------------------------------------------------------------------------------------
+-- Title          : Wishbone slave core for Shared TX Timestamping Unit (TXTSU)
+---------------------------------------------------------------------------------------
+-- File           : wrsw_txtsu_wb.vhd
+-- Author         : auto-generated by wbgen2 from wrsw_txtsu.wb
+-- Created        : Wed Mar 16 15:27:30 2011
+-- Standard       : VHDL'87
+---------------------------------------------------------------------------------------
+-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wrsw_txtsu.wb
+-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
+---------------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.wbgen2_pkg.all;
+
+entity wrsw_txtsu_wb is
+  port (
+    rst_n_i                                  : in     std_logic;
+    wb_clk_i                                 : in     std_logic;
+    wb_addr_i                                : in     std_logic_vector(2 downto 0);
+    wb_data_i                                : in     std_logic_vector(31 downto 0);
+    wb_data_o                                : out    std_logic_vector(31 downto 0);
+    wb_cyc_i                                 : in     std_logic;
+    wb_sel_i                                 : in     std_logic_vector(3 downto 0);
+    wb_stb_i                                 : in     std_logic;
+    wb_we_i                                  : in     std_logic;
+    wb_ack_o                                 : out    std_logic;
+    wb_irq_o                                 : out    std_logic;
+-- FIFO write request
+    txtsu_tsf_wr_req_i                       : in     std_logic;
+-- FIFO full flag
+    txtsu_tsf_wr_full_o                      : out    std_logic;
+-- FIFO empty flag
+    txtsu_tsf_wr_empty_o                     : out    std_logic;
+    txtsu_tsf_val_r_i                        : in     std_logic_vector(27 downto 0);
+    txtsu_tsf_val_f_i                        : in     std_logic_vector(3 downto 0);
+    txtsu_tsf_pid_i                          : in     std_logic_vector(4 downto 0);
+    txtsu_tsf_fid_i                          : in     std_logic_vector(15 downto 0);
+    irq_nempty_i                             : in     std_logic
+  );
+end wrsw_txtsu_wb;
+
+architecture syn of wrsw_txtsu_wb is
+
+signal txtsu_tsf_in_int                         : std_logic_vector(52 downto 0);
+signal txtsu_tsf_out_int                        : std_logic_vector(52 downto 0);
+signal txtsu_tsf_rdreq_int                      : std_logic      ;
+signal txtsu_tsf_rdreq_int_d0                   : std_logic      ;
+signal eic_idr_int                              : std_logic_vector(0 downto 0);
+signal eic_idr_write_int                        : std_logic      ;
+signal eic_ier_int                              : std_logic_vector(0 downto 0);
+signal eic_ier_write_int                        : std_logic      ;
+signal eic_imr_int                              : std_logic_vector(0 downto 0);
+signal eic_isr_clear_int                        : std_logic_vector(0 downto 0);
+signal eic_isr_status_int                       : std_logic_vector(0 downto 0);
+signal eic_irq_ack_int                          : std_logic_vector(0 downto 0);
+signal eic_isr_write_int                        : std_logic      ;
+signal txtsu_tsf_full_int                       : std_logic      ;
+signal txtsu_tsf_empty_int                      : std_logic      ;
+signal txtsu_tsf_usedw_int                      : std_logic_vector(7 downto 0);
+signal irq_inputs_vector_int                    : std_logic_vector(0 downto 0);
+signal ack_sreg                                 : std_logic_vector(9 downto 0);
+signal rddata_reg                               : std_logic_vector(31 downto 0);
+signal wrdata_reg                               : std_logic_vector(31 downto 0);
+signal bwsel_reg                                : std_logic_vector(3 downto 0);
+signal rwaddr_reg                               : std_logic_vector(2 downto 0);
+signal ack_in_progress                          : std_logic      ;
+signal wr_int                                   : std_logic      ;
+signal rd_int                                   : std_logic      ;
+signal bus_clock_int                            : std_logic      ;
+signal allones                                  : std_logic_vector(31 downto 0);
+signal allzeros                                 : std_logic_vector(31 downto 0);
+
+begin
+-- Some internal signals assignments. For (foreseen) compatibility with other bus standards.
+  wrdata_reg <= wb_data_i;
+  bwsel_reg <= wb_sel_i;
+  bus_clock_int <= wb_clk_i;
+  rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i));
+  wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i);
+  allones <= (others => '1');
+  allzeros <= (others => '0');
+-- 
+-- Main register bank access process.
+  process (bus_clock_int, rst_n_i)
+  begin
+    if (rst_n_i = '0') then 
+      ack_sreg <= "0000000000";
+      ack_in_progress <= '0';
+      rddata_reg <= "00000000000000000000000000000000";
+      eic_idr_write_int <= '0';
+      eic_ier_write_int <= '0';
+      eic_isr_write_int <= '0';
+      txtsu_tsf_rdreq_int <= '0';
+    elsif rising_edge(bus_clock_int) then
+-- advance the ACK generator shift register
+      ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
+      ack_sreg(9) <= '0';
+      if (ack_in_progress = '1') then
+        if (ack_sreg(0) = '1') then
+          eic_idr_write_int <= '0';
+          eic_ier_write_int <= '0';
+          eic_isr_write_int <= '0';
+          ack_in_progress <= '0';
+        else
+        end if;
+      else
+        if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then
+          case rwaddr_reg(2 downto 0) is
+          when "000" => 
+            if (wb_we_i = '1') then
+              eic_idr_write_int <= '1';
+            else
+              rddata_reg(0) <= 'X';
+              rddata_reg(1) <= 'X';
+              rddata_reg(2) <= 'X';
+              rddata_reg(3) <= 'X';
+              rddata_reg(4) <= 'X';
+              rddata_reg(5) <= 'X';
+              rddata_reg(6) <= 'X';
+              rddata_reg(7) <= 'X';
+              rddata_reg(8) <= 'X';
+              rddata_reg(9) <= 'X';
+              rddata_reg(10) <= 'X';
+              rddata_reg(11) <= 'X';
+              rddata_reg(12) <= 'X';
+              rddata_reg(13) <= 'X';
+              rddata_reg(14) <= 'X';
+              rddata_reg(15) <= 'X';
+              rddata_reg(16) <= 'X';
+              rddata_reg(17) <= 'X';
+              rddata_reg(18) <= 'X';
+              rddata_reg(19) <= 'X';
+              rddata_reg(20) <= 'X';
+              rddata_reg(21) <= 'X';
+              rddata_reg(22) <= 'X';
+              rddata_reg(23) <= 'X';
+              rddata_reg(24) <= 'X';
+              rddata_reg(25) <= 'X';
+              rddata_reg(26) <= 'X';
+              rddata_reg(27) <= 'X';
+              rddata_reg(28) <= 'X';
+              rddata_reg(29) <= 'X';
+              rddata_reg(30) <= 'X';
+              rddata_reg(31) <= 'X';
+            end if;
+            ack_sreg(0) <= '1';
+            ack_in_progress <= '1';
+          when "001" => 
+            if (wb_we_i = '1') then
+              eic_ier_write_int <= '1';
+            else
+              rddata_reg(0) <= 'X';
+              rddata_reg(1) <= 'X';
+              rddata_reg(2) <= 'X';
+              rddata_reg(3) <= 'X';
+              rddata_reg(4) <= 'X';
+              rddata_reg(5) <= 'X';
+              rddata_reg(6) <= 'X';
+              rddata_reg(7) <= 'X';
+              rddata_reg(8) <= 'X';
+              rddata_reg(9) <= 'X';
+              rddata_reg(10) <= 'X';
+              rddata_reg(11) <= 'X';
+              rddata_reg(12) <= 'X';
+              rddata_reg(13) <= 'X';
+              rddata_reg(14) <= 'X';
+              rddata_reg(15) <= 'X';
+              rddata_reg(16) <= 'X';
+              rddata_reg(17) <= 'X';
+              rddata_reg(18) <= 'X';
+              rddata_reg(19) <= 'X';
+              rddata_reg(20) <= 'X';
+              rddata_reg(21) <= 'X';
+              rddata_reg(22) <= 'X';
+              rddata_reg(23) <= 'X';
+              rddata_reg(24) <= 'X';
+              rddata_reg(25) <= 'X';
+              rddata_reg(26) <= 'X';
+              rddata_reg(27) <= 'X';
+              rddata_reg(28) <= 'X';
+              rddata_reg(29) <= 'X';
+              rddata_reg(30) <= 'X';
+              rddata_reg(31) <= 'X';
+            end if;
+            ack_sreg(0) <= '1';
+            ack_in_progress <= '1';
+          when "010" => 
+            if (wb_we_i = '1') then
+            else
+              rddata_reg(0) <= eic_imr_int(0);
+              rddata_reg(1) <= 'X';
+              rddata_reg(2) <= 'X';
+              rddata_reg(3) <= 'X';
+              rddata_reg(4) <= 'X';
+              rddata_reg(5) <= 'X';
+              rddata_reg(6) <= 'X';
+              rddata_reg(7) <= 'X';
+              rddata_reg(8) <= 'X';
+              rddata_reg(9) <= 'X';
+              rddata_reg(10) <= 'X';
+              rddata_reg(11) <= 'X';
+              rddata_reg(12) <= 'X';
+              rddata_reg(13) <= 'X';
+              rddata_reg(14) <= 'X';
+              rddata_reg(15) <= 'X';
+              rddata_reg(16) <= 'X';
+              rddata_reg(17) <= 'X';
+              rddata_reg(18) <= 'X';
+              rddata_reg(19) <= 'X';
+              rddata_reg(20) <= 'X';
+              rddata_reg(21) <= 'X';
+              rddata_reg(22) <= 'X';
+              rddata_reg(23) <= 'X';
+              rddata_reg(24) <= 'X';
+              rddata_reg(25) <= 'X';
+              rddata_reg(26) <= 'X';
+              rddata_reg(27) <= 'X';
+              rddata_reg(28) <= 'X';
+              rddata_reg(29) <= 'X';
+              rddata_reg(30) <= 'X';
+              rddata_reg(31) <= 'X';
+            end if;
+            ack_sreg(0) <= '1';
+            ack_in_progress <= '1';
+          when "011" => 
+            if (wb_we_i = '1') then
+              eic_isr_write_int <= '1';
+            else
+              rddata_reg(0) <= eic_isr_status_int(0);
+              rddata_reg(1) <= 'X';
+              rddata_reg(2) <= 'X';
+              rddata_reg(3) <= 'X';
+              rddata_reg(4) <= 'X';
+              rddata_reg(5) <= 'X';
+              rddata_reg(6) <= 'X';
+              rddata_reg(7) <= 'X';
+              rddata_reg(8) <= 'X';
+              rddata_reg(9) <= 'X';
+              rddata_reg(10) <= 'X';
+              rddata_reg(11) <= 'X';
+              rddata_reg(12) <= 'X';
+              rddata_reg(13) <= 'X';
+              rddata_reg(14) <= 'X';
+              rddata_reg(15) <= 'X';
+              rddata_reg(16) <= 'X';
+              rddata_reg(17) <= 'X';
+              rddata_reg(18) <= 'X';
+              rddata_reg(19) <= 'X';
+              rddata_reg(20) <= 'X';
+              rddata_reg(21) <= 'X';
+              rddata_reg(22) <= 'X';
+              rddata_reg(23) <= 'X';
+              rddata_reg(24) <= 'X';
+              rddata_reg(25) <= 'X';
+              rddata_reg(26) <= 'X';
+              rddata_reg(27) <= 'X';
+              rddata_reg(28) <= 'X';
+              rddata_reg(29) <= 'X';
+              rddata_reg(30) <= 'X';
+              rddata_reg(31) <= 'X';
+            end if;
+            ack_sreg(0) <= '1';
+            ack_in_progress <= '1';
+          when "100" => 
+            if (wb_we_i = '1') then
+            else
+              if (txtsu_tsf_rdreq_int_d0 = '0') then
+                txtsu_tsf_rdreq_int <= not txtsu_tsf_rdreq_int;
+              else
+                rddata_reg(27 downto 0) <= txtsu_tsf_out_int(27 downto 0);
+                rddata_reg(31 downto 28) <= txtsu_tsf_out_int(31 downto 28);
+                ack_in_progress <= '1';
+                ack_sreg(0) <= '1';
+              end if;
+            end if;
+          when "101" => 
+            if (wb_we_i = '1') then
+            else
+              rddata_reg(4 downto 0) <= txtsu_tsf_out_int(36 downto 32);
+              rddata_reg(31 downto 16) <= txtsu_tsf_out_int(52 downto 37);
+              rddata_reg(5) <= 'X';
+              rddata_reg(6) <= 'X';
+              rddata_reg(7) <= 'X';
+              rddata_reg(8) <= 'X';
+              rddata_reg(9) <= 'X';
+              rddata_reg(10) <= 'X';
+              rddata_reg(11) <= 'X';
+              rddata_reg(12) <= 'X';
+              rddata_reg(13) <= 'X';
+              rddata_reg(14) <= 'X';
+              rddata_reg(15) <= 'X';
+            end if;
+            ack_sreg(0) <= '1';
+            ack_in_progress <= '1';
+          when "110" => 
+            if (wb_we_i = '1') then
+            else
+              rddata_reg(16) <= txtsu_tsf_full_int;
+              rddata_reg(17) <= txtsu_tsf_empty_int;
+              rddata_reg(7 downto 0) <= txtsu_tsf_usedw_int;
+              rddata_reg(8) <= 'X';
+              rddata_reg(9) <= 'X';
+              rddata_reg(10) <= 'X';
+              rddata_reg(11) <= 'X';
+              rddata_reg(12) <= 'X';
+              rddata_reg(13) <= 'X';
+              rddata_reg(14) <= 'X';
+              rddata_reg(15) <= 'X';
+              rddata_reg(18) <= 'X';
+              rddata_reg(19) <= 'X';
+              rddata_reg(20) <= 'X';
+              rddata_reg(21) <= 'X';
+              rddata_reg(22) <= 'X';
+              rddata_reg(23) <= 'X';
+              rddata_reg(24) <= 'X';
+              rddata_reg(25) <= 'X';
+              rddata_reg(26) <= 'X';
+              rddata_reg(27) <= 'X';
+              rddata_reg(28) <= 'X';
+              rddata_reg(29) <= 'X';
+              rddata_reg(30) <= 'X';
+              rddata_reg(31) <= 'X';
+            end if;
+            ack_sreg(0) <= '1';
+            ack_in_progress <= '1';
+          when others =>
+-- prevent the slave from hanging the bus on invalid address
+            ack_in_progress <= '1';
+            ack_sreg(0) <= '1';
+          end case;
+        end if;
+      end if;
+    end if;
+  end process;
+  
+  
+-- Drive the data output bus
+  wb_data_o <= rddata_reg;
+-- extra code for reg/fifo/mem: Timestamp FIFO
+  txtsu_tsf_in_int(27 downto 0) <= txtsu_tsf_val_r_i;
+  txtsu_tsf_in_int(31 downto 28) <= txtsu_tsf_val_f_i;
+  txtsu_tsf_in_int(36 downto 32) <= txtsu_tsf_pid_i;
+  txtsu_tsf_in_int(52 downto 37) <= txtsu_tsf_fid_i;
+  txtsu_tsf_INST : wbgen2_fifo_sync
+    generic map (
+      g_size               => 256,
+      g_width              => 53,
+      g_usedw_size         => 8
+    )
+    port map (
+      wr_req_i             => txtsu_tsf_wr_req_i,
+      wr_full_o            => txtsu_tsf_wr_full_o,
+      wr_empty_o           => txtsu_tsf_wr_empty_o,
+      rd_full_o            => txtsu_tsf_full_int,
+      rd_empty_o           => txtsu_tsf_empty_int,
+      rd_usedw_o           => txtsu_tsf_usedw_int,
+      rd_req_i             => txtsu_tsf_rdreq_int,
+      clk_i                => bus_clock_int,
+      wr_data_i            => txtsu_tsf_in_int,
+      rd_data_o            => txtsu_tsf_out_int
+    );
+  
+-- extra code for reg/fifo/mem: Interrupt disable register
+  eic_idr_int(0) <= wrdata_reg(0);
+-- extra code for reg/fifo/mem: Interrupt enable register
+  eic_ier_int(0) <= wrdata_reg(0);
+-- extra code for reg/fifo/mem: Interrupt status register
+  eic_isr_clear_int(0) <= wrdata_reg(0);
+-- extra code for reg/fifo/mem: IRQ_CONTROLLER
+  eic_irq_controller_inst : wbgen2_eic
+    generic map (
+      g_num_interrupts     => 1,
+      g_irq00_mode         => 3,
+      g_irq01_mode         => 0,
+      g_irq02_mode         => 0,
+      g_irq03_mode         => 0,
+      g_irq04_mode         => 0,
+      g_irq05_mode         => 0,
+      g_irq06_mode         => 0,
+      g_irq07_mode         => 0,
+      g_irq08_mode         => 0,
+      g_irq09_mode         => 0,
+      g_irq0a_mode         => 0,
+      g_irq0b_mode         => 0,
+      g_irq0c_mode         => 0,
+      g_irq0d_mode         => 0,
+      g_irq0e_mode         => 0,
+      g_irq0f_mode         => 0,
+      g_irq10_mode         => 0,
+      g_irq11_mode         => 0,
+      g_irq12_mode         => 0,
+      g_irq13_mode         => 0,
+      g_irq14_mode         => 0,
+      g_irq15_mode         => 0,
+      g_irq16_mode         => 0,
+      g_irq17_mode         => 0,
+      g_irq18_mode         => 0,
+      g_irq19_mode         => 0,
+      g_irq1a_mode         => 0,
+      g_irq1b_mode         => 0,
+      g_irq1c_mode         => 0,
+      g_irq1d_mode         => 0,
+      g_irq1e_mode         => 0,
+      g_irq1f_mode         => 0
+    )
+    port map (
+      clk_i                => bus_clock_int,
+      rst_n_i              => rst_n_i,
+      irq_i                => irq_inputs_vector_int,
+      irq_ack_o            => eic_irq_ack_int,
+      reg_imr_o            => eic_imr_int,
+      reg_ier_i            => eic_ier_int,
+      reg_ier_wr_stb_i     => eic_ier_write_int,
+      reg_idr_i            => eic_idr_int,
+      reg_idr_wr_stb_i     => eic_idr_write_int,
+      reg_isr_o            => eic_isr_status_int,
+      reg_isr_i            => eic_isr_clear_int,
+      reg_isr_wr_stb_i     => eic_isr_write_int,
+      wb_irq_o             => wb_irq_o
+    );
+  
+  irq_inputs_vector_int(0) <= irq_nempty_i;
+-- extra code for reg/fifo/mem: FIFO 'Timestamp FIFO' data output register 0
+  process (bus_clock_int, rst_n_i)
+  begin
+    if (rst_n_i = '0') then 
+      txtsu_tsf_rdreq_int_d0 <= '0';
+    elsif rising_edge(bus_clock_int) then
+      txtsu_tsf_rdreq_int_d0 <= txtsu_tsf_rdreq_int;
+    end if;
+  end process;
+  
+  
+-- extra code for reg/fifo/mem: FIFO 'Timestamp FIFO' data output register 1
+  rwaddr_reg <= wb_addr_i;
+-- ACK signal generation. Just pass the LSB of ACK counter.
+  wb_ack_o <= ack_sreg(0);
+end syn;
diff --git a/modules/wrsw_txtsu/xwrsw_txtsu.vhd b/modules/wrsw_txtsu/xwrsw_txtsu.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..1b6a0a7920d8aa8746336feae643523d80f7ffcf
--- /dev/null
+++ b/modules/wrsw_txtsu/xwrsw_txtsu.vhd
@@ -0,0 +1,223 @@
+-------------------------------------------------------------------------------
+-- Title      : TX Timestamping Unit
+-- Project    : White Rabbit Switch
+-------------------------------------------------------------------------------
+-- File       : xwrsw_txtsu.vhd
+-- Author     : Tomasz Wlostowski
+-- Company    : CERN BE-Co-HT
+-- Created    : 2010-04-26
+-- Last update: 2012-01-18
+-- Platform   : FPGA-generic
+-- Standard   : VHDL
+-------------------------------------------------------------------------------
+-- Description: Shared timestamping unit for all switch endpoints. It collects
+-- TX timestamps with associated frame identifiers and puts them (along
+-- with the identifier of requesting port) in a shared FIFO. Each FIFO entry
+-- contains:
+-- - Frame ID value (from OOB field of transmitted frame)
+-- - Timestamp value (from the endpoint)
+-- - Port ID value (ID of the TXTSU port to which the timstamp+frame id came).
+-- FIFO is accessible from the Wishbone bus. An IRQ (level-active) is triggered
+-- when the FIFO is not empty. The driver reads TX timestamps (with associated
+-- port and frame identifiers) and passes them to PTP daemon.
+
+-------------------------------------------------------------------------------
+-- Copyright (c) 2010 Tomasz Wlostowski
+-------------------------------------------------------------------------------
+-- Revisions  :
+-- Date        Version  Author          Description
+-- 2010-04-26  1.0      twlostow        Created
+-------------------------------------------------------------------------------
+
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+
+use work.wishbone_pkg.all;
+use work.wrsw_txtsu_pkg.all;
+
+entity xwrsw_tx_tsu is
+  
+  generic (
+    g_num_ports           : integer                        := 10;
+    g_interface_mode      : t_wishbone_interface_mode      := CLASSIC;
+    g_address_granularity : t_wishbone_address_granularity := WORD);
+
+  port (
+-- reference clock / 2 (62.5 MHz). All signals below are synchronous to this clock
+    clk_sys_i : in std_logic;
+
+-- sync reset, active LO
+    rst_n_i : in std_logic;
+
+-------------------------------------------------------------------------------
+-- TX timestamp interface (from endpoints)
+-------------------------------------------------------------------------------
+
+-- frame identifier inputs (separate for each port)
+    timestamps_i     : in  t_txtsu_timestamp_array(g_num_ports-1 downto 0);
+    timestamps_ack_o : out std_logic_vector(g_num_ports -1 downto 0);
+
+-------------------------------------------------------------------------------
+-- Wishbone bus
+-------------------------------------------------------------------------------
+
+    wb_i: in t_wishbone_slave_in;
+    wb_o: out t_wishbone_slave_out
+    );
+
+
+
+end xwrsw_tx_tsu;
+
+
+architecture syn of xwrsw_tx_tsu is
+
+  component wrsw_txtsu_wb
+    port (
+      rst_n_i              : in  std_logic;
+      wb_clk_i             : in  std_logic;
+      wb_addr_i            : in  std_logic_vector(2 downto 0);
+      wb_data_i            : in  std_logic_vector(31 downto 0);
+      wb_data_o            : out std_logic_vector(31 downto 0);
+      wb_cyc_i             : in  std_logic;
+      wb_sel_i             : in  std_logic_vector(3 downto 0);
+      wb_stb_i             : in  std_logic;
+      wb_we_i              : in  std_logic;
+      wb_ack_o             : out std_logic;
+      wb_irq_o             : out std_logic;
+      txtsu_tsf_wr_req_i   : in  std_logic;
+      txtsu_tsf_wr_full_o  : out std_logic;
+      txtsu_tsf_wr_empty_o : out std_logic;
+      txtsu_tsf_val_r_i    : in  std_logic_vector(27 downto 0);
+      txtsu_tsf_val_f_i    : in  std_logic_vector(3 downto 0);
+      txtsu_tsf_pid_i      : in  std_logic_vector(4 downto 0);
+      txtsu_tsf_fid_i      : in  std_logic_vector(15 downto 0);
+      irq_nempty_i         : in  std_logic);
+  end component;
+
+
+  signal txtsu_tsf_wr_req   : std_logic;
+  signal txtsu_tsf_wr_full  : std_logic;
+  signal txtsu_tsf_wr_empty : std_logic;
+  signal txtsu_tsf_val_r    : std_logic_vector(27 downto 0);
+  signal txtsu_tsf_val_f    : std_logic_vector(3 downto 0);
+  signal txtsu_tsf_pid      : std_logic_vector(4 downto 0);
+  signal txtsu_tsf_fid      : std_logic_vector(15 downto 0);
+
+  signal irq_nempty : std_logic;
+
+
+  signal scan_cntr : unsigned(4 downto 0);
+
+  type t_txtsu_state is (TSU_SCAN, TSU_ACK);
+
+  signal state : t_txtsu_state;
+
+  signal ep_valid : std_logic_vector(g_num_ports-1 downto 0);
+  signal ep_ack   : std_logic_vector(g_num_ports-1 downto 0);
+
+  signal cur_ep : integer;
+
+  signal wb_out       : t_wishbone_slave_out;
+  signal wb_in        : t_wishbone_slave_in;
+  
+begin  -- syn
+
+  U_Adapter : wb_slave_adapter
+    generic map (
+      g_master_use_struct  => true,
+      g_master_mode        => CLASSIC,
+      g_master_granularity => WORD,
+      g_slave_use_struct   => true,
+      g_slave_mode         => g_interface_mode,
+      g_slave_granularity  => g_address_granularity)
+    port map (
+      clk_sys_i  => clk_sys_i,
+      rst_n_i    => rst_n_i,
+      master_i   => wb_out,
+      master_o   => wb_in,
+      slave_i => wb_i,
+      slave_o => wb_o);
+
+  
+  cur_ep <= to_integer(scan_cntr);
+
+  process(clk_sys_i, rst_n_i)
+  begin
+    if rising_edge(clk_sys_i) then
+      if rst_n_i = '0' then
+        
+        state            <= TSU_SCAN;
+        scan_cntr        <= (others => '0');
+        txtsu_tsf_wr_req <= '0';
+
+        timestamps_ack_o <= (others => '0');
+        
+      else
+        case state is
+          when TSU_SCAN =>
+
+            if(ep_valid(cur_ep) = '1') then
+              ep_ack(cur_ep) <= '1';
+              state          <= TSU_ACK;
+
+              if(txtsu_tsf_wr_full = '0') then
+                txtsu_tsf_pid    <= timestamps_i(cur_ep).port_id(4 downto 0);
+                txtsu_tsf_fid    <= timestamps_i(cur_ep).frame_id;
+                txtsu_tsf_val_f  <= timestamps_i(cur_ep).tsval(31 downto 28);
+                txtsu_tsf_val_r  <= timestamps_i(cur_ep).tsval(27 downto 0);
+                txtsu_tsf_wr_req <= '1';
+              end if;
+            else
+              if(scan_cntr = g_num_ports-1)then
+                scan_cntr <= (others => '0');
+              else
+                scan_cntr <= scan_cntr + 1;
+              end if;
+            end if;
+          when TSU_ACK =>
+            timestamps_ack_o(cur_ep)   <= '0';
+            txtsu_tsf_wr_req <= '0';
+            state            <= TSU_SCAN;
+            if(scan_cntr = g_num_ports-1)then
+              scan_cntr <= (others => '0');
+            else
+              scan_cntr <= scan_cntr + 1;
+            end if;
+          when others => null;
+        end case;
+      end if;
+    end if;
+  end process;
+
+
+  U_WB_SLAVE : wrsw_txtsu_wb
+    port map (
+      rst_n_i              => rst_n_i,
+      wb_clk_i             => clk_sys_i,
+      wb_addr_i            => wb_in.adr(2 downto 0),
+      wb_data_i            => wb_in.dat,
+      wb_data_o            => wb_out.dat,
+      wb_cyc_i             => wb_in.cyc,
+      wb_sel_i             => wb_in.sel,
+      wb_stb_i             => wb_in.stb,
+      wb_we_i              => wb_in.we,
+      wb_ack_o             => wb_out.ack,
+      wb_irq_o             => wb_out.int,
+      txtsu_tsf_wr_req_i   => txtsu_tsf_wr_req,
+      txtsu_tsf_wr_full_o  => txtsu_tsf_wr_full,
+      txtsu_tsf_wr_empty_o => txtsu_tsf_wr_empty,
+      txtsu_tsf_val_r_i    => txtsu_tsf_val_r,
+      txtsu_tsf_val_f_i    => txtsu_tsf_val_f,
+      txtsu_tsf_pid_i      => txtsu_tsf_pid,
+      txtsu_tsf_fid_i      => txtsu_tsf_fid,
+      irq_nempty_i         => irq_nempty);
+
+  irq_nempty <= not txtsu_tsf_wr_empty;
+  
+end syn;