]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
*** empty log message ***
authorhadeshyp <hadeshyp>
Mon, 22 Dec 2008 12:18:47 +0000 (12:18 +0000)
committerhadeshyp <hadeshyp>
Mon, 22 Dec 2008 12:18:47 +0000 (12:18 +0000)
trb_net16_api_base.vhd
trb_net16_hub_base.vhd
trb_net16_med_8_SDR_sync.vhd [new file with mode: 0644]
trb_net16_regIO.vhd
trb_net_std.vhd

index 9af3988f1d369d9d8bc1aa4ad205c82975770e05..e2e3ec6721ad680208906ecf5bc26d3eaf628212 100644 (file)
@@ -34,6 +34,7 @@ entity trb_net16_api_base is
     APL_SHORT_TRANSFER_IN : in  std_logic;
     APL_DTYPE_IN          : in  std_logic_vector (3 downto 0);
     APL_ERROR_PATTERN_IN  : in  std_logic_vector (31 downto 0);
+    APL_LENGTH_IN         : in  std_logic_vector (15 downto 0);
     APL_SEND_IN           : in  std_logic;
     APL_TARGET_ADDRESS_IN : in  std_logic_vector (15 downto 0);-- the target (only for active APIs)
 
index ad856a7584ad0875f3eb6fee14a3dbf0f9d4d848..7ae760d16ab742ede075828841c3cc52843ad69a 100644 (file)
@@ -490,14 +490,14 @@ architecture trb_net16_hub_base_arch of trb_net16_hub_base is
       DAT_ADDR_OUT        : out std_logic_vector(c_REGIO_ADDRESS_WIDTH-1 downto 0);
       DAT_READ_ENABLE_OUT : out std_logic;
       DAT_WRITE_ENABLE_OUT: out std_logic;
-      DAT_DATA_OUT        : out std_logic_vector(c_REGIO_REGISTER_WIDTH-1 downto 0);
-      --Data input can only be used as reaction on read or write access. write operation should return data
-      --if successful
-      DAT_DATA_IN         : in  std_logic_vector(c_REGIO_REGISTER_WIDTH-1 downto 0);
-      DAT_DATAREADY_IN    : in std_logic;
-      DAT_NO_MORE_DATA_IN : in std_logic;
-        --finish transmission, when reading from a fifo and it got empty
-    --Additional write access to ctrl registers
+      DAT_DATA_OUT        : out std_logic_vector(c_REGIO_REG_WIDTH-1 downto 0);
+      DAT_DATA_IN         : in  std_logic_vector(c_REGIO_REG_WIDTH-1 downto 0);
+      DAT_DATAREADY_IN    : in  std_logic;
+      DAT_NO_MORE_DATA_IN : in  std_logic;
+      DAT_WRITE_ACK_IN    : in  std_logic;
+      DAT_UNKNOWN_ADDR_IN : in  std_logic;
+      DAT_TIMEOUT_OUT     : out std_logic;
+
       EXT_REG_DATA_IN     : in  std_logic_vector(31 downto 0);
       EXT_REG_DATA_OUT    : out std_logic_vector(31 downto 0);
       EXT_REG_WRITE_IN    : in  std_logic;
@@ -1198,6 +1198,9 @@ HUB_MED_CONNECTED(31 downto MII_NUMBER) <= (others => '1');
       DAT_DATA_IN         => x"00000000",
       DAT_DATAREADY_IN    => '0',
       DAT_NO_MORE_DATA_IN => '0',
+      DAT_UNKNOWN_ADDR_IN => '0',
+      DAT_TIMEOUT_OUT     => open,
+      DAT_WRITE_ACK_IN    => '0',
       EXT_REG_DATA_IN     => REGIO_EXT_REG_DATA_IN,
       EXT_REG_WRITE_IN    => REGIO_EXT_REG_WRITE_IN,
       EXT_REG_ADDR_IN     => REGIO_EXT_REG_ADDR_IN,
diff --git a/trb_net16_med_8_SDR_sync.vhd b/trb_net16_med_8_SDR_sync.vhd
new file mode 100644 (file)
index 0000000..08976e7
--- /dev/null
@@ -0,0 +1,456 @@
+--media interface with 16 data lines, single data rate and oversampling of RX input
+--oversampling running at 250 MHz
+
+
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.std_logic_ARITH.ALL;
+USE IEEE.std_logic_UNSIGNED.ALL;
+
+library work;
+use work.trb_net_std.all;
+
+entity trb_net16_med_8_SDR_sync is
+  port(
+    --  Misc
+    CLK    : in std_logic;
+    RESET  : in std_logic;
+    CLK_EN : in std_logic;
+
+    INT_DATAREADY_OUT  : out std_logic;
+    INT_DATA_OUT       : out std_logic_vector (c_DATA_WIDTH-1 downto 0);
+    INT_PACKET_NUM_OUT : out std_logic_vector (c_NUM_WIDTH-1  downto 0);
+    INT_READ_IN        : in  std_logic;
+
+    INT_DATAREADY_IN   : in  std_logic;
+    INT_DATA_IN        : in  std_logic_vector (c_DATA_WIDTH-1 downto 0);
+    INT_PACKET_NUM_IN  : in  std_logic_vector (c_NUM_WIDTH-1  downto 0);
+    INT_READ_OUT       : out std_logic;
+
+    --  Media direction port
+    TX_DATA_OUT        : out std_logic_vector (15 downto 0);
+    TX_CTRL_OUT        : out std_logic_vector (3 downto 0);
+    RX_DATA_IN         : in  std_logic_vector (15 downto 0);
+    RX_CTRL_IN         : in  std_logic_vector (3 downto 0);
+
+    -- Status and control port
+    STAT_OP: out std_logic_vector (15 downto 0);
+    CTRL_OP: in  std_logic_vector (15 downto 0);
+
+    STAT: out std_logic_vector (31 downto 0);
+    CTRL: in  std_logic_vector (31 downto 0)
+    );
+end entity;
+
+architecture trb_net16_med_8_SDR_sync_arch of trb_net16_med_8_SDR_sync is
+
+  component trb_net_fifo_16bit_bram_dualport is
+    generic(
+      USE_STATUS_FLAGS : integer  := c_YES
+      );
+    port (
+      read_clock_in:   IN  std_logic;
+      write_clock_in:  IN  std_logic;
+      read_enable_in:  IN  std_logic;
+      write_enable_in: IN  std_logic;
+      fifo_gsr_in:     IN  std_logic;
+      write_data_in:   IN  std_logic_vector(17 downto 0);
+      read_data_out:   OUT std_logic_vector(17 downto 0);
+      full_out:        OUT std_logic;
+      empty_out:       OUT std_logic;
+      fifostatus_out:  OUT std_logic_vector(3 downto 0);
+      valid_read_out:  OUT std_logic;
+      almost_empty_out:OUT std_logic;
+      almost_full_out :OUT std_logic
+      );
+  end component;
+
+  component dualdatarate_flipflop is
+  --1 clock, no CE, PRE for Lattice SCM
+    generic(
+      WIDTH : integer := 1
+      );
+    port(
+      C0 : in std_logic;
+      C1 : in std_logic;
+      CE : in std_logic;
+      CLR : in std_logic;
+      D0 : in std_logic_vector(WIDTH-1 downto 0);
+      D1 : in std_logic_vector(WIDTH-1 downto 0);
+      PRE : in std_logic;
+      Q : out std_logic_vector(WIDTH-1 downto 0)
+      );
+  end component;
+
+  signal RECV_CLK, recv_clk_locked : std_logic;
+  signal reg_RX_CLK, buf_RX_CLK, last_RX_CLK   : std_logic;
+  signal reg_RX_CTRL, buf_RX_CTRL : std_logic_vector(3 downto 0);
+  signal reg_RX_DATA, buf_RX_DATA : std_logic_vector(15 downto 0);
+
+  signal rx_datavalid    : std_logic;
+  signal rx_first_packet : std_logic;
+  signal rx_reset        : std_logic;
+  signal rx_parity       : std_logic;
+  signal rx_parity_match : std_logic;
+
+  signal rx_fifo_read_enable : std_logic;
+  signal rx_fifo_write_enable, next_rx_fifo_write_enable: std_logic;
+  signal rx_fifo_data_in, next_rx_fifo_data_in     : std_logic_vector(17 downto 0);
+  signal rx_fifo_data_out    : std_logic_vector(17 downto 0);
+  signal rx_fifo_full        : std_logic;
+  signal rx_fifo_empty       : std_logic;
+  signal rx_fifostatus_out : std_logic_vector(3 downto 0);
+  signal rx_valid_read_out : std_logic;
+  signal rx_almost_empty_out : std_logic;
+  signal rx_almost_full_out  : std_logic;
+
+
+  signal buf_INT_DATAREADY_OUT  : std_logic;
+
+  signal rx_packet_counter      : std_logic_vector(c_NUM_WIDTH-1 downto 0);
+  signal wait_for_startup       : std_logic;
+  signal wait_for_startup_slow  : std_logic;
+  signal rx_CLK_counter         : std_logic_vector(4 downto 0);
+  signal rx_clock_detect        : std_logic;
+
+  signal med_reset : std_logic;
+
+  signal tx_datavalid, tx_first_packet, tx_reset, tx_parity : std_logic;
+  signal buf_INT_DATA_IN  : std_logic_vector(c_DATA_WIDTH-1 downto 0);
+  signal buf_INT_READ_OUT : std_logic;
+  signal tx_clock_enable  : std_logic;
+  signal next_tx_reset    : std_logic;
+  signal buf_tx_reset     : std_logic;
+  signal buf_tx_clk       : std_logic;
+  signal recv_clk_real_locked : std_logic;
+  signal locked_counter : std_logic_vector(19 downto 0);
+
+  signal led_counter : std_logic_vector(18 downto 0);
+  signal send_resync_counter : std_logic_vector(11 downto 0);
+  signal send_resync         : std_logic;
+  signal rx_led, tx_led, link_led : std_logic;
+  signal med_error        : std_logic_vector(2 downto 0);
+  signal trbnet_reset : std_logic;
+begin
+
+
+--Transmitter (full speed only)
+-------------------------
+  INT_READ_OUT <= buf_INT_READ_OUT;
+  buf_INT_READ_OUT <= not wait_for_startup_slow and not buf_tx_reset;
+
+  TX_DATA_OUT     <= buf_INT_DATA_IN;
+  TX_CTRL_OUT(0)  <= tx_datavalid;
+  TX_CTRL_OUT(1)  <= tx_first_packet;
+  TX_CTRL_OUT(2)  <= tx_reset;
+  TX_CTRL_OUT(3)  <= tx_parity;
+
+  tx_clock_enable <= not RESET;
+
+  next_tx_reset <= CTRL_OP(15) or (recv_clk_real_locked and wait_for_startup_slow);
+
+
+  process(CLK)
+    begin
+      if rising_edge(CLK) then
+        TX_CLK_OUT <= buf_tx_clk;
+      end if;
+    end process;
+
+  process(CLK)
+    begin
+      if rising_edge(CLK) then
+        if med_reset = '1' then
+          tx_datavalid <= '0';
+          tx_reset <= '1';
+          buf_tx_reset <= '1';
+          buf_INT_DATA_IN <= (others => '0');
+          tx_first_packet <= '0';
+          tx_parity <= '0';
+          buf_tx_clk <= '0';
+        else
+          buf_INT_DATA_IN <= INT_DATA_IN;
+          tx_datavalid    <= INT_DATAREADY_IN and buf_INT_READ_OUT;
+          if INT_PACKET_NUM_IN = c_H0 then
+            tx_first_packet <= '1';
+          else
+            tx_first_packet <= '0';
+          end if;
+          tx_reset        <= buf_tx_reset;
+          buf_tx_reset    <= next_tx_reset;
+          tx_parity       <= xor_all(INT_DATA_IN);
+          buf_tx_clk      <= not buf_tx_clk;
+        end if;
+      end if;
+    end process;
+
+
+
+--Receiver
+-------------------------
+  RECV_CLOCK_GEN : trb_net_clock_generator
+    generic map(
+      FREQUENCY_IN  => 100.0,
+      FREQUENCY_OUT => 200.0,
+      CLOCK_MULT    => 2,
+      CLOCK_DIV     => 1,
+      CLKIN_DIVIDE_BY_2 => false,
+      CLKIN_PERIOD  => 10.0
+      )
+    port map(
+      RESET   => RESET,
+      CLK_IN  => CLK,
+      CLK_OUT => RECV_CLK,
+      LOCKED  => recv_clk_locked
+      );
+
+process(CLK)
+  begin
+    if rising_edge(CLK) then
+      if recv_clk_locked = '0' then
+        locked_counter <= (others => '0');
+        recv_clk_real_locked <= '0';
+      else
+        if locked_counter /= x"0000F" then
+          locked_counter <= locked_counter + 1;
+        else
+          recv_clk_real_locked <= '1';
+        end if;
+      end if;
+    end if;
+  end process;
+
+  RX_INPUT_REG : process(RECV_CLK)
+    begin
+      if rising_edge(RECV_CLK) then
+        reg_RX_CLK  <= RX_CLK_IN;
+        reg_RX_CTRL <= RX_CTRL_IN;
+        reg_RX_DATA <= RX_DATA_IN;
+      end if;
+    end process;
+
+  RX_REG : process(RECV_CLK, recv_clk_real_locked)
+    begin
+      if rising_edge(RECV_CLK) then
+        if recv_clk_real_locked = '0' then
+          buf_RX_CTRL <= (others => '0');
+          buf_RX_CLK  <= '0';
+          last_RX_CLK <= '0';
+          buf_RX_DATA <= (others => '0');
+        else
+          buf_RX_CLK  <= reg_RX_CLK;
+          buf_RX_DATA <= reg_RX_DATA;
+          buf_RX_CTRL <= reg_RX_CTRL;
+          last_RX_CLK <= buf_RX_CLK;
+        end if;
+      end if;
+    end process;
+
+  rx_datavalid    <= buf_RX_CTRL(0);
+  rx_first_packet <= buf_RX_CTRL(1);
+  rx_reset        <= buf_RX_CTRL(2);
+  rx_parity       <= buf_RX_CTRL(3);
+
+  rx_parity_match      <= '1' when rx_parity = xor_all(buf_RX_DATA) else '0';
+  next_rx_fifo_write_enable <= (buf_RX_CLK xor last_RX_CLK) and rx_datavalid;
+  next_rx_fifo_data_in      <= rx_first_packet & rx_parity_match & buf_RX_DATA;
+
+  reg_fifo_in : process(RECV_CLK)
+    begin
+      if rising_edge(RECV_CLK) then
+        rx_fifo_write_enable <= next_rx_fifo_write_enable;
+        rx_fifo_data_in      <= next_rx_fifo_data_in;
+      end if;
+    end process;
+
+  RX_FIFO : trb_net_fifo_16bit_bram_dualport
+    port map(
+      read_clock_in => CLK,
+      write_clock_in => RECV_CLK,
+      read_enable_in => rx_fifo_read_enable,
+      write_enable_in => rx_fifo_write_enable,
+      fifo_gsr_in => med_reset,
+      write_data_in => rx_fifo_data_in,
+      read_data_out => rx_fifo_data_out,
+      full_out => rx_fifo_full,
+      empty_out => rx_fifo_empty,
+      fifostatus_out => rx_fifostatus_out,
+      valid_read_out => rx_valid_read_out,
+      almost_empty_out => rx_almost_empty_out,
+      almost_full_out => rx_almost_full_out
+      );
+
+  rx_fifo_read_enable <= INT_READ_IN;
+
+  INT_DATA_OUT <= rx_fifo_data_out(15 downto 0);
+  INT_PACKET_NUM_OUT <= rx_packet_counter;
+  INT_DATAREADY_OUT <= buf_INT_DATAREADY_OUT;
+
+  packet_counter_p : process(CLK)
+    begin
+      if rising_edge(CLK) then
+        if med_reset = '1' then
+          rx_packet_counter <= "100";
+        elsif buf_INT_DATAREADY_OUT = '1' then
+          if rx_packet_counter = c_max_word_number then
+            rx_packet_counter <= (others => '0');
+          else
+            rx_packet_counter <= rx_packet_counter + 1;
+          end if;
+        end if;
+      end if;
+    end process;
+
+
+  rx_dataready_p : process(CLK)
+    begin
+      if rising_edge(CLK) then
+        if med_reset = '1' then
+          buf_INT_DATAREADY_OUT <= '0';
+        else
+          buf_INT_DATAREADY_OUT <= rx_fifo_read_enable and not rx_fifo_empty;
+        end if;
+      end if;
+    end process;
+
+
+--monitor link
+-------------------------
+  process(CLK)
+    begin
+      if rising_edge(CLK) then
+        wait_for_startup_slow <= wait_for_startup;
+      end if;
+    end process;
+
+  process(RECV_CLK, recv_clk_real_locked,med_reset)
+    begin
+      if rising_edge(RECV_CLK) then
+        if recv_clk_real_locked = '0' or med_reset = '1' or rx_clock_detect = '0' then
+          wait_for_startup <= '1';
+        elsif rx_reset = '1' and recv_clk_locked = '1' then
+          wait_for_startup <= '0';
+        end if;
+      end if;
+    end process;
+
+
+  ERROR_OUT_gen : process(CLK)
+    begin
+      if rising_edge(CLK) then
+        if recv_clk_real_locked = '0' or rx_clock_detect = '0' then
+          med_error <= ERROR_NC;
+        elsif (buf_INT_DATAREADY_OUT = '1' and rx_fifo_data_out(16) = '0')  then --Parity error
+          med_error <= ERROR_ENCOD;
+        elsif (rx_packet_counter /= "100" and buf_INT_DATAREADY_OUT = '1' and rx_fifo_data_out(17) = '1') then
+          med_error <= ERROR_FATAL;                                          --Counter error
+        else
+          med_error <= ERROR_OK;
+        end if;
+      end if;
+    end process;
+
+
+  rx_clk_detect_counter: process (RECV_CLK, recv_clk_real_locked)
+    begin
+      if rising_edge(RECV_CLK) then
+        if recv_clk_real_locked = '0'  then
+          rx_CLK_counter <= (others => '0');
+          rx_clock_detect <= '0';
+        elsif buf_RX_CLK = '1' and last_RX_CLK = '0' then
+          rx_CLK_counter <= (others => '0');
+          rx_clock_detect <= '1';
+        elsif rx_CLK_counter /= 31 then
+          rx_CLK_counter <= rx_CLK_counter + 1;
+        elsif rx_CLK_counter = 31 then
+          rx_clock_detect <= '0';
+        end if;
+      end if;
+    end process;
+
+
+--STAT & CTRL Ports
+-------------------------
+
+--LED
+  link_led <= rx_clock_detect and not wait_for_startup_slow;
+
+  process(CLK)
+    begin
+      if rising_edge(CLK) then
+        if led_counter(18) = '1' then
+          led_counter <= (others => '0');
+        else
+          led_counter <= led_counter + 1;
+        end if;
+        if rx_fifo_empty = '0' then
+          rx_led <= '1';
+        elsif led_counter(18) = '1' then
+          rx_led <= '0';
+        end if;
+        if tx_datavalid = '1' then
+          tx_led <= '1';
+        elsif led_counter(18) = '1' then
+          tx_led <= '0';
+        end if;
+      end if;
+    end process;
+
+
+  STAT_OP(2 downto 0) <= med_error;
+  STAT_OP(8 downto 3) <= (others => '0');
+  STAT_OP(9)  <= link_led;
+  STAT_OP(10) <= rx_led;
+  STAT_OP(11) <= tx_led;
+  STAT_OP(12) <= '0';
+  STAT_OP(13) <= trbnet_reset;
+  STAT_OP(14) <= rx_clock_detect;
+  STAT_OP(15) <= '1' when rx_reset = '1' and wait_for_startup_slow = '0' else '0';
+
+  STAT(12) <= rx_parity_match;
+  STAT(11) <= RECV_CLK;
+  STAT(10) <= recv_clk_real_locked;
+  STAT(9) <= rx_reset;
+  STAT(8) <= buf_RX_CLK xor last_RX_CLK;
+  STAT(7) <= recv_clk_locked;
+  STAT(6) <= wait_for_startup;
+  STAT(5) <= rx_first_packet;
+  STAT(4) <= buf_tx_clk; --not or_all(INT_PACKET_NUM_IN); --tx_first_packet;
+  STAT(3) <= rx_datavalid;
+  STAT(2) <= next_tx_reset;
+  STAT(1) <= buf_RX_CLK;
+
+  STAT(13) <= or_all(rx_fifostatus_out);
+  STAT(14) <= rx_valid_read_out;
+  STAT(15) <= rx_almost_empty_out;
+  STAT(16) <= rx_almost_full_out;
+  STAT(31 downto 17)    <= (others => '0');
+
+  med_reset <= RESET or send_resync;
+  trbnet_reset <= rx_reset or not recv_clk_real_locked;
+
+
+--detect resync
+  process(CLK)
+    begin
+      if rising_edge(CLK) then
+        if RESET = '1' then
+          send_resync <= '0';
+          send_resync_counter <= (others => '0');
+        else
+          if not (send_resync_counter = 0) then
+            send_resync_counter <= send_resync_counter + 1;
+          end if;
+          if CTRL_OP(15) = '1' and send_resync_counter(11 downto 4) = 0 then
+            send_resync <= '1';
+            send_resync_counter <= send_resync_counter + 1;
+          end if;
+          if send_resync_counter = x"00F" then
+            send_resync <= '0';
+          end if;
+        end if;
+      end if;
+    end process;
+
+end architecture;
\ No newline at end of file
index 186af9f2f0518a5e66ba0cf7c0a1f3116630ddd3..cf6f8cac57ac237458ada957609c76dd788df985 100644 (file)
@@ -17,7 +17,7 @@ entity trb_net16_regIO is
     INIT_CTRL_REGS     : std_logic_vector(2**(3)*32-1 downto 0) :=
             (others => '0');
     --set to 0 for unused ctrl registers to save resources
-    USED_CTRL_REGS     : std_logic_vector(2**(3)-1 downto 0)   := "00001111";
+    USED_CTRL_REGS     : std_logic_vector(2**(3)-1 downto 0)   := "00000001";
     --set to 0 for each unused bit in a register
     USED_CTRL_BITMASK  : std_logic_vector(2**(3)*32-1 downto 0) :=
             (others => '1');
@@ -62,22 +62,23 @@ entity trb_net16_regIO is
     MY_ADDRESS_OUT      : out std_logic_vector(15 downto 0);
 
   --Common Register in / out
-    COMMON_STAT_REG_IN  : in  std_logic_vector(std_COMSTATREG*c_REGIO_REGISTER_WIDTH-1 downto 0);
-    COMMON_CTRL_REG_OUT : out std_logic_vector(std_COMCTRLREG*c_REGIO_REGISTER_WIDTH-1 downto 0);
+    COMMON_STAT_REG_IN  : in  std_logic_vector(std_COMSTATREG*c_REGIO_REG_WIDTH-1 downto 0);
+    COMMON_CTRL_REG_OUT : out std_logic_vector(std_COMCTRLREG*c_REGIO_REG_WIDTH-1 downto 0);
   --Custom Register in / out
-    REGISTERS_IN        : in  std_logic_vector(c_REGIO_REGISTER_WIDTH*2**(NUM_STAT_REGS)-1 downto 0);
-    REGISTERS_OUT       : out std_logic_vector(c_REGIO_REGISTER_WIDTH*2**(NUM_CTRL_REGS)-1 downto 0);
+    REGISTERS_IN        : in  std_logic_vector(c_REGIO_REG_WIDTH*2**(NUM_STAT_REGS)-1 downto 0);
+    REGISTERS_OUT       : out std_logic_vector(c_REGIO_REG_WIDTH*2**(NUM_CTRL_REGS)-1 downto 0);
   --Internal Data Port
     DAT_ADDR_OUT        : out std_logic_vector(c_REGIO_ADDRESS_WIDTH-1 downto 0);
     DAT_READ_ENABLE_OUT : out std_logic;
     DAT_WRITE_ENABLE_OUT: out std_logic;
-    DAT_DATA_OUT        : out std_logic_vector(c_REGIO_REGISTER_WIDTH-1 downto 0);
-    --Data input can only be used as reaction on read or write access. write operation should return data
-    --if successful
-    DAT_DATA_IN         : in  std_logic_vector(c_REGIO_REGISTER_WIDTH-1 downto 0);
-    DAT_DATAREADY_IN    : in std_logic;
-    DAT_NO_MORE_DATA_IN : in std_logic;
-      --finish transmission, when reading from a fifo and it got empty
+    DAT_DATA_OUT        : out std_logic_vector(c_REGIO_REG_WIDTH-1 downto 0);
+    DAT_DATA_IN         : in  std_logic_vector(c_REGIO_REG_WIDTH-1 downto 0);
+    DAT_DATAREADY_IN    : in  std_logic;
+    DAT_NO_MORE_DATA_IN : in  std_logic;
+    DAT_WRITE_ACK_IN    : in  std_logic;
+    DAT_UNKNOWN_ADDR_IN : in  std_logic;
+    DAT_TIMEOUT_OUT     : out std_logic;
+
   --Additional write access to ctrl registers
     EXT_REG_DATA_IN     : in  std_logic_vector(31 downto 0);
     EXT_REG_DATA_OUT    : out std_logic_vector(31 downto 0);
@@ -148,7 +149,7 @@ architecture trb_net16_regIO_arch of trb_net16_regIO is
 
   type fsm_state_t is (IDLE, HEADER_RECV, REG_READ, REG_WRITE, ONE_READ, ONE_WRITE, SEND_REPLY_SHORT_TRANSFER, MEM_START_WRITE,
                        MEM_READ, MEM_WRITE, DAT_START_READ, DAT_READ, SEND_REPLY_DATA_finish, ADDRESS_ACK, ADDRESS_RECV,
-                       MEM_START_READ, DAT_START_READ_AFTER_WRITE);
+                       MEM_START_READ, SEND_RW_ERROR, MEM_WRITE_2, WAIT_AFTER_REG_WRITE);
   signal current_state, next_state             : fsm_state_t;
 --  signal HDR_F1, HDR_F2, HDR_F3, HDR_F0        : std_logic_vector(c_DATA_WIDTH-1 downto 0);
 --  signal next_HDR_F1, next_HDR_F2, next_HDR_F3, next_HDR_F0 : std_logic_vector(c_DATA_WIDTH-1 downto 0);
@@ -164,21 +165,21 @@ architecture trb_net16_regIO_arch of trb_net16_regIO is
   signal buf_API_SHORT_TRANSFER_OUT, next_API_SHORT_TRANSFER_OUT : std_logic;
   signal buf_API_DATAREADY_OUT, next_API_DATAREADY_OUT       : std_logic;
 
-  signal buf_DAT_DATA_OUT                 : std_logic_vector(c_REGIO_REGISTER_WIDTH-1 downto 0);
-  signal buf_DAT_DATA_IN                  : std_logic_vector(c_REGIO_REGISTER_WIDTH-1 downto 0);
+  signal buf_DAT_DATA_OUT                 : std_logic_vector(c_REGIO_REG_WIDTH-1 downto 0);
+  signal buf_DAT_DATA_IN                  : std_logic_vector(c_REGIO_REG_WIDTH-1 downto 0);
 
   signal buf_DAT_READ_ENABLE_OUT, next_DAT_READ_ENABLE_OUT   : std_logic;
   signal buf_DAT_WRITE_ENABLE_OUT, next_DAT_WRITE_ENABLE_OUT : std_logic;
   signal buf_DAT_ADDR_OUT                 : std_logic_vector(c_REGIO_ADDRESS_WIDTH-1 downto 0);
 
-  signal buf_REGISTERS_OUT                     : std_logic_vector(c_REGIO_REGISTER_WIDTH*2**(NUM_CTRL_REGS)-1 downto 0);
+  signal buf_REGISTERS_OUT                     : std_logic_vector(c_REGIO_REG_WIDTH*2**(NUM_CTRL_REGS)-1 downto 0);
   signal REGISTERS_OUT_write_enable            : std_logic_vector(2**(NUM_CTRL_REGS)-1 downto 0);
   signal next_REGISTERS_OUT_write_enable       : std_logic_vector(2**(NUM_CTRL_REGS)-1 downto 0);
   signal reg_enable_pattern                    : std_logic_vector(63 downto 0);
 
   signal next_COMMON_REGISTERS_OUT_write_enable: std_logic_vector(std_COMCTRLREG - 1 downto 0);
   signal COMMON_REGISTERS_OUT_write_enable     : std_logic_vector(std_COMCTRLREG - 1 downto 0);
-  signal buf_COMMON_CTRL_REG_OUT               : std_logic_vector(c_REGIO_REGISTER_WIDTH*std_COMCTRLREG-1 downto 0);
+  signal buf_COMMON_CTRL_REG_OUT               : std_logic_vector(c_REGIO_REG_WIDTH*std_COMCTRLREG-1 downto 0);
   signal state_bits                            : std_logic_vector(3 downto 0);
 
   signal ADR_SEND_OUT : std_logic;
@@ -197,6 +198,20 @@ architecture trb_net16_regIO_arch of trb_net16_regIO is
   signal packet_counter : std_logic_vector(c_NUM_WIDTH-1 downto 0);
   signal next_packet_counter : std_logic_vector(c_NUM_WIDTH-1 downto 0);
   signal addr_counter_enable, next_addr_counter_enable : std_logic;
+  signal timeout_counter      : std_logic_vector(c_regio_timeout_bit downto 0);
+  signal next_timeout_counter : std_logic_vector(c_regio_timeout_bit downto 0);
+  signal timeout              : std_logic;
+  signal next_timeout         : std_logic;
+  signal unknown              : std_logic;
+  signal next_unknown         : std_logic;
+  signal next_API_READ_OUT    : std_logic;
+  signal next_nomoredata      : std_logic;
+  signal nomoredata           : std_logic;
+  signal DAT_DATAREADY_IN_before : std_logic;
+  signal combined_API_READ_OUT   : std_logic;
+  signal dat_data_counter      : std_logic_vector(15 downto 0);
+  signal next_dat_data_counter : std_logic_vector(15 downto 0);
+
 
 begin
 
@@ -238,15 +253,15 @@ begin
   buf_DAT_ADDR_OUT <= address;
   buf_DAT_DATA_OUT <= saved_Reg_high & saved_Reg_low;
 
-  fsm : process(current_state,
-                API_DATA_IN, API_PACKET_NUM_IN, API_TYP_IN, API_DATAREADY_IN, API_READ_IN,
-                address, saved_Reg_high, saved_Reg_low, saved_operation,
+  fsm : process(API_DATA_IN, API_PACKET_NUM_IN, API_TYP_IN, API_DATAREADY_IN, API_READ_IN,
+                address, saved_Reg_high, saved_Reg_low, saved_operation, current_state,
                 buf_API_SEND_OUT, next_packet_counter, buf_API_DATA_OUT, buf_API_SHORT_TRANSFER_OUT,
                 REGISTERS_IN, buf_REGISTERS_OUT, reg_enable_pattern, DAT_NO_MORE_DATA_IN,
-                DAT_DATAREADY_IN, buf_DAT_DATA_IN, ADR_REJECTED,
+                DAT_DATAREADY_IN, buf_DAT_DATA_IN, ADR_REJECTED, timeout_counter, nomoredata,
                 ADR_READ_OUT, ADR_DATAREADY_OUT, ADR_DATA_OUT, length, dont_understand,
-                buf_rom_read_addr, ADR_SEND_OUT, rom_read_dout, COMMON_STAT_REG_IN, buf_COMMON_CTRL_REG_OUT
---              ,  HDR_F1, HDR_F2, HDR_F3
+                buf_rom_read_addr, ADR_SEND_OUT, rom_read_dout, COMMON_STAT_REG_IN, buf_COMMON_CTRL_REG_OUT,
+                timeout, unknown, addr_counter_enable, DAT_UNKNOWN_ADDR_IN, dat_data_counter,
+                DAT_WRITE_ACK_IN, DAT_DATAREADY_IN_before
                 )
     variable regnum_STAT : integer range 0 to 2**NUM_STAT_REGS-1;
     variable regnum_CTRL : integer range 0 to 2**NUM_CTRL_REGS-1;
@@ -254,15 +269,11 @@ begin
     variable regnum_cCTRL : integer range 0 to std_COMCTRLREG-1;
    begin
       next_state  <= current_state;
---       next_HDR_F1 <= HDR_F1;
---       next_HDR_F2 <= HDR_F2;
---       next_HDR_F3 <= HDR_F3;
       next_address  <= address;
       next_Reg_high <= saved_Reg_high;
       next_Reg_low  <= saved_Reg_low;
       ADR_DATAREADY_IN <= '0';
       ADR_READ_IN <= '0';
-      buf_API_READ_OUT <= '1';
       next_API_SEND_OUT <= buf_API_SEND_OUT;
       next_API_DATAREADY_OUT <= '0';
       next_API_DATA_OUT <= buf_API_DATA_OUT;
@@ -279,12 +290,23 @@ begin
       regnum_cSTAT := conv_integer(address(std_COMneededwidth-1 downto 0));
       regnum_cCTRL := conv_integer(address(std_COMneededwidth-1 downto 0));
       next_dont_understand <= dont_understand;
+      next_timeout <= timeout;
+      next_unknown <= unknown;
+      next_nomoredata <= nomoredata;
+      next_timeout_counter <= (others => '0');
+      next_addr_counter_enable <= addr_counter_enable;
+      next_API_READ_OUT <= '1';
+      next_dat_data_counter <= dat_data_counter;
 
       case current_state is
         when IDLE =>
           next_dont_understand <= '0';
           next_API_SEND_OUT <= '0';
           next_API_SHORT_TRANSFER_OUT <= '0';
+          next_unknown <= '0';
+          next_timeout <= '0';
+          next_nomoredata <= '0';
+          next_dat_data_counter <= (others => '0');
           if API_TYP_IN = TYPE_HDR then
             next_state <= HEADER_RECV;
           end if;
@@ -292,14 +314,7 @@ begin
         when HEADER_RECV =>        --read and save HDR
           if API_DATAREADY_IN = '1' then
             case API_PACKET_NUM_IN is
---               when c_F0 =>
---                 next_HDR_F0 <= API_DATA_IN;
---               when c_F1 =>
---                 next_HDR_F1 <= API_DATA_IN;
---               when c_F2 =>
---                 next_HDR_F2 <= API_DATA_IN;
               when c_F3 =>
---                 next_HDR_F3 <= API_DATA_IN;
                 case API_DATA_IN(3 downto 0) is
                   when c_read_register_type   => next_state <= ONE_READ;
                   when c_write_register_type  => next_state <= ONE_WRITE;
@@ -317,7 +332,6 @@ begin
 
         when ADDRESS_RECV =>
           ADR_DATAREADY_IN <= API_DATAREADY_IN;
-          buf_API_READ_OUT <= ADR_READ_OUT;
           ADR_READ_IN <= '0';
           if ADR_REJECTED = '1' then
             next_state <= SEND_REPLY_SHORT_TRANSFER;
@@ -395,12 +409,23 @@ begin
                   next_state   <= REG_READ;
                 else
                   next_DAT_WRITE_ENABLE_OUT <= '1';
-                  next_state   <= DAT_START_READ_AFTER_WRITE;
+                  next_state   <= WAIT_AFTER_REG_WRITE;
                 end if;
               when others => null;
             end case;
           end if;
 
+        when WAIT_AFTER_REG_WRITE =>
+          next_timeout_counter <= timeout_counter + 1;
+          if DAT_WRITE_ACK_IN = '1' then
+            next_state      <= SEND_REPLY_SHORT_TRANSFER;
+          elsif DAT_NO_MORE_DATA_IN = '1' or DAT_UNKNOWN_ADDR_IN = '1' or timeout_counter(c_regio_timeout_bit) = '1' then
+            next_state      <= SEND_RW_ERROR;
+            next_timeout    <= timeout_counter(c_regio_timeout_bit);
+            next_unknown    <= DAT_UNKNOWN_ADDR_IN;
+            next_nomoredata <= DAT_NO_MORE_DATA_IN;
+          end if;
+
         when REG_READ =>
           next_API_SEND_OUT <= '1';
           next_API_DATAREADY_OUT <= '1';
@@ -412,25 +437,25 @@ begin
                 next_API_DATA_OUT <= rom_read_dout;
                 rom_read_addr <= address(1 downto 0) & '0';
               elsif address(7 downto 6) = "10" then
-                next_API_DATA_OUT <= REGISTERS_IN(regnum_STAT*c_REGIO_REGISTER_WIDTH+31 downto regnum_STAT*c_REGIO_REGISTER_WIDTH+16);
+                next_API_DATA_OUT <= REGISTERS_IN(regnum_STAT*c_REGIO_REG_WIDTH+31 downto regnum_STAT*c_REGIO_REG_WIDTH+16);
               elsif address(7 downto 6) = "11" then
-                next_API_DATA_OUT <= buf_REGISTERS_OUT(regnum_CTRL*c_REGIO_REGISTER_WIDTH+31 downto regnum_CTRL*c_REGIO_REGISTER_WIDTH+16);
+                next_API_DATA_OUT <= buf_REGISTERS_OUT(regnum_CTRL*c_REGIO_REG_WIDTH+31 downto regnum_CTRL*c_REGIO_REG_WIDTH+16);
               elsif address(5) = '0' then
-                next_API_DATA_OUT <= COMMON_STAT_REG_IN(regnum_cSTAT*c_REGIO_REGISTER_WIDTH+31 downto regnum_cSTAT*c_REGIO_REGISTER_WIDTH+16);
+                next_API_DATA_OUT <= COMMON_STAT_REG_IN(regnum_cSTAT*c_REGIO_REG_WIDTH+31 downto regnum_cSTAT*c_REGIO_REG_WIDTH+16);
               else --if address(5) = '1' then
-                next_API_DATA_OUT <= buf_COMMON_CTRL_REG_OUT(regnum_cCTRL*c_REGIO_REGISTER_WIDTH+31 downto regnum_cCTRL*c_REGIO_REGISTER_WIDTH+16);
+                next_API_DATA_OUT <= buf_COMMON_CTRL_REG_OUT(regnum_cCTRL*c_REGIO_REG_WIDTH+31 downto regnum_cCTRL*c_REGIO_REG_WIDTH+16);
               end if;
             when c_F2 =>
               if address(7 downto 6) = "01" then
                 next_API_DATA_OUT <= rom_read_dout;
               elsif address(7 downto 6) = "10" then
-                next_API_DATA_OUT <= REGISTERS_IN(regnum_STAT*c_REGIO_REGISTER_WIDTH+15 downto regnum_STAT*c_REGIO_REGISTER_WIDTH);
+                next_API_DATA_OUT <= REGISTERS_IN(regnum_STAT*c_REGIO_REG_WIDTH+15 downto regnum_STAT*c_REGIO_REG_WIDTH);
               elsif address(7 downto 6) = "11" then
-                next_API_DATA_OUT <= buf_REGISTERS_OUT(regnum_CTRL*c_REGIO_REGISTER_WIDTH+15 downto regnum_CTRL*c_REGIO_REGISTER_WIDTH);
+                next_API_DATA_OUT <= buf_REGISTERS_OUT(regnum_CTRL*c_REGIO_REG_WIDTH+15 downto regnum_CTRL*c_REGIO_REG_WIDTH);
               elsif address(5) = '0' then
-                next_API_DATA_OUT <= COMMON_STAT_REG_IN(regnum_cSTAT*c_REGIO_REGISTER_WIDTH+15 downto regnum_cSTAT*c_REGIO_REGISTER_WIDTH);
+                next_API_DATA_OUT <= COMMON_STAT_REG_IN(regnum_cSTAT*c_REGIO_REG_WIDTH+15 downto regnum_cSTAT*c_REGIO_REG_WIDTH);
               else --if address(5) = '1' then
-                next_API_DATA_OUT <= buf_COMMON_CTRL_REG_OUT(regnum_cCTRL*c_REGIO_REGISTER_WIDTH+15 downto regnum_cCTRL*c_REGIO_REGISTER_WIDTH);
+                next_API_DATA_OUT <= buf_COMMON_CTRL_REG_OUT(regnum_cCTRL*c_REGIO_REG_WIDTH+15 downto regnum_cCTRL*c_REGIO_REG_WIDTH);
               end if;
             when c_F3 =>
               next_API_DATA_OUT <= (others => '0');
@@ -446,16 +471,19 @@ begin
             next_state <= SEND_REPLY_SHORT_TRANSFER;
             next_dont_understand <= '1';
           else
-            if API_TYP_IN = TYPE_DAT and API_PACKET_NUM_IN = c_F1 and API_DATAREADY_IN = '1' then
-              next_length <= '0' & API_DATA_IN(14 downto 0);
-              next_addr_counter_enable <= API_DATA_IN(15);
-              next_DAT_READ_ENABLE_OUT <= '1';
-              next_state <= MEM_READ;
-            elsif API_TYP_IN = TYPE_DAT and API_PACKET_NUM_IN = c_F0 and API_DATAREADY_IN = '1' then
-              next_address <= API_DATA_IN;
-              if API_DATA_IN(15 downto 8) = 0 then
-                next_state <= SEND_REPLY_SHORT_TRANSFER;
-                next_dont_understand <= '1';
+            if API_TYP_IN = TYPE_DAT  and API_DATAREADY_IN = '1' then
+              if API_PACKET_NUM_IN = c_F1 then
+                next_length <= '0' & API_DATA_IN(14 downto 0);
+                next_addr_counter_enable <= API_DATA_IN(15);
+                next_DAT_READ_ENABLE_OUT <= '1';
+                next_dat_data_counter <= dat_data_counter + 1;
+                next_state <= MEM_READ;
+              elsif API_PACKET_NUM_IN = c_F0 then
+                next_address <= API_DATA_IN;
+                if API_DATA_IN(15 downto 8) = 0 then
+                  next_state <= SEND_REPLY_SHORT_TRANSFER;
+                  next_dont_understand <= '1';
+                end if;
               end if;
             end if;
           end if;
@@ -464,15 +492,23 @@ begin
           next_API_DATAREADY_OUT <= '1';
           case next_packet_counter is
             when c_F0 =>
-              if DAT_DATAREADY_IN = '0' then
+              next_timeout_counter <= timeout_counter + 1;
+              if DAT_DATAREADY_IN = '0' and DAT_DATAREADY_IN_before = '0' then
                 next_API_DATAREADY_OUT <= '0';
               end if;
               if length = 0 or DAT_NO_MORE_DATA_IN = '1' then
-                next_state <= SEND_REPLY_DATA_finish;
+                next_state <= SEND_REPLY_SHORT_TRANSFER;
+                next_nomoredata <= DAT_NO_MORE_DATA_IN;
                 next_API_DATAREADY_OUT <= '0';
-              else
+              elsif DAT_UNKNOWN_ADDR_IN = '1' then
+                next_state <= SEND_REPLY_DATA_finish;
+                next_unknown <= '1';
+              elsif DAT_DATAREADY_IN = '1' then
                 next_API_SEND_OUT <= '1';
                 next_API_DATA_OUT <= address;
+              elsif timeout_counter(c_regio_timeout_bit) = '1' then
+                next_state <= SEND_REPLY_DATA_finish;
+                next_timeout <= '1';
               end if;
             when c_F1 =>
               next_API_DATA_OUT <= buf_DAT_DATA_IN(31 downto 16);
@@ -483,6 +519,8 @@ begin
               next_API_DATA_OUT <= (others => '0');
               if length > 1 and API_READ_IN = '1' then
                 next_DAT_READ_ENABLE_OUT <= '1';
+                next_dat_data_counter    <= dat_data_counter + 1;
+                next_timeout_counter     <= (others => '0');
                 if addr_counter_enable = '1' then
                   next_address <= address + 1;
                 end if;
@@ -494,68 +532,97 @@ begin
           if USE_DAT_PORT = c_NO then
             next_state <= SEND_REPLY_SHORT_TRANSFER;
             next_dont_understand <= '1';
-          elsif API_PACKET_NUM_IN = c_F0 and API_TYP_IN = TYPE_DAT and API_DATAREADY_IN = '1' then
-            next_address <= API_DATA_IN;
-          elsif API_PACKET_NUM_IN = c_F1 and API_TYP_IN = TYPE_DAT and API_DATAREADY_IN = '1' then
-            next_addr_counter_enable <= API_DATA_IN(15);
-          elsif API_PACKET_NUM_IN = c_F3 and API_TYP_IN = TYPE_DAT and API_DATAREADY_IN = '1' then
-            next_state <= MEM_WRITE;
+          else
+            if API_TYP_IN = TYPE_DAT and API_DATAREADY_IN = '1' then
+              if API_PACKET_NUM_IN = c_F0 then
+                next_address <= API_DATA_IN;
+              elsif API_PACKET_NUM_IN = c_F1 then
+                next_addr_counter_enable <= API_DATA_IN(15);
+              elsif API_PACKET_NUM_IN = c_F3 then
+                next_state <= MEM_WRITE;
+              end if;
+            end if;
           end if;
 
         when MEM_WRITE =>
-          if USE_DAT_PORT = c_NO then
-            next_state <= SEND_REPLY_SHORT_TRANSFER;
-            next_dont_understand <= '1';
-          elsif API_DATAREADY_IN = '1' then
+          if API_DATAREADY_IN = '1' then
             case API_PACKET_NUM_IN is
               when c_F1 =>
-                next_Reg_high <= API_DATA_IN;
+                next_Reg_high         <= API_DATA_IN;
               when c_F2 =>
-                next_Reg_low <= API_DATA_IN;
+                next_Reg_low          <= API_DATA_IN;
                 next_DAT_WRITE_ENABLE_OUT <= '1';
+                next_dat_data_counter <= dat_data_counter + 1;
+                next_API_READ_OUT     <= '0';
+                next_state            <= MEM_WRITE_2;
               when c_F3 =>
                 if addr_counter_enable = '1' then
-                  next_address <= address + 1;
+                  next_address        <= address + 1;
                 end if;
               when others => null;
             end case;
             if API_TYP_IN = TYPE_TRM then
-              next_state <= DAT_START_READ;
-              next_DAT_READ_ENABLE_OUT <= '1';
-              next_API_SEND_OUT <= '1';
+              next_state <= SEND_REPLY_SHORT_TRANSFER;
             end if;
           end if;
 
-        when DAT_START_READ_AFTER_WRITE =>
-          next_state <= DAT_START_READ;
-          next_DAT_READ_ENABLE_OUT <= '1';
+        when MEM_WRITE_2 =>
+          if DAT_WRITE_ACK_IN = '1' then
+            next_API_READ_OUT <= '1';
+            next_state        <= MEM_WRITE;
+          elsif timeout_counter(c_regio_timeout_bit) = '1' or DAT_UNKNOWN_ADDR_IN = '1' or DAT_NO_MORE_DATA_IN = '1' then
+            next_API_READ_OUT <= '1';
+            next_state        <= SEND_RW_ERROR;
+            next_timeout      <= timeout_counter(c_regio_timeout_bit);
+            next_unknown      <= DAT_UNKNOWN_ADDR_IN;
+            next_nomoredata   <= DAT_NO_MORE_DATA_IN;
+          else
+            next_timeout_counter <= timeout_counter + 1;
+            next_API_READ_OUT <= '0';
+          end if;
 
         when DAT_START_READ =>
           if DAT_DATAREADY_IN = '1' then
-            next_state <= DAT_READ;
-          elsif DAT_NO_MORE_DATA_IN = '1' then
-            next_state <= SEND_REPLY_SHORT_TRANSFER;
+            next_state      <= DAT_READ;
+          elsif DAT_NO_MORE_DATA_IN = '1' or DAT_UNKNOWN_ADDR_IN = '1' or timeout_counter(c_regio_timeout_bit) = '1' then
+            next_state      <= SEND_REPLY_SHORT_TRANSFER;
+            next_nomoredata <= DAT_NO_MORE_DATA_IN;
+            next_unknown    <= DAT_UNKNOWN_ADDR_IN;
+            next_timeout    <= timeout_counter(c_regio_timeout_bit);
+          else
+            next_timeout_counter <= timeout_counter + 1;
           end if;
 
         when DAT_READ =>
           next_API_SEND_OUT <= '1';
           next_API_DATAREADY_OUT <= '1';
           case next_packet_counter is
-            when c_F0 => next_API_DATA_OUT <= address;
-            when c_F1 => next_API_DATA_OUT <= buf_DAT_DATA_IN(31 downto 16);
-            when c_F2 =>
-              next_API_DATA_OUT <= buf_DAT_DATA_IN(15 downto 0);
-            when c_F3 =>
-              next_API_DATA_OUT <= (others => '0');
-              if API_READ_IN = '1' then
-                next_state <= SEND_REPLY_DATA_finish;
-              end if;
+            when c_F0 =>  next_API_DATA_OUT <= address;
+            when c_F1 =>  next_API_DATA_OUT <= buf_DAT_DATA_IN(31 downto 16);
+            when c_F2 =>  next_API_DATA_OUT <= buf_DAT_DATA_IN(15 downto 0);
+            when c_F3 =>  next_API_DATA_OUT <= (others => '0');
+                          if API_READ_IN = '1' then
+                            next_state <= SEND_REPLY_DATA_finish;
+                          end if;
             when others => null;
           end case;
 
+        when SEND_RW_ERROR =>
+          next_API_SEND_OUT <= '1';
+          next_API_DATAREADY_OUT <= '1';
+          case next_packet_counter is
+            when c_F0 => next_API_DATA_OUT <= address;
+            when c_F1 => next_API_DATA_OUT <= dat_data_counter;
+            when c_F2 => next_API_DATA_OUT <= (others => '0');
+            when c_F3 => next_API_DATA_OUT <= (others => '0');
+                         if API_READ_IN = '1' then
+                           next_state <= SEND_REPLY_DATA_finish;
+                         end if;
+            when others => null;
+          end case;
         when others =>
-          next_state <= IDLE;
-      end case;
+                  next_state <= IDLE;
+     end case;
    end process;
 
 
@@ -574,14 +641,16 @@ begin
           length <= (others => '0');
           dont_understand <= '0';
           addr_counter_enable <= '0';
+          timeout_counter <= (others => '0');
+          timeout <= '0';
+          unknown <= '0';
+          nomoredata <= '0';
+          buf_API_READ_OUT <= '0';
         else
           current_state <= next_state;
---           HDR_F0 <= next_HDR_F0;
---           HDR_F1 <= next_HDR_F1;
---           HDR_F2 <= next_HDR_F2;
---           HDR_F3 <= next_HDR_F3;
           buf_API_SEND_OUT <= next_API_SEND_OUT;
           buf_API_SHORT_TRANSFER_OUT <= next_API_SHORT_TRANSFER_OUT;
+          buf_API_READ_OUT <= next_API_READ_OUT;
           address <= next_address;
           saved_Reg_high <= next_Reg_high;
           saved_Reg_low  <= next_Reg_low;
@@ -594,11 +663,17 @@ begin
           length <= next_length;
           dont_understand <= next_dont_understand;
           addr_counter_enable <= next_addr_counter_enable;
+          timeout_counter <= next_timeout_counter;
+          timeout <= next_timeout;
+          unknown <= next_unknown;
+          nomoredata <= next_nomoredata;
+          dat_data_counter <= next_dat_data_counter;
         end if;
       end if;
     end process;
 
 
+--generate packet numbers
   reg_packet_counter : process(CLK)
     begin
       if rising_edge(CLK) then
@@ -610,7 +685,6 @@ begin
       end if;
     end process;
 
-
   next_packet_counter_proc : process(API_READ_IN, buf_API_DATAREADY_OUT, packet_counter)
     begin
       if buf_API_DATAREADY_OUT = '1' and API_READ_IN = '1' then
@@ -637,21 +711,35 @@ begin
       end if;
     end process;
 
+--save Dataready_in in case API can not read immediately
+  process(CLK)
+    begin
+      if rising_edge(CLK) then
+        if RESET = '1' then
+          DAT_DATAREADY_IN_before <= '0';
+        elsif DAT_DATAREADY_IN = '1' then
+          DAT_DATAREADY_IN_before <= '1';
+        elsif API_READ_IN = '1' and buf_API_DATAREADY_OUT = '1' then
+          DAT_DATAREADY_IN_before <= '0';
+        end if;
+      end if;
+    end process;
+
 
   gen_regout : for i in 0 to 2**(NUM_CTRL_REGS)-1 generate
-    gen_regoutff1 : for j in i*c_REGIO_REGISTER_WIDTH to (i+1)*c_REGIO_REGISTER_WIDTH-1 generate
+    gen_regoutff1 : for j in i*c_REGIO_REG_WIDTH to (i+1)*c_REGIO_REG_WIDTH-1 generate
       gen_regoutff : if USED_CTRL_REGS(i) = '1' and USED_CTRL_BITMASK(j) = '1' generate
         process(CLK)
-          variable tmp : std_logic_vector(c_REGIO_REGISTER_WIDTH-1 downto 0);
+          variable tmp : std_logic_vector(c_REGIO_REG_WIDTH-1 downto 0);
           begin
             if rising_edge(CLK) then
               if RESET = '1' then
                 buf_REGISTERS_OUT(j)  <= INIT_CTRL_REGS(j);
               elsif REGISTERS_OUT_write_enable(i) = '1' then
                 tmp := saved_Reg_high & saved_Reg_low;
-                buf_REGISTERS_OUT(j) <= tmp(j-i*c_REGIO_REGISTER_WIDTH);
+                buf_REGISTERS_OUT(j) <= tmp(j-i*c_REGIO_REG_WIDTH);
               elsif EXT_REG_WRITE_IN = '1' and EXT_REG_ADDR_IN = (conv_std_logic_vector(i,8) or x"D0") then
-                buf_REGISTERS_OUT(j) <= EXT_REG_DATA_IN(j-i*c_REGIO_REGISTER_WIDTH);
+                buf_REGISTERS_OUT(j) <= EXT_REG_DATA_IN(j-i*c_REGIO_REG_WIDTH);
               end if;
             end if;
           end process;
@@ -663,18 +751,18 @@ begin
   end generate;
 
   gen_cregout : for i in 0 to std_COMCTRLREG-1 generate
-    gen_cregoutff1 : for j in i*c_REGIO_REGISTER_WIDTH to (i+1)*c_REGIO_REGISTER_WIDTH-1 generate
+    gen_cregoutff1 : for j in i*c_REGIO_REG_WIDTH to (i+1)*c_REGIO_REG_WIDTH-1 generate
       process(CLK)
-        variable tmp : std_logic_vector(c_REGIO_REGISTER_WIDTH-1 downto 0);
+        variable tmp : std_logic_vector(c_REGIO_REG_WIDTH-1 downto 0);
         begin
           if rising_edge(CLK) then
             if RESET = '1' then
               buf_COMMON_CTRL_REG_OUT(j)  <= '0';
             elsif COMMON_REGISTERS_OUT_write_enable(i) = '1' then
               tmp := saved_Reg_high & saved_Reg_low;
-              buf_COMMON_CTRL_REG_OUT(j) <= tmp(j-i*c_REGIO_REGISTER_WIDTH);
+              buf_COMMON_CTRL_REG_OUT(j) <= tmp(j-i*c_REGIO_REG_WIDTH);
             elsif EXT_REG_WRITE_IN = '1' and EXT_REG_ADDR_IN = (conv_std_logic_vector(i,8) or x"20") then
-              buf_COMMON_CTRL_REG_OUT(j) <= EXT_REG_DATA_IN(j-i*c_REGIO_REGISTER_WIDTH);
+              buf_COMMON_CTRL_REG_OUT(j) <= EXT_REG_DATA_IN(j-i*c_REGIO_REG_WIDTH);
             end if;
           end if;
         end process;
@@ -698,13 +786,13 @@ begin
         elsif EXT_REG_ADDR_IN(7 downto 6) = "01" then
           EXT_REG_DATA_OUT <= (others => '0');
         elsif EXT_REG_ADDR_IN(7 downto 6) = "10" then
-          EXT_REG_DATA_OUT <= REGISTERS_IN(regnum_STAT*c_REGIO_REGISTER_WIDTH+31 downto regnum_STAT*c_REGIO_REGISTER_WIDTH);
+          EXT_REG_DATA_OUT <= REGISTERS_IN(regnum_STAT*c_REGIO_REG_WIDTH+31 downto regnum_STAT*c_REGIO_REG_WIDTH);
         elsif EXT_REG_ADDR_IN(7 downto 6) = "11" then
-          EXT_REG_DATA_OUT <= buf_REGISTERS_OUT(regnum_CTRL*c_REGIO_REGISTER_WIDTH+31 downto regnum_CTRL*c_REGIO_REGISTER_WIDTH);
+          EXT_REG_DATA_OUT <= buf_REGISTERS_OUT(regnum_CTRL*c_REGIO_REG_WIDTH+31 downto regnum_CTRL*c_REGIO_REG_WIDTH);
         elsif EXT_REG_ADDR_IN(5) = '0' then
-          EXT_REG_DATA_OUT <= COMMON_STAT_REG_IN(regnum_cSTAT*c_REGIO_REGISTER_WIDTH+31 downto regnum_cSTAT*c_REGIO_REGISTER_WIDTH);
+          EXT_REG_DATA_OUT <= COMMON_STAT_REG_IN(regnum_cSTAT*c_REGIO_REG_WIDTH+31 downto regnum_cSTAT*c_REGIO_REG_WIDTH);
         else --if EXT_CTRL_ADDR_IN(5) = '1' then
-          EXT_REG_DATA_OUT <= buf_COMMON_CTRL_REG_OUT(regnum_cCTRL*c_REGIO_REGISTER_WIDTH+31 downto regnum_cCTRL*c_REGIO_REGISTER_WIDTH);
+          EXT_REG_DATA_OUT <= buf_COMMON_CTRL_REG_OUT(regnum_cCTRL*c_REGIO_REG_WIDTH+31 downto regnum_cCTRL*c_REGIO_REG_WIDTH);
         end if;
       end if;
     end process;
@@ -721,6 +809,17 @@ begin
     end process;
 
 
+  --combine read_out of regio and addresses
+  process(current_state, ADR_READ_OUT, buf_API_READ_OUT)
+    begin
+      if current_state = ADDRESS_RECV then
+        combined_API_READ_OUT <= ADR_READ_OUT;
+      else
+        combined_API_READ_OUT <= buf_API_READ_OUT;
+      end if;
+    end process;
+
+
   board_rom : rom_16x8
     generic map(
       INIT0 => COMPILE_TIME(15 downto 0),
@@ -738,12 +837,15 @@ begin
       dout    => rom_read_dout
       );
 
-
-  buf_API_ERROR_PATTERN_OUT(31 downto 5) <= (others => '0');
+  buf_API_ERROR_PATTERN_OUT(31 downto 19) <= (others => '0');
+  buf_API_ERROR_PATTERN_OUT(18) <= nomoredata;
+  buf_API_ERROR_PATTERN_OUT(17) <= timeout;
+  buf_API_ERROR_PATTERN_OUT(16) <= unknown;
+  buf_API_ERROR_PATTERN_OUT(15 downto 5) <= (others => '0');
   buf_API_ERROR_PATTERN_OUT(4) <= dont_understand;
   buf_API_ERROR_PATTERN_OUT(3 downto 0) <= (others => '0');
 
-  API_READ_OUT       <= buf_API_READ_OUT;
+  API_READ_OUT       <= combined_API_READ_OUT;
   API_SEND_OUT       <= buf_API_SEND_OUT;
   API_DATAREADY_OUT      <= buf_API_DATAREADY_OUT;
   API_PACKET_NUM_OUT <= buf_API_PACKET_NUM_OUT;
@@ -755,6 +857,7 @@ begin
   DAT_READ_ENABLE_OUT    <= buf_DAT_READ_ENABLE_OUT;
   DAT_WRITE_ENABLE_OUT   <= buf_DAT_WRITE_ENABLE_OUT;
   DAT_ADDR_OUT           <= buf_DAT_ADDR_OUT;
+  DAT_TIMEOUT_OUT        <= timeout;
   REGISTERS_OUT          <= buf_REGISTERS_OUT;
   COMMON_CTRL_REG_OUT    <= buf_COMMON_CTRL_REG_OUT;
 
index 854a9ea259add1b070a59f571672d9fa1e859290..5e452fa54e918205667cd1cc9f33bc052e46996c 100644 (file)
@@ -102,6 +102,8 @@ package trb_net_std is
   constant std_COMneededwidth : integer := 1;
   constant c_REGIO_ADDRESS_WIDTH : integer := 16;
   constant c_REGIO_REGISTER_WIDTH : integer := 32;
+  constant c_REGIO_REG_WIDTH : integer := 32;
+  constant c_regio_timeout_bit : integer := 5;
 
 --RegIO operation dtype
   constant c_network_control_type : std_logic_vector(3 downto 0) := x"F";