From: Adrian Weber Date: Thu, 2 Jul 2020 15:00:18 +0000 (+0200) Subject: entity to send data from event packer to API/CRI; not debugged yet X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=690469fe825ba455752145bd484ddbfd78847df1;p=dirich.git entity to send data from event packer to API/CRI; not debugged yet --- diff --git a/combiner_cts/cri/cri_data_sender.vhd b/combiner_cts/cri/cri_data_sender.vhd new file mode 100644 index 0000000..f08e432 --- /dev/null +++ b/combiner_cts/cri/cri_data_sender.vhd @@ -0,0 +1,410 @@ +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;