--- /dev/null
+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 cri_data_sender is
+ port(
+ -- Misc
+ CLK : in std_logic;
+ RESET : in std_logic;
+ CLK_EN : in std_logic;
+ -- Port to API
+ API_DATA_OUT : out std_logic_vector (c_DATA_WIDTH-1 downto 0);
+ API_PACKET_NUM_OUT : out std_logic_vector (c_NUM_WIDTH-1 downto 0);
+ API_DATAREADY_OUT : out std_logic;
+ API_READ_IN : in std_logic;
+ API_SHORT_TRANSFER_OUT : out std_logic;
+ API_DTYPE_OUT : out std_logic_vector (3 downto 0);
+ API_ERROR_PATTERN_OUT : out std_logic_vector (31 downto 0);
+ API_SEND_OUT : out std_logic;
+ -- Receiver port
+ API_DATA_IN : in std_logic_vector (c_DATA_WIDTH-1 downto 0);
+ API_PACKET_NUM_IN : in std_logic_vector (c_NUM_WIDTH-1 downto 0);
+ API_TYP_IN : in std_logic_vector (2 downto 0);
+ API_DATAREADY_IN : in std_logic;
+ API_READ_OUT : out std_logic;
+ -- APL Control port
+ API_RUN_IN : in std_logic;
+ API_SEQNR_IN : in std_logic_vector (7 downto 0);
+ API_LENGTH_OUT : out std_logic_vector (15 downto 0);
+ MY_ADDRESS_IN : in std_logic_vector (15 downto 0);
+
+ --data from event packer
+ CRI_DATA_IN : in std_logic_vector (8 downto 0); --8 is EOD
+ CRI_DATAREADY_IN : in std_logic;
+ --no more data, send TRM
+ CRI_READOUT_FINISHED_IN : in std_logic; --currently not used
+ CRI_READ_OUT : out std_logic;
+ CRI_LENGTH_IN : in std_logic_vector (15 downto 0);
+
+ STAT_DEBUG : out std_logic_vector(31 downto 0)
+ );
+end entity;
+
+architecture cri_data_sender_arch of cri_data_sender is
+
+ type send_state_t is (IDLE, WAITING, SEND_DATA, READ_ANSWER);
+ signal send_state_current, send_state_next : send_state_t;
+ signal send_state_bits : std_logic_vector( 2 downto 0);
+
+ attribute syn_encoding : string;
+
+ type fifo_states is (IDLE, PREPARE_DATA, WAIT_FOR_READY, SAVE, CLOSE, WAIT_FOR_TRANS, DIVIDE, CLEANUP);
+ signal fifo_machine_current_state, fifo_machine_next_state : fifo_states;
+ attribute syn_encoding of fifo_machine_current_state : signal is "onehot";
+ signal fifo_state_bits : std_logic_vector( 2 downto 0);
+
+ type loc_buffer_t is array (0 to 15) of std_logic_vector(17 downto 0);
+ signal local_buffer : loc_buffer_t := (others => (others=> '0'));
+
+ signal fifo_wr_en : std_logic;
+ signal fifo_almFull : std_logic;
+ signal fifo_full : std_logic;
+ signal fifo_empty : std_logic;
+
+ signal local_end : std_logic_vector(15 downto 0);
+ signal fifo_rd_en : std_logic;
+ signal fifo_data_in : std_logic_vector(17 downto 0);
+ signal fifo_wcnt : std_logic_vector(11 downto 0);
+ signal fifo_data_out : std_logic_vector(17 downto 0);
+
+ signal cri_rd : std_logic;
+ signal cri_rd_q : std_logic;
+ signal cri_rd_qq : std_logic;
+ signal cri_data_avail : std_logic;
+
+ signal data_word_pos : std_logic;
+ signal local_buffer_empty : std_logic;
+
+ signal data_ready_q : std_logic;
+ signal data_ready_qq : std_logic;
+ signal buf_data_ready : std_logic;
+ signal buf_data_out : std_logic_vector(15 downto 0);
+ signal buf_eod : std_logic_vector( 1 downto 0);
+
+ signal loc_sending_flag : std_logic;
+
+ signal buf_API_READ_OUT : std_logic;
+ signal buf_API_SEND_OUT : std_logic;
+
+begin
+
+
+-----------------------------------------------------------------
+-- Receive finaly packed events
+-----------------------------------------------------------------
+--
+-- 8 bit words with all headers are reordered to 16 bit words for
+-- trbnet. The Fifo is buffering and the readout is controled by
+-- the status of trbnet and event packer.
+--
+
+ THE_CRI_BUFF : entity work.fifo_18x2k_oreg
+ port map (
+ Data => fifo_data_in,
+ Clock => CLK,
+ WrEn => fifo_wr_en,
+ RdEn => fifo_rd_en,
+ Reset => RESET,
+ AmFullThresh => b"11111110000",
+ Q => fifo_data_out,
+ WCNT => fifo_wcnt,
+ Empty => fifo_empty,
+ Full => fifo_full,
+ AlmostFull => fifo_almFull
+ );
+
+
+ FIFO_MACHINE_PROC : process(RESET, CLK)
+ begin
+ if RESET = '1' then
+ fifo_machine_current_state <= IDLE;
+ elsif rising_edge(CLK) then
+ fifo_machine_current_state <= transmit_next_state;
+ end if;
+ end process FIFO_MACHINE_PROC;
+
+
+ FIFO_MACHINE : process(fifo_machine_current_state, CRI_DATAREADY_IN, local_end, fifo_almFull)
+ begin
+ fifo_machine_state <= x"0";
+ case fifo_machine_current_state is
+ when IDLE =>
+ fifo_machine_state <= x"1";
+ if (CRI_DATAREADY_IN = '1') then
+ fifo_machine_next_state <= PREPARE_DATA;
+ else
+ fifo_machine_next_state <= IDLE;
+ end if;
+
+ when PREPARE_DATA =>
+ fifo_machine_state <= x"2";
+ if (fifo_almFull = '0') then
+ fifo_machine_next_state <= WAIT_FOR_READY;
+ else
+ fifo_machine_next_state <= PREPARE_DATA;
+ end if;
+ when WAIT_FOR_READY =>
+ fifo_machine_state <= x"3";
+ if (fifo_almFull = '0') then
+ fifo_machine_next_state <= SAVE;
+ else
+ fifo_machine_next_state <= WAIT_FOR_READY;
+ end if;
+
+ when SAVE =>
+ fifo_machine_state <= x"4";
+ if (local_end = x"0000") then -- or look for DataIn(8) ??
+ fifo_machine_next_state <= CLOSE;
+ else
+ if (fifo_almFull = '1') then
+ fifo_machine_next_state <= WAIT_FOR_READY;
+ else
+ fifo_machine_next_state <= SAVE;
+ end if;
+ end if;
+
+ when CLOSE =>
+ fifo_machine_state <= x"5";
+ fifo_machine_next_state <= IDLE;
+
+ end case;
+ end process FIFO_MACHINE;
+
+
+ LOCAL_END_PROC : process begin
+ wait until rising_edge(CLK);
+ if (fifo_machine_current_state = IDLE and CRI_DATAREADY_IN = '1') then
+ local_end <= CRI_LENGTH_IN - x"1";
+ --full_packet_size <= CRI_LENGTH_IN;
+ elsif (transmit_current_state = SAVE) then
+ local_end <= local_end - x"1";
+ --full_packet_size <= full_packet_size;
+ else
+ local_end <= local_end;
+ --full_packet_size <= full_packet_size;
+ end if;
+ end process LOCAL_END_PROC;
+
+ SYNC_PROC : process begin
+ wait until rising_edge(CLK);
+ cri_rd_q <= cri_rd;
+ cri_rd_qq <= cri_rd_q;
+ cri_data_avail <= cri_rd_qq;
+ end process SYNC_PROC;
+
+
+ -- If a 8bit word is available, it is putt in the correct position of the
+ -- 16bit words with the EOD bit in the MSB positions
+ ARRANGE_DATA_WORDS_PROC : process begin
+ wait until rising_edge(CLK);
+ fifo_wr_en <= '0';
+ if RESET = '1' then
+ data_word_pos <= '0';
+ else
+ if cri_data_avail = 1 then
+ if data_word_pos = '0' then
+ fifo_data_in(7 downto 0) <= CRI_DATA_IN(7 downto 0);
+ fifo_data_in(16) <= CRI_DATA_IN(8); --16: mark lower 8 bit as end;
+
+ data_word_pos <= '1';
+
+ -- case that event size is odd;
+ if (CRI_DATA_IN(8) = 1) then
+ fifo_data_in(15 downto 8) <= (others => '0');
+ fifo_data_in(17) <= CRI_DATA_IN(8); --17: mark 16bit as EOD;
+
+ fifo_wr_en <= '1';
+ data_word_pos <= '0';
+ end if;
+
+ else
+ fifo_data_in(15 downto 8) <= CRI_DATA_IN(7 downto 0);
+ fifo_data_in(17) <= CRI_DATA_IN(8);
+
+ data_word_pos <= '0';
+ fifo_wr_en <= '1';
+ end if;
+ end if;
+ end if;
+ end process LOCAL_END_PROC;
+
+ cri_rd <= '1' when fifo_machine_current_state = SAVE else '0';
+ CRI_READ_OUT <= cri_rd;
+
+-----------------------------------------------------------------
+--XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX--
+-----------------------------------------------------------------
+
+
+-----------------------------------------------------------------
+-- Send data to API for transfer to CRI
+-----------------------------------------------------------------
+
+--load data from fifo
+ fifo_rd_en <= API_READ_IN and (not fifo_empty) and local_buffer_empty and loc_sending_flag;
+
+
+ FIFO_DATARDY_PROC : process begin
+ wait until rising_edge(CLK);
+ if RESET = '1' then
+ data_ready_q <= '0';
+ data_ready_qq <= '0';
+ else
+ data_ready_q <= fifo_rd_en;
+ data_ready_qq <= data_ready_q;
+ end if;
+ end process;
+
+ -- buffer words from fifo if the API FIFO is going full while we are reding from our fifo
+ local_buffer_process : process
+ variable wcnt : unsigned( 2 downto 0) := 0;
+ begin
+ wait until rising_edge(CLK);
+
+ buf_data_ready <= '0';
+
+ if RESET = '1' then
+ local_buffer_empty <= '1';
+ packet_number <= c_F0;
+ wcnt := 0;
+ buf_eod <= "00";
+ else
+ -- buffer if data is read and API FIFO is full OR buffer also if the transmission
+ -- has finished, but a few words are still coming from FIFO.
+ if (((data_ready_qq = '1') and (API_READ_IN = '0')) or
+ ((data_ready_qq = '1') and (loc_sending_flag = '0')))
+ then
+ local_buffer(to_integer(wcnt)) <= fifo_data_out;
+ wcnt := wcnt + 1;
+ end if;
+
+ -- Data output to API:
+ if ((loc_sending_flag = '1') and (API_READ_IN = '1')) then
+ if (wcnt > 0) then
+ buf_data_ready <= '1';
+ buf_data_out <= local_buffer(to_integer(wcnt-1))(15 downto 0);
+ buf_eod <= local_buffer(to_integer(wcnt-1))(17 downto 16);
+ wcnt := wcnt - 1;
+ else -- standard output from FIFO
+ buf_data_ready <= data_ready_qq;
+ buf_data_out <= fifo_data_out(15 downto 0);
+ buf_eod <= fifo_data_out(17 downto 16);
+ end if;
+
+ -- Generate packet number
+ packet_number <= packet_number + 1;
+ if packet_number = c_F3 then
+ packet_number <= c_F0;
+ end if;
+ end if;
+
+ if wcnt = 0 then
+ local_buffer_empty <= '1';
+ else
+ local_buffer_empty <= '0';
+ end if;
+
+ end if;
+ end process;
+
+
+--send loaded data to CRI
+
+ SEND_STATE_PROC : process(RESET, CLK)
+ begin
+ if RESET = '1' then
+ send_state_current <= IDLE;
+ buf_API_READ_OUT <= '0';
+ elsif rising_edge(CLK) then
+ send_state_current <= send_state_next;
+ buf_API_READ_OUT <= '1';
+ end if;
+ end process;
+
+
+ SEND_STATE_MACHINE : process(send_state_current, API_RUN_IN, fifo_empty, API_READ_IN, buf_eod)
+ begin
+ send_state_bits <= x"0";
+ case send_state_current is
+ when IDLE =>
+ send_state_bits <= x"1";
+ buf_API_SEND_OUT <= '0';
+ loc_sending_flag <= '0';
+
+ if (API_RUN_IN = '0' and (not fifo_empty)) then
+ send_state_next <= WAITING;
+ end if;
+
+ when WAITING =>
+ send_state_bits <= x"2";
+ loc_sending_flag <= '0';
+ if (fifo_empty = '0') and API_READ_IN = '1' then
+ -- read signal for DHDR
+ send_state_next <= SEND_DATA;
+ loc_sending_flag <= '1';
+ end if;
+
+ when SEND_DATA => -- send DHDR packet
+ send_state_bits <= x"3";
+ loc_sending_flag <= '1';
+ buf_API_SEND_OUT <= '1';
+ if buf_eod(1) = '1' then --TO CHECK: is this to late? maybe one word too much send!
+ loc_sending_flag <= '0';
+ send_state_next <= READ_ANSWER;
+ end if;
+
+ when READ_ANSWER =>
+ send_state_bits <= x"4";
+ buf_API_SEND_OUT <= '0';
+ loc_sending_flag <= '0';
+ if API_DATAREADY_IN = '1' and buf_API_READ_OUT = '1' and API_TYP_IN = TYPE_TRM then
+ case API_PACKET_NUM_IN is
+ when c_F0 => null; --crc field, ignore
+ when c_F1 => null;
+ when c_F2 => null;
+ when c_F3 => --buf_TYPE <= API_DATA_IN(3 downto 0);
+ null;
+ send_state_next <= IDLE;
+ when others => null;
+ end case;
+ end if;
+
+ when others =>
+ send_state_bits <= x"5";
+ send_state_next <= IDLE;
+
+ end case;
+ end process;
+
+
+
+
+---------------------------------------------------------------------
+--Connect Outputs
+---------------------------------------------------------------------
+
+ API_ERROR_PATTERN_OUT <= (others => '0');
+ API_LENGTH_OUT <= (others => '0');
+ API_READ_OUT <= buf_API_READ_OUT;
+ API_DATAREADY_OUT <= buf_data_ready;
+ API_DATA_OUT <= buf_data_out;
+ API_PACKET_NUM_OUT <= packet_number;
+ API_SEND_OUT <= buf_API_SEND_OUT;
+ API_SHORT_TRANSFER_OUT<= '0';
+ API_DTYPE_OUT <= (others => '0');--buf_TYPE;
+
+---------------------------------------------------------------------
+--Debugging
+---------------------------------------------------------------------
+ STAT_DEBUG( 2 downto 0) <= fifo_state_bits;
+ STAT_DEBUG( 5 downto 3) <= send_state_bits;
+ STAT_DEBUG(31 downto 3) <= (others => '0');
+
+
+
+end architecture;