-- readoutHist.vhd - writes histogram data to the transmit buffer. -- August 2009 -- Alexander Law (atlaw@lbl.gov) -- Lawrence Berkeley National Laboratory -- -- converted for use with SCT daq. -- Now this is almost a generic BRAM to LocalLink readout tool -- -- Hacked by tom library ieee; use ieee.std_logic_1164.all; use IEEE.NUMERIC_STD.all; library utils; use utils.pkg_types.all; entity readoutHist_tom is generic( --STREAM_ID : integer := 0; histogram_depth : natural := 11; histogram_width : natural := 16; max_address_count : natural := 1280 ); port( STREAM_ID : in integer; clk : in std_logic; -- rst : in std_logic; -- start_ro_i : in std_logic; ready_out : out std_logic; -- hst_rdPtr_out : out std_logic_vector(histogram_depth-1 downto 0); -- hst_rdData_i : in std_logic_vector(histogram_width-1 downto 0); -- hst_rdEn_out : out std_logic; lls_o : out t_llsrc; lld_i : in std_logic; header_count : in std_logic_vector(histogram_width-1 downto 0); hit_count : in std_logic_vector(histogram_width-1 downto 0); error_count : in std_logic_vector(histogram_width-1 downto 0); parseError_count : in std_logic_vector(histogram_width-1 downto 0) ); end readoutHist_tom; architecture rtl of readoutHist_tom is -- histo is split across 2 packets. -- a packet contains 1280/2 strips @ 2bytes/strip = 1280 bytes/packet -- The additional 10 is the number of header bytes (anything not histo data) constant payload_size : natural := max_address_count + 10; constant DoolData : natural := 16#d011#; -- Can we calculate this? How big can a packet be? -- Network packets can be up to 65535 bytes long -- minimum required is 576 bytes constant number_of_packets : natural := 2; signal hst_rdPtr : integer range 0 to 2**histogram_depth - 1; signal hst_wrEn : std_logic; type states is ( SrcRdy, Opcode, Size, Seqnum, StreamID, EventCount, HitCount, ErrorCount, ParseErrorCount, ReadoutData, NextPacketEOF, LastPacketEOF, Idle ); signal state : states := Idle; signal nextState : states := Idle; signal ready : std_logic; signal ll_sof : std_logic; signal ll_eof : std_logic; signal ll_src_rdy : std_logic; signal ll_data : std_logic_vector(histogram_width-1 downto 0); --signal sctdaq_header : std_logic; --signal header_data : std_logic_vector(histogram_width-1 downto 0); signal seqnum_count : integer range 0 to 2**histogram_width-1; signal seqnum_inc : std_logic; signal addr_inc : std_logic; signal addr_clr : std_logic; signal fifo_rd : std_logic; signal fifo_rd_q : std_logic; signal hst_rdData : std_logic_vector(histogram_width-1 downto 0); signal hst_rdData_q : std_logic_vector(histogram_width-1 downto 0); signal fragment2 : std_logic; begin -- ll_data_len_o <= std_logic_vector(to_unsigned(payload_size, ll_data_len_o'length)); ready_out <= ready; hst_rdEn_out <= fifo_rd; hst_rdPtr_out <= std_logic_vector(to_unsigned(hst_rdPtr, histogram_depth)); -- This is the data output to the local link lls_o.data <= ll_data; --header_data when (sctdaq_header = '1') else hst_rdData; lls_o.sof <= ll_sof; lls_o.eof <= ll_eof; lls_o.src_rdy <= ll_src_rdy; -- readout peak absorber prc_peak_absorb : process (clk, rst) begin if rising_edge(clk) then if (rst = '1') then hst_rdData_q <= (others => '0'); fifo_rd_q <= '0'; else fifo_rd_q <= fifo_rd; if (fifo_rd_q = '1') then hst_rdData_q <= hst_rdData_i; end if; end if; end if; end process; hst_rdData <= hst_rdData_q when (fifo_rd_q = '0') else hst_rdData_i; addr_inc <= fifo_rd; ------------------------------------------------- -- synchronous assignments process(clk, rst) begin if rising_edge(clk) then if (rst = '1') then state <= Idle; hst_rdPtr <= 0; fragment2 <= '0'; else state <= nextState; if (addr_clr = '1') then hst_rdPtr <= 0; elsif (addr_inc = '1') then hst_rdPtr <= hst_rdPtr + 1; end if; -- fragment marker if (state = Idle) then fragment2 <= '0'; elsif (state = NextPacketEOF) then fragment2 <= '1'; end if; end if; end if; end process; ------------------------------------------------- -- async state machine process prc_sm_async : process( state, start_ro_i, hst_rdPtr, lld_i, seqnum_count, fragment2, hst_rdData, header_count, hit_count, error_count, parseError_count) begin -- defaults ready <= '0'; ll_sof <= '0'; ll_eof <= '0'; addr_clr <= '0'; fifo_rd <= '0'; seqnum_inc <= '0'; ll_src_rdy <= '1'; ll_data <= hst_rdData; case state is when Idle => nextState <= Idle; ready <= '1'; addr_clr <= '1'; ll_src_rdy <= '0'; if (start_ro_i = '1') then nextState <= SrcRdy; end if; when SrcRdy => nextState <= SrcRdy; if (lld_i = '1') then nextState <= Opcode; end if; when Opcode => nextState <= Opcode; ll_data <= std_logic_vector(to_unsigned(DoolData, ll_data'length)); ll_sof <= '1'; if (lld_i = '1') then nextState <= Seqnum; end if; when Seqnum => nextState <= Seqnum; ll_data <= std_logic_vector(to_unsigned(seqnum_count, ll_data'length)); if (lld_i = '1') then seqnum_inc <= '1'; nextState <= Size; end if; when Size => nextState <= Size; ll_data <= std_logic_vector(to_unsigned(payload_size, ll_data'length)); if (lld_i = '1') then nextState <= StreamID; end if; when StreamID => nextState <= StreamID; -- Bit of a mouthful ll_data(histogram_width-1 downto histogram_width-8) <= std_logic_vector(to_unsigned(STREAM_ID, 8)); ll_data(histogram_width-9 downto 0) <= (0 => fragment2, others => '0'); if (lld_i = '1') then nextState <= EventCount; end if; when EventCount => nextState <= EventCount; ll_data <= header_count; if (lld_i = '1') then nextState <= HitCount; end if; when HitCount => nextState <= HitCount; ll_data <= hit_count; if (lld_i = '1') then nextState <= ErrorCount; end if; when ErrorCount => nextState <= ErrorCount; ll_data <= error_count; if (lld_i = '1') then nextState <= ParseErrorCount; end if; when ParseErrorCount => nextState <= ParseErrorCount; ll_data <= parseerror_count; if (lld_i = '1') then nextState <= ReadoutData; fifo_rd <= '1'; end if; when ReadoutData => nextState <= ReadoutData; if (lld_i = '1') then fifo_rd <= '1'; if (hst_rdPtr = (max_address_count/number_of_packets - 1)) then -- split data across n packets nextState <= NextPacketEOF; elsif (hst_rdPtr = (max_address_count-1)) then nextState <= LastPacketEOF; end if; end if; when NextPacketEOF => nextState <= NextPacketEOF; ll_eof <= '1'; if (lld_i = '1') then nextState <= SrcRdy; end if; when LastPacketEOF => nextState <= LastPacketEOF; ll_eof <= '1'; if (lld_i = '1') then nextState <= Idle; end if; end case; end process; prc_sequence_number : process (clk) begin if rising_edge(clk) then if (rst = '1') then seqnum_count <= 0; else if (seqnum_inc = '1') then seqnum_count <= seqnum_count + 1; end if; end if; end if; end process; end rtl;