]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
initial version of the (yet incomplete) read-out handler for cbmnet
authorManuel Penschuck <manuel.penschuck@stud.uni-frankfurt.de>
Mon, 30 Jun 2014 14:19:59 +0000 (16:19 +0200)
committerManuel Penschuck <manuel.penschuck@stud.uni-frankfurt.de>
Mon, 30 Jun 2014 14:19:59 +0000 (16:19 +0200)
cbmnet/code/cbmnet_interface_pkg.vhd
cbmnet/code/cbmnet_readout.vhd [new file with mode: 0644]
cbmnet/code/cbmnet_readout_fifo.vhd [new file with mode: 0644]
cbmnet/code/cbmnet_readout_tx_fsm.vhd [new file with mode: 0644]
cbmnet/code/tb_cbmnet_fifotx.vhd [new file with mode: 0644]
cbmnet/code/tb_cbmnet_readout_fifo.vhd [new file with mode: 0644]

index 4d0111aa0738b601b10f3b259733931e446e6747..c36532eae3bfa20d44a1233c7e1715f91ee2fa1d 100644 (file)
@@ -1,4 +1,4 @@
--- Hardware Independent CBMNet components (merely an interface definition for the Verilog modules)
+-- Hardware Independent CBMNet components 
 
 library ieee;
    use ieee.std_logic_1164.all;
@@ -304,6 +304,148 @@ package cbmnet_interface_pkg is
          ctrl_rec_stop : out std_logic
       );
    end component;
+   
+   component CBMNET_READOUT_FIFO is
+      generic (
+         ADDR_WIDTH : positive := 10;
+         WATERMARK  : positive := 2
+      );
+
+      port (
+         -- write port
+         WCLK_IN   : in std_logic; -- not faster than rclk_in
+         WRESET_IN : in std_logic;
+         
+         WADDR_STORE_IN   : in std_logic;
+         WADDR_RESTORE_IN : in std_logic;
+         
+         WDATA_IN    : in std_logic_vector(17 downto 0);
+         WENQUEUE_IN : in std_logic;
+         WPACKET_COMPLETE_IN : in std_logic;
+         
+         WALMOST_FULL_OUT : out std_logic;
+         WFULL_OUT        : out std_logic;
+         
+         -- read port
+         RCLK_IN   : in std_logic;
+         RRESET_IN : in std_logic;  -- has to active at least two clocks AFTER (or while) write port was (is being) initialised
+         
+         RDATA_OUT   : out std_logic_vector(17 downto 0);
+         RDEQUEUE_IN : in std_logic;
+         
+         RPACKET_COMPLETE_OUT : out std_logic;   -- atleast one packet is completed in fifo
+         RPACKET_COMPLETE_ACK_IN : in std_logic -- mark one event as dealt with (effectively decrease number of completed packets by one)
+      );
+   end component;
+   
+  
+   component CBMNET_READOUT_TX_FSM is
+      port (
+         CLK_IN   : in std_logic;
+         RESET_IN : in std_logic; 
+
+         -- fifo 
+         FIFO_DATA_IN   : in std_logic_vector(15 downto 0);
+         FIFO_DEQUEUE_OUT : out std_logic;
+         FIFO_PACKET_COMPLETE_IN : in std_logic;  
+         FIFO_PACKET_COMPLETE_ACK_OUT : out std_logic;
+
+         -- cbmnet
+         CBMNET_STOP_IN   : in std_logic;
+         CBMNET_START_OUT : out std_logic;
+         CBMNET_END_OUT   : out std_logic;
+         CBMNET_DATA_OUT  : out std_logic_vector(15 downto 0)
+      );
+   end component;
+   
+   component CBMNET_READOUT_FIFO is
+      generic (
+         ADDR_WIDTH : positive := 10;
+         WATERMARK  : positive := 2
+      );
+
+      port (
+         -- write port
+         WCLK_IN   : in std_logic; -- not faster than rclk_in
+         WRESET_IN : in std_logic;
+         
+         WADDR_STORE_IN   : in std_logic;
+         WADDR_RESTORE_IN : in std_logic;
+         
+         WDATA_IN    : in std_logic_vector(17 downto 0);
+         WENQUEUE_IN : in std_logic;
+         WPACKET_COMPLETE_IN : in std_logic;
+         
+         WALMOST_FULL_OUT : out std_logic;
+         WFULL_OUT        : out std_logic;
+         
+         -- read port
+         RCLK_IN   : in std_logic;
+         RRESET_IN : in std_logic;  -- has to active at least two clocks AFTER (or while) write port was (is being) initialised
+         
+         RDATA_OUT   : out std_logic_vector(17 downto 0);
+         RDEQUEUE_IN : in std_logic;
+         
+         RPACKET_COMPLETE_OUT : out std_logic;   -- atleast one packet is completed in fifo
+         RPACKET_COMPLETE_ACK_IN : in std_logic -- mark one event as dealt with (effectively decrease number of completed packets by one)
+      );
+   end component;
+
+   component CBMNET_READOUT is
+      port (
+      -- TrbNet
+         CLK_IN   : in std_logic;
+         RESET_IN : in std_logic;
+
+         -- connect to hub
+         HUB_CTS_NUMBER_IN              : in  std_logic_vector (15 downto 0);
+         HUB_CTS_CODE_IN                : in  std_logic_vector (7  downto 0);
+         HUB_CTS_INFORMATION_IN         : in  std_logic_vector (7  downto 0);
+         HUB_CTS_READOUT_TYPE_IN        : in  std_logic_vector (3  downto 0);
+         HUB_CTS_START_READOUT_IN       : in  std_logic;
+         HUB_CTS_READOUT_FINISHED_OUT   : out std_logic;  --no more data, end transfer, send TRM
+         HUB_CTS_STATUS_BITS_OUT        : out std_logic_vector (31 downto 0);
+         HUB_FEE_DATA_IN                : in  std_logic_vector (15 downto 0);
+         HUB_FEE_DATAREADY_IN           : in  std_logic;
+         HUB_FEE_READ_OUT               : out std_logic;  --must be high when idle, otherwise you will never get a dataready
+         HUB_FEE_STATUS_BITS_IN         : in  std_logic_vector (31 downto 0);
+         HUB_FEE_BUSY_IN                : in  std_logic;   
+
+         -- connect to GbE
+         GBE_CTS_NUMBER_OUT             : out std_logic_vector (15 downto 0);
+         GBE_CTS_CODE_OUT               : out std_logic_vector (7  downto 0);
+         GBE_CTS_INFORMATION_OUT        : out std_logic_vector (7  downto 0);
+         GBE_CTS_READOUT_TYPE_OUT       : out std_logic_vector (3  downto 0);
+         GBE_CTS_START_READOUT_OUT      : out std_logic;
+         GBE_CTS_READOUT_FINISHED_IN    : in  std_logic;      --no more data, end transfer, send TRM
+         GBE_CTS_STATUS_BITS_IN         : in  std_logic_vector (31 downto 0);
+         GBE_FEE_DATA_OUT               : out std_logic_vector (15 downto 0);
+         GBE_FEE_DATAREADY_OUT          : out std_logic;
+         GBE_FEE_READ_IN                : in  std_logic;  --must be high when idle, otherwise you will never get a dataready
+         GBE_FEE_STATUS_BITS_OUT        : out std_logic_vector (31 downto 0);
+         GBE_FEE_BUSY_OUT               : out std_logic;
+
+         -- reg io
+         REGIO_ADDR_IN                  : in  std_logic_vector(15 downto 0);
+         REGIO_DATA_IN                  : in  std_logic_vector(31 downto 0);
+         REGIO_READ_ENABLE_IN           : in  std_logic;
+         REGIO_WRITE_ENABLE_IN          : in  std_logic;
+         REGIO_DATA_OUT                 : out std_logic_vector(31 downto 0);
+         REGIO_DATAREADY_OUT            : out std_logic;
+         REGIO_WRITE_ACK_OUT            : out std_logic;
+         REGIO_UNKNOWN_ADDR_OUT         : out std_logic;
+
+      -- CBMNet
+         CBMNET_CLK_IN     : in std_logic;
+         CBMNET_RESET_IN   : in std_logic;
+         CBMNET_LINK_ACTIVE_IN : in std_logic;         
+
+         CBMNET_DATA2SEND_STOP_IN   : in std_logic;
+         CBMNET_DATA2SEND_START_OUT : out std_logic;
+         CBMNET_DATA2SEND_END_OUT   : out std_logic;
+         CBMNET_DATA2SEND_DATA_OUT  : out std_logic_vector(15 downto 0)
+      );
+   end component;
 end package cbmnet_interface_pkg;
 
 package body cbmnet_interface_pkg is
diff --git a/cbmnet/code/cbmnet_readout.vhd b/cbmnet/code/cbmnet_readout.vhd
new file mode 100644 (file)
index 0000000..c22bfc3
--- /dev/null
@@ -0,0 +1,65 @@
+library ieee;
+   use ieee.std_logic_1164.all;
+   use ieee.numeric_std.all;
+
+entity CBMNET_READOUT is
+   port (
+   -- TrbNet
+      CLK_IN   : in std_logic;
+      RESET_IN : in std_logic;
+
+      -- connect to hub
+      HUB_CTS_NUMBER_IN              : in  std_logic_vector (15 downto 0);
+      HUB_CTS_CODE_IN                : in  std_logic_vector (7  downto 0);
+      HUB_CTS_INFORMATION_IN         : in  std_logic_vector (7  downto 0);
+      HUB_CTS_READOUT_TYPE_IN        : in  std_logic_vector (3  downto 0);
+      HUB_CTS_START_READOUT_IN       : in  std_logic;
+      HUB_CTS_READOUT_FINISHED_OUT   : out std_logic;  --no more data, end transfer, send TRM
+      HUB_CTS_STATUS_BITS_OUT        : out std_logic_vector (31 downto 0);
+      HUB_FEE_DATA_IN                : in  std_logic_vector (15 downto 0);
+      HUB_FEE_DATAREADY_IN           : in  std_logic;
+      HUB_FEE_READ_OUT               : out std_logic;  --must be high when idle, otherwise you will never get a dataready
+      HUB_FEE_STATUS_BITS_IN         : in  std_logic_vector (31 downto 0);
+      HUB_FEE_BUSY_IN                : in  std_logic;   
+
+      -- connect to GbE
+      GBE_CTS_NUMBER_OUT             : out std_logic_vector (15 downto 0);
+      GBE_CTS_CODE_OUT               : out std_logic_vector (7  downto 0);
+      GBE_CTS_INFORMATION_OUT        : out std_logic_vector (7  downto 0);
+      GBE_CTS_READOUT_TYPE_OUT       : out std_logic_vector (3  downto 0);
+      GBE_CTS_START_READOUT_OUT      : out std_logic;
+      GBE_CTS_READOUT_FINISHED_IN    : in  std_logic;      --no more data, end transfer, send TRM
+      GBE_CTS_STATUS_BITS_IN         : in  std_logic_vector (31 downto 0);
+      GBE_FEE_DATA_OUT               : out std_logic_vector (15 downto 0);
+      GBE_FEE_DATAREADY_OUT          : out std_logic;
+      GBE_FEE_READ_IN                : in  std_logic;  --must be high when idle, otherwise you will never get a dataready
+      GBE_FEE_STATUS_BITS_OUT        : out std_logic_vector (31 downto 0);
+      GBE_FEE_BUSY_OUT               : out std_logic;
+
+      -- reg io
+      REGIO_ADDR_IN                  : in  std_logic_vector(15 downto 0);
+      REGIO_DATA_IN                  : in  std_logic_vector(31 downto 0);
+      REGIO_READ_ENABLE_IN           : in  std_logic;
+      REGIO_WRITE_ENABLE_IN          : in  std_logic;
+      REGIO_DATA_OUT                 : out std_logic_vector(31 downto 0);
+      REGIO_DATAREADY_OUT            : out std_logic;
+      REGIO_WRITE_ACK_OUT            : out std_logic;
+      REGIO_UNKNOWN_ADDR_OUT         : out std_logic;
+
+   -- CBMNet
+      CBMNET_CLK_IN     : in std_logic;
+      CBMNET_RESET_IN   : in std_logic;
+      CBMNET_LINK_ACTIVE_IN : in std_logic;
+
+      CBMNET_DATA2SEND_STOP_IN   : in std_logic;
+      CBMNET_DATA2SEND_START_OUT : out std_logic;
+      CBMNET_DATA2SEND_END_OUT   : out std_logic;
+      CBMNET_DATA2SEND_DATA_OUT  : out std_logic_vector(15 downto 0)
+   );
+end entity;
+
+architecture cbmnet_readout_arch of CBMNET_READOUT is
+begin
+
+end architecture;
+
diff --git a/cbmnet/code/cbmnet_readout_fifo.vhd b/cbmnet/code/cbmnet_readout_fifo.vhd
new file mode 100644 (file)
index 0000000..fb9b6e7
--- /dev/null
@@ -0,0 +1,160 @@
+library ieee;
+   use ieee.std_logic_1164.all;
+   use ieee.numeric_std.all;
+
+
+entity CBMNET_READOUT_FIFO is
+   generic (
+      ADDR_WIDTH : positive := 10;
+      WATERMARK  : positive := 2
+   );
+
+   port (
+      -- write port
+      WCLK_IN   : in std_logic; -- not faster than rclk_in
+      WRESET_IN : in std_logic;
+      
+      WADDR_STORE_IN   : in std_logic;
+      WADDR_RESTORE_IN : in std_logic;
+      
+      WDATA_IN    : in std_logic_vector(17 downto 0);
+      WENQUEUE_IN : in std_logic;
+      WPACKET_COMPLETE_IN : in std_logic;
+      
+      WALMOST_FULL_OUT : out std_logic;
+      WFULL_OUT        : out std_logic;
+      
+      -- read port
+      RCLK_IN   : in std_logic;
+      RRESET_IN : in std_logic;  -- has to active at least two clocks AFTER (or while) write port was (is being) initialised
+      
+      RDATA_OUT   : out std_logic_vector(17 downto 0);
+      RDEQUEUE_IN : in std_logic;
+      
+      RPACKET_COMPLETE_OUT : out std_logic;   -- atleast one packet is completed in fifo
+      RPACKET_COMPLETE_ACK_IN : in std_logic -- mark one event as dealt with (effectively decrease number of completed packets by one)
+   );
+end CBMNET_READOUT_FIFO;
+
+architecture cbmnet_readout_fifo_arch of CBMNET_READOUT_FIFO is
+   signal waddr_i, waddr_stored_i, wread_pointer_i, wwords_remaining_i : unsigned(ADDR_WIDTH-1 downto 0) := (others => '0');
+   signal wfull_i, walmost_full_i : std_logic;
+   signal wpacket_complete_xchange_i : std_logic := '0';
+   
+   signal raddr_i, raddr_stored_i, rwrite_pointer_i, rpacket_counter_i : unsigned(ADDR_WIDTH-1 downto 0) := (others => '0');
+   signal rpacket_complete_xchange_i : std_logic := '0'; 
+
+   type FIFO_MEM_T is array(0 to 2**ADDR_WIDTH-1) of std_logic_vector(17 downto 0);
+   signal mem_i : FIFO_MEM_T;
+begin
+-- Memory
+   MEM_WRITE_PORT: process is
+      variable last_full_v : std_logic := '1';
+   begin
+      wait until rising_edge(WCLK_IN);
+      if (wfull_i = '0' or last_full_v = '0') and WENQUEUE_IN = '1' then
+         mem_i(to_integer(waddr_i)) <= WDATA_IN;
+      end if;
+      
+      last_full_v := wfull_i;
+   end process;
+
+-- Read Port
+   raddr_stored_i <= waddr_stored_i when rising_edge(RCLK_IN);
+   rwrite_pointer_i <= waddr_i when rising_edge(RCLK_IN);
+   
+   RPROC_COMPLETE_COUNTER: process is
+      variable delta_v : unsigned(1 downto 0);
+   begin
+      wait until rising_edge(RCLK_IN);
+      delta_v := TO_UNSIGNED(1, delta_v'length);
+      rpacket_complete_xchange_i <= wpacket_complete_xchange_i;
+      RPACKET_COMPLETE_OUT <= '0';
+      
+      if RRESET_IN = '1' then
+         rpacket_counter_i <= (others => '0');
+      else
+         if RPACKET_COMPLETE_ACK_IN = '1' then
+            delta_v := TO_UNSIGNED(0, delta_v'length);
+         end if;
+      
+         if rpacket_complete_xchange_i /= wpacket_complete_xchange_i then
+            delta_v := delta_v + TO_UNSIGNED(1, delta_v'length);
+         end if;
+         
+         rpacket_counter_i <= rpacket_counter_i + delta_v -  TO_UNSIGNED(1, 1);
+         
+         if rpacket_counter_i /= 0 or delta_v = 2 then
+            RPACKET_COMPLETE_OUT <= '1';
+         end if;
+      end if;
+   end process;
+   
+   RPROC_ADDRESSING: process is
+      variable next_addr_v : unsigned(raddr_i'range);
+   begin
+      wait until rising_edge(RCLK_IN);
+      
+      next_addr_v := raddr_i;
+      
+      if RRESET_IN = '1' then
+         next_addr_v := raddr_stored_i;
+      else
+         if RDEQUEUE_IN = '1' and raddr_i + 1 /= rwrite_pointer_i then
+            next_addr_v := next_addr_v + 1;
+         end if;
+      end if;
+      
+      raddr_i <= next_addr_v;
+   end process;
+   RDATA_OUT <= mem_i(to_integer(raddr_i));
+
+-- Write Port
+   wread_pointer_i <= raddr_i when rising_edge(WCLK_IN);
+   WPROC_ADDRESSING: process is 
+   begin
+      wait until rising_edge(WCLK_IN);
+      if WADDR_RESTORE_IN = '1' then
+         waddr_i <= waddr_stored_i;
+      elsif wfull_i = '0' and WENQUEUE_IN = '1' then
+         waddr_i <= waddr_i + 1;
+      end if;
+   end process;
+
+   WPROC_STORE_ADDR: process is
+   begin
+      wait until rising_edge(WCLK_IN);
+      if WRESET_IN = '1' then
+         waddr_stored_i <= (others => '0');
+      elsif WADDR_STORE_IN = '1' then
+         waddr_stored_i <= waddr_i;
+      end if;
+   end process;
+
+   wwords_remaining_i <= wread_pointer_i - waddr_i - 1;
+   WPROC_FULL_INDICATOR: process(wwords_remaining_i) is
+   begin
+      wfull_i <= '0';
+      if wwords_remaining_i = 0 then
+         wfull_i <= '1';
+      end if;
+      
+      walmost_full_i <= '0';
+      if wwords_remaining_i < WATERMARK then
+         walmost_full_i <= '1';
+      end if;
+   end process;
+   
+   WPROC_PACKET_COMPLETE: process is
+      variable last_v : std_logic;
+   begin
+      wait until rising_edge(WCLK_IN);
+      if WPACKET_COMPLETE_IN = '1' and last_v = '0' then
+         wpacket_complete_xchange_i <= not wpacket_complete_xchange_i;
+      end if;
+      last_v := WPACKET_COMPLETE_IN;
+   end process;
+   
+   WALMOST_FULL_OUT <= walmost_full_i;
+   WFULL_OUT <= wfull_i;
+end architecture;
\ No newline at end of file
diff --git a/cbmnet/code/cbmnet_readout_tx_fsm.vhd b/cbmnet/code/cbmnet_readout_tx_fsm.vhd
new file mode 100644 (file)
index 0000000..00dbc03
--- /dev/null
@@ -0,0 +1,127 @@
+library ieee;
+   use ieee.std_logic_1164.all;
+   use ieee.numeric_std.all;
+
+
+entity CBMNET_READOUT_TX_FSM is
+   port (
+      CLK_IN   : in std_logic;
+      RESET_IN : in std_logic; 
+
+      -- fifo 
+      FIFO_DATA_IN   : in std_logic_vector(15 downto 0);
+      FIFO_DEQUEUE_OUT : out std_logic;
+      FIFO_PACKET_COMPLETE_IN : in std_logic;  
+      FIFO_PACKET_COMPLETE_ACK_OUT : out std_logic;
+
+      -- cbmnet
+      CBMNET_STOP_IN   : in std_logic;
+      CBMNET_START_OUT : out std_logic;
+      CBMNET_END_OUT   : out std_logic;
+      CBMNET_DATA_OUT  : out std_logic_vector(15 downto 0)
+   );
+end entity;
+
+architecture cbmnet_readout_tx_fsm_arch of CBMNET_READOUT_TX_FSM is
+   constant PAYLOAD_PER_PACKET_C : integer := 62; -- bytes
+
+
+   type FSM_STATES_T is (WAIT_FOR_COMPL_PACKET, READ_LENGTH_H, SETUP_TRANSACTION, SEND_HEADER, SEND_PAYLOAD, FINISH_TRANSACTION);
+   signal fsm_i : FSM_STATES_T;
+   
+   signal trans_length_high_i : std_logic_vector(15 downto 0);
+   signal trans_remaining_length_i : unsigned(15 downto 0);
+   
+   signal pack_num_i : unsigned(10 downto 0);
+   signal pack_payload_words_i : unsigned(4 downto 0);
+   
+   signal pack_start_i, pack_stop_i : std_logic;
+begin
+   PROC_TX_CNTL: process is 
+   begin
+      wait until rising_edge(CLK_IN);
+      
+      CBMNET_START_OUT <= '0';
+      CBMNET_END_OUT <= '0';
+      CBMNET_DATA_OUT <= FIFO_DATA_IN;
+      
+      FIFO_DEQUEUE_OUT <= '0';
+      FIFO_PACKET_COMPLETE_ACK_OUT <= '0';
+      
+      if RESET_IN = '1' then
+         fsm_i <= WAIT_FOR_COMPL_PACKET;
+      else
+         case(fsm_i) is
+            when WAIT_FOR_COMPL_PACKET =>
+               if FIFO_PACKET_COMPLETE_IN = '1' then
+                  fsm_i <= READ_LENGTH_H;
+                  FIFO_DEQUEUE_OUT <= '1';
+               end if;
+               
+            when READ_LENGTH_H =>
+               trans_length_high_i <= FIFO_DATA_IN(15 downto 0);
+               fsm_i <= SETUP_TRANSACTION;
+            
+            when SETUP_TRANSACTION =>
+               trans_remaining_length_i <= UNSIGNED(FIFO_DATA_IN(15 downto 0));
+               pack_start_i <= '1';
+               pack_num_i <= (others => '0');
+               fsm_i <= SEND_HEADER;
+            
+            when SEND_HEADER =>
+               if CBMNET_STOP_IN = '0' then
+                  CBMNET_DATA_OUT(10 downto 0) <= STD_LOGIC_VECTOR(pack_num_i);
+                  CBMNET_DATA_OUT(14) <= pack_start_i;
+                  CBMNET_DATA_OUT(15) <= pack_stop_i;
+                  CBMNET_START_OUT <= '1';
+
+                  if trans_remaining_length_i < PAYLOAD_PER_PACKET_C then
+                     -- TODO: i dont think that odd packet lengths are supported by TrbNet, but check it !
+                     pack_payload_words_i <= UNSIGNED(trans_remaining_length_i(pack_payload_words_i'high + 1 downto 1));
+                  else
+                     pack_payload_words_i <= TO_UNSIGNED(PAYLOAD_PER_PACKET_C / 2, pack_payload_words_i'length);
+                  end if;
+               
+                  FIFO_DEQUEUE_OUT <= not pack_start_i;
+                  fsm_i <= SEND_PAYLOAD;
+               end if;
+            
+            when SEND_PAYLOAD =>
+               if pack_start_i = '1' then
+                  CBMNET_DATA_OUT <= trans_length_high_i;
+                  FIFO_DEQUEUE_OUT <= '1';
+                  
+               else
+                  if pack_payload_words_i = 1 then
+                     CBMNET_END_OUT <= '1';
+                     pack_num_i <= pack_num_i + 1;
+                     
+                     if trans_remaining_length_i = 2 then
+                        fsm_i <= FINISH_TRANSACTION;
+                     else
+                        fsm_i <= SEND_HEADER;
+                     end if;
+                     
+                  else
+                     FIFO_DEQUEUE_OUT <= '1';
+                  end if;
+               end if;
+               
+               pack_start_i <= '0';
+               pack_payload_words_i <= pack_payload_words_i - 1;
+               trans_remaining_length_i <= trans_remaining_length_i - 2;
+            
+            when FINISH_TRANSACTION =>
+               FIFO_PACKET_COMPLETE_ACK_OUT <= '1';
+               fsm_i <= WAIT_FOR_COMPL_PACKET;
+         
+         end case;
+      end if;
+   end process;
+
+
+
+
+   pack_stop_i <= '1' when trans_remaining_length_i < PAYLOAD_PER_PACKET_C else '0';
+end architecture;
+
diff --git a/cbmnet/code/tb_cbmnet_fifotx.vhd b/cbmnet/code/tb_cbmnet_fifotx.vhd
new file mode 100644 (file)
index 0000000..0c64cff
--- /dev/null
@@ -0,0 +1,139 @@
+library ieee;
+   use ieee.std_logic_1164.all;
+   use ieee.numeric_std.all;
+   use work.cbmnet_interface_pkg.all;
+
+entity tb_cbmnet_fifotx is
+end tb_cbmnet_fifotx;
+
+architecture TB of tb_cbmnet_fifotx is
+   constant ADDR_WIDTH : positive := 16;
+   constant WATERMARK  : positive := 2;
+
+-- write port
+   signal WCLK_IN   : std_logic := '0'; -- not faster than rclk_in
+   signal WRESET_IN : std_logic := '0';
+   
+   signal WADDR_STORE_IN   : std_logic := '0';
+   signal WADDR_RESTORE_IN : std_logic := '0';
+   
+   signal WDATA_IN    : std_logic_vector(17 downto 0);
+   signal WENQUEUE_IN : std_logic:= '0';
+   signal WPACKET_COMPLETE_IN : std_logic:= '0';
+   
+   signal WALMOST_FULL_OUT : std_logic;
+   signal WFULL_OUT        : std_logic;
+   
+   -- read port
+   signal RCLK_IN   : std_logic := '0';
+   signal RRESET_IN : std_logic:= '0';  -- has to active at least two clocks AFTER (or while) write port was (is being) initialised
+   
+   signal RDATA_OUT   : std_logic_vector(17 downto 0);
+   signal RDEQUEUE_IN : std_logic:= '0';
+   
+   signal RPACKET_COMPLETE_OUT : std_logic;   -- atleast one packet is completed fifo
+   signal RPACKET_COMPLETE_ACK_IN : std_logic:= '0'; -- mark one event as dealt with (effectively decrease number of completed packets by one)
+
+   signal CBMNET_STOP_IN, CBMNET_START_OUT, CBMNET_END_OUT : std_logic := '0';
+   signal CBMNET_DATA_OUT : std_logic_vector(15 downto 0);
+   
+begin
+   WCLK_IN <= not WCLK_IN after 5 ns;
+   RCLK_IN <= not RCLK_IN after 4 ns;
+
+   WPROC: process is
+      variable length : integer range 0 to 1024;
+   begin
+      WDATA_IN <= (others => '0');
+      
+      WRESET_IN <= '1'; wait for 20 ns; wait until rising_edge(WCLK_IN);
+      WRESET_IN <= '0'; wait until rising_edge(WCLK_IN);
+      
+      WENQUEUE_IN <= '1';
+      for j in 0 to 10 loop
+         length := 100 + j * 50;
+      
+         WDATA_IN(15 downto 0) <= x"0000";
+         wait until rising_edge(WCLK_IN);
+         WDATA_IN(15 downto 0) <= STD_LOGIC_VECTOR(TO_UNSIGNED(length + 4, 16)) ;
+         wait until rising_edge(WCLK_IN);
+      
+         for i in 1 to length / 2 loop
+            WDATA_IN(15 downto 0) <= STD_LOGIC_VECTOR( TO_UNSIGNED(j, 8) ) &  STD_LOGIC_VECTOR ( TO_UNSIGNED(i, 8) );
+            WPACKET_COMPLETE_IN <= '0';
+            if i = length / 2 then
+               WPACKET_COMPLETE_IN <= '1';
+            end if;
+            wait until rising_edge(WCLK_IN);
+         end loop;
+         WPACKET_COMPLETE_IN <= '0';
+
+      end loop;
+
+      
+      wait;
+   end process;
+   
+   RPROC: process is
+   begin
+      RRESET_IN <= '1';
+      wait for 50 ns;
+      RRESET_IN <= '0';
+      
+      wait;
+   end process;
+   
+   process is begin
+      wait until rising_edge(CBMNET_END_OUT);
+      CBMNET_STOP_IN <= '1';
+      wait for 32 ns;
+      CBMNET_STOP_IN <= '0';
+   end process;
+   
+   FIFO: cbmnet_readout_fifo 
+   generic map (
+      ADDR_WIDTH => ADDR_WIDTH,
+      WATERMARK  => WATERMARK
+   ) port map (
+   -- write port
+      WCLK_IN => WCLK_IN,
+      WRESET_IN => WRESET_IN,
+            
+      WADDR_STORE_IN => WADDR_STORE_IN,
+      WADDR_RESTORE_IN => WADDR_RESTORE_IN,
+            
+      WDATA_IN => WDATA_IN,
+      WENQUEUE_IN => WENQUEUE_IN,
+      WPACKET_COMPLETE_IN => WPACKET_COMPLETE_IN,
+            
+      WALMOST_FULL_OUT => WALMOST_FULL_OUT,
+      WFULL_OUT => WFULL_OUT,
+         
+   -- read port
+      RCLK_IN => RCLK_IN,
+      RRESET_IN => RRESET_IN,
+            
+      RDATA_OUT => RDATA_OUT,
+      RDEQUEUE_IN => RDEQUEUE_IN,
+            
+      RPACKET_COMPLETE_OUT => RPACKET_COMPLETE_OUT,
+      RPACKET_COMPLETE_ACK_IN => RPACKET_COMPLETE_ACK_IN
+   );
+   
+   TX_FSM: cbmnet_readout_tx_fsm port map (
+      CLK_IN   => RCLK_IN,
+      RESET_IN => RRESET_IN,
+
+      -- fifo 
+      FIFO_DATA_IN   => RDATA_OUT(15 downto 0),
+      FIFO_DEQUEUE_OUT => RDEQUEUE_IN,
+      FIFO_PACKET_COMPLETE_IN => RPACKET_COMPLETE_OUT,
+      FIFO_PACKET_COMPLETE_ACK_OUT => RPACKET_COMPLETE_ACK_IN,
+
+      -- cbmnet
+      CBMNET_STOP_IN   => CBMNET_STOP_IN,
+      CBMNET_START_OUT => CBMNET_START_OUT,
+      CBMNET_END_OUT   => CBMNET_END_OUT,
+      CBMNET_DATA_OUT  => CBMNET_DATA_OUT
+   );
+end architecture;
\ No newline at end of file
diff --git a/cbmnet/code/tb_cbmnet_readout_fifo.vhd b/cbmnet/code/tb_cbmnet_readout_fifo.vhd
new file mode 100644 (file)
index 0000000..b82ba69
--- /dev/null
@@ -0,0 +1,129 @@
+library ieee;
+   use ieee.std_logic_1164.all;
+   use ieee.numeric_std.all;
+   use work.cbmnet_interface_pkg.all;
+
+entity tb_cbmnet_readout_fifo is
+end tb_cbmnet_readout_fifo;
+
+architecture TB of tb_cbmnet_readout_fifo is
+   constant ADDR_WIDTH : positive := 4;
+   constant WATERMARK  : positive := 2;
+
+-- write port
+   signal WCLK_IN   : std_logic := '0'; -- not faster than rclk_in
+   signal WRESET_IN : std_logic := '0';
+   
+   signal WADDR_STORE_IN   : std_logic := '0';
+   signal WADDR_RESTORE_IN : std_logic := '0';
+   
+   signal WDATA_IN    : std_logic_vector(17 downto 0);
+   signal WENQUEUE_IN : std_logic:= '0';
+   signal WPACKET_COMPLETE_IN : std_logic:= '0';
+   
+   signal WALMOST_FULL_OUT : std_logic;
+   signal WFULL_OUT        : std_logic;
+   
+   -- read port
+   signal RCLK_IN   : std_logic := '0';
+   signal RRESET_IN : std_logic:= '0';  -- has to active at least two clocks AFTER (or while) write port was (is being) initialised
+   
+   signal RDATA_OUT   : std_logic_vector(17 downto 0);
+   signal RDEQUEUE_IN : std_logic:= '0';
+   
+   signal RPACKET_COMPLETE_OUT : std_logic;   -- atleast one packet is completed fifo
+   signal RPACKET_COMPLETE_ACK_IN : std_logic:= '0'; -- mark one event as dealt with (effectively decrease number of completed packets by one)
+
+begin
+   WCLK_IN <= not WCLK_IN after 5 ns;
+   RCLK_IN <= not RCLK_IN after 4 ns;
+
+   WPROC: process is
+   begin
+      WRESET_IN <= '1'; wait for 20 ns; wait until rising_edge(WCLK_IN);
+      WRESET_IN <= '0'; wait until rising_edge(WCLK_IN);
+      
+      for i in 3*2**ADDR_WIDTH downto 0 loop
+         WDATA_IN <= STD_LOGIC_VECTOR(TO_UNSIGNED(i, WDATA_IN'length));
+         WENQUEUE_IN <= '1';
+         
+         WADDR_STORE_IN <= '0';
+         if i = 3*2**ADDR_WIDTH - (2**(ADDR_WIDTH-1)) then
+            WADDR_STORE_IN <= '1';
+         end if;
+         WADDR_RESTORE_IN <= '0';
+         if i = 2*2**ADDR_WIDTH then
+            WADDR_RESTORE_IN <= '1';
+         end if;
+         
+         wait until rising_edge(WCLK_IN);
+      end loop;
+
+      WENQUEUE_IN <= '0';
+
+      
+      wait;
+   end process;
+   
+   RPROC: process is
+   begin
+      RRESET_IN <= '1';
+      wait for 50 ns;
+      RRESET_IN <= '0';
+      
+      wait for 250 ns;
+      
+      RDEQUEUE_IN <= '1';
+      wait until rising_edge(RCLK_IN);
+      wait until rising_edge(RCLK_IN);
+      RDEQUEUE_IN <= '0';
+      wait until rising_edge(RCLK_IN);
+
+      RRESET_IN <= '1';
+      wait until rising_edge(RCLK_IN);
+      RRESET_IN <= '0';
+
+      wait until rising_edge(RCLK_IN);
+      wait until rising_edge(RCLK_IN);
+      wait until rising_edge(RCLK_IN);
+      
+      RDEQUEUE_IN <= '1';
+      
+      wait;
+   end process;
+   
+      
+      
+   
+
+
+   DUT: cbmnet_readout_fifo 
+   generic map (
+      ADDR_WIDTH => ADDR_WIDTH,
+      WATERMARK  => WATERMARK
+   ) port map (
+   -- write port
+      WCLK_IN => WCLK_IN,
+      WRESET_IN => WRESET_IN,
+            
+      WADDR_STORE_IN => WADDR_STORE_IN,
+      WADDR_RESTORE_IN => WADDR_RESTORE_IN,
+            
+      WDATA_IN => WDATA_IN,
+      WENQUEUE_IN => WENQUEUE_IN,
+      WPACKET_COMPLETE_IN => WPACKET_COMPLETE_IN,
+            
+      WALMOST_FULL_OUT => WALMOST_FULL_OUT,
+      WFULL_OUT => WFULL_OUT,
+         
+   -- read port
+      RCLK_IN => RCLK_IN,
+      RRESET_IN => RRESET_IN,
+            
+      RDATA_OUT => RDATA_OUT,
+      RDEQUEUE_IN => RDEQUEUE_IN,
+            
+      RPACKET_COMPLETE_OUT => RPACKET_COMPLETE_OUT,
+      RPACKET_COMPLETE_ACK_IN => RPACKET_COMPLETE_ACK_IN
+   );
+end architecture;
\ No newline at end of file