From 46582612c0eef27aa98f7d6249873beb91ccf27c Mon Sep 17 00:00:00 2001 From: Manuel Penschuck Date: Mon, 30 Jun 2014 16:19:59 +0200 Subject: [PATCH] initial version of the (yet incomplete) read-out handler for cbmnet --- cbmnet/code/cbmnet_interface_pkg.vhd | 144 +++++++++++++++++++++- cbmnet/code/cbmnet_readout.vhd | 65 ++++++++++ cbmnet/code/cbmnet_readout_fifo.vhd | 160 +++++++++++++++++++++++++ cbmnet/code/cbmnet_readout_tx_fsm.vhd | 127 ++++++++++++++++++++ cbmnet/code/tb_cbmnet_fifotx.vhd | 139 +++++++++++++++++++++ cbmnet/code/tb_cbmnet_readout_fifo.vhd | 129 ++++++++++++++++++++ 6 files changed, 763 insertions(+), 1 deletion(-) create mode 100644 cbmnet/code/cbmnet_readout.vhd create mode 100644 cbmnet/code/cbmnet_readout_fifo.vhd create mode 100644 cbmnet/code/cbmnet_readout_tx_fsm.vhd create mode 100644 cbmnet/code/tb_cbmnet_fifotx.vhd create mode 100644 cbmnet/code/tb_cbmnet_readout_fifo.vhd diff --git a/cbmnet/code/cbmnet_interface_pkg.vhd b/cbmnet/code/cbmnet_interface_pkg.vhd index 4d0111a..c36532e 100644 --- a/cbmnet/code/cbmnet_interface_pkg.vhd +++ b/cbmnet/code/cbmnet_interface_pkg.vhd @@ -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 index 0000000..c22bfc3 --- /dev/null +++ b/cbmnet/code/cbmnet_readout.vhd @@ -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 index 0000000..fb9b6e7 --- /dev/null +++ b/cbmnet/code/cbmnet_readout_fifo.vhd @@ -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 index 0000000..00dbc03 --- /dev/null +++ b/cbmnet/code/cbmnet_readout_tx_fsm.vhd @@ -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 index 0000000..0c64cff --- /dev/null +++ b/cbmnet/code/tb_cbmnet_fifotx.vhd @@ -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 index 0000000..b82ba69 --- /dev/null +++ b/cbmnet/code/tb_cbmnet_readout_fifo.vhd @@ -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 -- 2.43.0