-- -- Readout Unit Status Block -- -- Drives LL out when stat_req comes in -- -- -- -- Change log: -- 2012-10-02 - fixed non mapped busy_en_i's -- 2012-10-03 - reset delta counter if not en -- 2012-10-30 - fixed hd_delta stuck at max/min bug library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; library utils; use utils.pkg_types.all; library hsio; use hsio.pkg_core_globals.all; entity ro_unit_stat is --generic( -- STREAM_ID : integer := 0 --); port( STREAM_ID : in integer; -- locallink tx interface lls_o : out t_llsrc; lld_i : in std_logic; -- stats req_stat_i : in std_logic; strm_reg_i : in slv16; reg_busy_delta_i : in slv16; header_seen_i : in std_logic; trig80_i : in std_logic; dropped_pkts_i : in slv8; fifo_count_i : in slv2; len_fifo_count_i : in slv2; busy_en_delta_i : in std_logic; busy_en_fifo_i : in std_logic; --hd_delta_max_i : in slv6; deser_en_i : in std_logic; histo_en_i : in std_logic; busy_o : out std_logic; -- infrastructure clk : in std_logic; rst : in std_logic ); -- Declarations end ro_unit_stat; architecture rtl of ro_unit_stat is signal hd_delta : slv6; signal hd_delta_en : std_logic; signal hd_code : slv2; signal hd_delta_on : integer range 0 to 63; signal hd_delta_off : integer range 0 to 63; signal busy_fifo : std_logic; signal busy_delta : std_logic; signal seq_id_inc : std_logic; signal seq_id : std_logic_vector(3 downto 0); signal statword0 : slv16; signal statword1 : slv16; -- signal statword2 : slv16; type states is (SrcRdy, OpcodeSOF, OCSeq, Size, StrmID, Data0, --Data1, DataEOF, Idle); signal state, nstate : states; begin -- State Machine -------------------------------------------------------- prc_sync_part : process (clk) begin if rising_edge(clk) then if (rst = '1') then state <= Idle; else state <= nstate; -- after 50 ps; end if; end if; end process; prc_async_machine : process (req_stat_i, lld_i, strm_reg_i, statword0, statword1, state ) begin -- defaults nstate <= Idle; lls_o.src_rdy <= '1'; lls_o.sof <= '0'; lls_o.eof <= '0'; lls_o.data <= OC_STRM_STAT_DATA; seq_id_inc <= '0'; case state is ------------------------------------------------------------------- when Idle => -- Make sure we get rising edge of oc_valid nstate <= Idle; lls_o.src_rdy <= '0'; if (req_stat_i = '1') then nstate <= SrcRdy; end if; when SrcRdy => nstate <= SrcRdy; if (lld_i = '1') then nstate <= OpcodeSOF; end if; when OpcodeSOF => nstate <= OpcodeSOF; lls_o.data <= OC_STRM_STAT_DATA; lls_o.sof <= '1'; if (lld_i = '1') then nstate <= OCSeq; end if; when OCSeq => nstate <= OCSeq; lls_o.data <= x"000" & seq_id; --x"0000"; if (lld_i = '1') then nstate <= Size; end if; when Size => nstate <= Size; lls_o.data <= x"0006"; if (lld_i = '1') then nstate <= StrmID; end if; when StrmID => nstate <= StrmID; lls_o.data <= conv_std_logic_vector(STREAM_ID, 16); if (lld_i = '1') then nstate <= Data0; end if; when Data0 => nstate <= Data0; lls_o.data <= statword0; if (lld_i = '1') then nstate <= DataEOF; end if; -- when Data1 => -- nstate <= Data1; -- lls_o.data <= statword1; -- if (lld_i = '1') then -- nstate <= Data2EOF; -- end if; when DataEOF => nstate <= DataEOF; lls_o.data <= statword1; lls_o.eof <= '1'; if (lld_i = '1') then seq_id_inc <= '1'; nstate <= Idle; end if; end case; end process; statword0 <= strm_reg_i; statword1 <= dropped_pkts_i(3 downto 0) & len_fifo_count_i & fifo_count_i & busy_fifo & busy_delta & hd_delta; -- statword1 <= x"00" & busy_fifo & busy_delta & hd_delta; -- statword2 <= dropped_pkts_i(3 downto 0) & "0000" & len_fifo_count_i & fifo_count_i; -- Delta headers and triggers ----------------------------------------------------- hd_delta_en <= (deser_en_i or histo_en_i) and busy_en_delta_i; hd_code <= header_seen_i & trig80_i; prc_hd_delta : process (clk) begin if rising_edge(clk) then if (rst = '1') or (hd_delta_en = '0') then hd_delta <= (others => '0'); else if (hd_delta /= "111111") and (hd_code = "01") then hd_delta <= hd_delta + '1'; elsif (hd_delta /= "000000") and (hd_code = "10") then hd_delta <= hd_delta - '1'; end if; end if; end if; end process; -- Busy Generate ------------------------------------------------------- hd_delta_on <= conv_integer(reg_busy_delta_i(13 downto 8)); hd_delta_off <= conv_integer(reg_busy_delta_i(5 downto 0)); prc_busy_delta : process (clk) begin if rising_edge(clk) then if (rst = '1') then busy_delta <= '0'; else if (hd_delta >= hd_delta_on) then busy_delta <= '1'; elsif (hd_delta <= hd_delta_off) then busy_delta <= '0'; end if; end if; end if; end process; busy_fifo <= '1' when (fifo_count_i(1) = '1') or (len_fifo_count_i(1) = '1') else '0'; busy_o <= (busy_delta and busy_en_delta_i) or (busy_fifo and busy_en_fifo_i); -- Sequence ID counter ------------------------------------------------------- prc_seq_id : process (clk) begin if rising_edge(clk) then if (rst = '1') then seq_id <= (others => '0'); else if (seq_id_inc = '1') then if (seq_id = x"f") then seq_id <= x"0"; else seq_id <= seq_id + '1'; end if; end if; end if; end if; end process; end architecture;