--- Hardware Independent CBMNet components (merely an interface definition for the Verilog modules)
+-- Hardware Independent CBMNet components
library ieee;
use ieee.std_logic_1164.all;
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
--- /dev/null
+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;
+
--- /dev/null
+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
--- /dev/null
+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;
+
--- /dev/null
+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
--- /dev/null
+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