From: Tobias Weber Date: Thu, 3 May 2018 09:37:27 +0000 (+0200) Subject: Bugfixes to trigger code. X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=0b424e263d9dc4fe2755966e39dfd235c6cba4fb;p=trb3.git Bugfixes to trigger code. --- diff --git a/mupix/Mupix8/sources/MupixTRBReadout.vhd b/mupix/Mupix8/sources/MupixTRBReadout.vhd index 77e8d40..dbf57f9 100644 --- a/mupix/Mupix8/sources/MupixTRBReadout.vhd +++ b/mupix/Mupix8/sources/MupixTRBReadout.vhd @@ -8,363 +8,363 @@ use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity MupixTRBReadout is - generic(g_mupix_links : natural := 4; -- number of input data channels from mupix - g_cyc_mem_address_width : integer := 13; -- memory depth of circular buffer - g_datawidth : integer := 32 -- width of data words - ); - port( - clk : in std_logic; -- clock input - rst : in std_logic; -- reset input - -- input fifo signals (maybe we need word width conversion somewhere ?) - fifo_empty : in std_logic_vector(g_mupix_links - 1 downto 0); - fifo_full : in std_logic_vector(g_mupix_links - 1 downto 0); - fifo_datain : in std_logic_vector(g_mupix_links*g_datawidth - 1 downto 0); - fifo_rden : out std_logic_vector(g_mupix_links - 1 downto 0); - -- readout and trigger - trb_trigger : in std_logic; -- signal from trb to start readout - dataout : out std_logic_vector(g_datawidth - 1 downto 0); -- data to TRB data channel - data_valid : out std_logic; -- output data is valid - busy : out std_logic; -- readout controller is busy - -- TRB slow Control channel - SLV_READ_IN : in std_logic; - SLV_WRITE_IN : in std_logic; - SLV_DATA_OUT : out std_logic_vector(31 downto 0); - SLV_DATA_IN : in std_logic_vector(31 downto 0); - SLV_ADDR_IN : in std_logic_vector(15 downto 0); - SLV_ACK_OUT : out std_logic; - SLV_NO_MORE_DATA_OUT : out std_logic; - SLV_UNKNOWN_ADDR_OUT : out std_logic); + generic(g_mupix_links : natural := 4; -- number of input data channels from mupix + g_cyc_mem_address_width : integer := 13; -- memory depth of circular buffer + g_datawidth : integer := 32 -- width of data words + ); + port( + clk : in std_logic; -- clock input + rst : in std_logic; -- reset input + -- input fifo signals (maybe we need word width conversion somewhere ?) + fifo_empty : in std_logic_vector(g_mupix_links - 1 downto 0); + fifo_full : in std_logic_vector(g_mupix_links - 1 downto 0); + fifo_datain : in std_logic_vector(g_mupix_links*g_datawidth - 1 downto 0); + fifo_rden : out std_logic_vector(g_mupix_links - 1 downto 0); + -- readout and trigger + trb_trigger : in std_logic; -- signal from trb to start readout + dataout : out std_logic_vector(g_datawidth - 1 downto 0); -- data to TRB data channel + data_valid : out std_logic; -- output data is valid + busy : out std_logic; -- readout controller is busy + -- TRB slow Control channel + SLV_READ_IN : in std_logic; + SLV_WRITE_IN : in std_logic; + SLV_DATA_OUT : out std_logic_vector(31 downto 0); + SLV_DATA_IN : in std_logic_vector(31 downto 0); + SLV_ADDR_IN : in std_logic_vector(15 downto 0); + SLV_ACK_OUT : out std_logic; + SLV_NO_MORE_DATA_OUT : out std_logic; + SLV_UNKNOWN_ADDR_OUT : out std_logic); end entity MupixTRBReadout; architecture rtl of MupixTRBReadout is - component CircularMemory - generic( - g_datawidth : integer := 32; - g_addresswidth : integer := 10; - g_clockspeed : integer := 1e8; - g_boundedbuf : boolean := false - ); - port( - clk : in std_logic; - rst : in std_logic; - wr_en : in std_logic; - data_in : in std_logic_vector(g_datawidth - 1 downto 0); - rd_en : in std_logic; - offset_en : in std_logic; - offset : in std_logic_vector(g_addresswidth - 1 downto 0); - data_out : out std_logic_vector(g_datawidth - 1 downto 0); - empty : out std_logic; - full : out std_logic; - almost_empty : out std_logic; - almost_full : out std_logic; - fillcnt : out std_logic_vector(g_addresswidth downto 0); - inword_freq : out std_logic_vector(31 downto 0); - outword_freq : out std_logic_vector(31 downto 0) - ); - end component CircularMemory; - - component FiFoDataMux - generic( - g_datawidth : integer := 32; - g_inputs : integer := 4; - g_clockspeed : integer := 1e8 - ); - port( - clk : in std_logic; - rst : in std_logic; - fifo_empty : in std_logic_vector(g_inputs - 1 downto 0); - fifo_full : in std_logic_vector(g_inputs - 1 downto 0); - fifo_datain : in std_logic_vector(g_inputs*g_datawidth - 1 downto 0); - fifo_mask : in std_logic_vector(g_inputs - 1 downto 0); - fifo_rden : out std_logic_vector(g_inputs - 1 downto 0); - buff_wren : out std_logic; - dataout : out std_logic_vector(g_datawidth - 1 downto 0); - wordin_freq : out std_logic_vector(32*g_inputs - 1 downto 0); - fifo_full_o : out std_logic - ); - end component FiFoDataMux; - - component ReadoutController - generic( - g_datawidth : integer := 32; - g_addresswidth : integer := 10 - ); - port( - clk : in std_logic; - rst : in std_logic; - start : in std_logic; - mode : in std_logic_vector(1 downto 0); - writes_after_trig : in std_logic_vector(g_addresswidth - 1 downto 0); - max_words : in std_logic_vector(g_addresswidth - 1 downto 0); - data_in : in std_logic_vector(g_datawidth - 1 downto 0); - empty : in std_logic; - almost_empty : in std_logic; - sensor_id : in std_logic_vector(g_datawidth - 1 downto 0); - offset_en : out std_logic; - rd_en : out std_logic; - busy : out std_logic; - data_valid : out std_logic; - data_out : out std_logic_vector(g_datawidth - 1 downto 0) - ); - end component ReadoutController; - - signal readout_mode_i : std_logic_vector(1 downto 0) := "00"; - signal readout_writes_aft_trig : std_logic_vector(g_cyc_mem_address_width - 1 downto 0) := (others => '0'); - signal readout_words : std_logic_vector(g_cyc_mem_address_width - 1 downto 0) := (others => '0'); - signal sensor_id : std_logic_vector(31 downto 0) := (others => '0'); - signal multiplexer_mask : std_logic_vector(g_mupix_links - 1 downto 0) := (others => '0'); - signal multiplexer_channel_sel : integer range 0 to g_mupix_links - 1 := 0; - signal wordin_freq : std_logic_vector(32*g_mupix_links - 1 downto 0) := (others => '0'); - signal fifo_full_o : std_logic; - - signal cycl_fillcnt : std_logic_vector(g_cyc_mem_address_width downto 0); - signal cycl_inword_freq : std_logic_vector(31 downto 0); - signal cycl_outword_freq : std_logic_vector(31 downto 0); - signal cycl_empty : std_logic; - signal cycl_full : std_logic; - signal cycl_almost_empty : std_logic; - - signal fifo_mux_wren : std_logic; - signal fifo_mux_data_out : std_logic_vector(g_datawidth - 1 downto 0); - - signal start_readout_slow_to_buffer : std_logic := '0'; - signal start_readout : std_logic := '0'; - signal readout_controller_data_in : std_logic_vector(g_datawidth - 1 downto 0); - signal readout_controller_data_out : std_logic_vector(g_datawidth - 1 downto 0); - signal readout_controller_busy : std_logic; - signal readout_controller_offset_en : std_logic; - signal readout_controller_rd_en : std_logic; - signal readout_controller_data_valid : std_logic; - - type slow_readout_fsm_type is (idle, waitstate); - signal slow_readout_fsm : slow_readout_fsm_type := idle; - signal slow_data : std_logic_vector(g_datawidth - 1 downto 0) := (others => '0'); - signal start_slow_read : std_logic := '0'; - signal slow_read_busy : std_logic := '0'; - signal slow_read_done : std_logic := '0'; - + component CircularMemory + generic( + g_datawidth : integer := 32; + g_addresswidth : integer := 10; + g_clockspeed : integer := 1e8; + g_boundedbuf : boolean := false + ); + port( + clk : in std_logic; + rst : in std_logic; + wr_en : in std_logic; + data_in : in std_logic_vector(g_datawidth - 1 downto 0); + rd_en : in std_logic; + offset_en : in std_logic; + offset : in std_logic_vector(g_addresswidth - 1 downto 0); + data_out : out std_logic_vector(g_datawidth - 1 downto 0); + empty : out std_logic; + full : out std_logic; + almost_empty : out std_logic; + almost_full : out std_logic; + fillcnt : out std_logic_vector(g_addresswidth downto 0); + inword_freq : out std_logic_vector(31 downto 0); + outword_freq : out std_logic_vector(31 downto 0) + ); + end component CircularMemory; + + component FiFoDataMux + generic( + g_datawidth : integer := 32; + g_inputs : integer := 4; + g_clockspeed : integer := 1e8 + ); + port( + clk : in std_logic; + rst : in std_logic; + fifo_empty : in std_logic_vector(g_inputs - 1 downto 0); + fifo_full : in std_logic_vector(g_inputs - 1 downto 0); + fifo_datain : in std_logic_vector(g_inputs*g_datawidth - 1 downto 0); + fifo_mask : in std_logic_vector(g_inputs - 1 downto 0); + fifo_rden : out std_logic_vector(g_inputs - 1 downto 0); + buff_wren : out std_logic; + dataout : out std_logic_vector(g_datawidth - 1 downto 0); + wordin_freq : out std_logic_vector(32*g_inputs - 1 downto 0); + fifo_full_o : out std_logic + ); + end component FiFoDataMux; + + component ReadoutController + generic( + g_datawidth : integer := 32; + g_addresswidth : integer := 10 + ); + port( + clk : in std_logic; + rst : in std_logic; + start : in std_logic; + mode : in std_logic_vector(1 downto 0); + writes_after_trig : in std_logic_vector(g_addresswidth - 1 downto 0); + max_words : in std_logic_vector(g_addresswidth - 1 downto 0); + data_in : in std_logic_vector(g_datawidth - 1 downto 0); + empty : in std_logic; + almost_empty : in std_logic; + sensor_id : in std_logic_vector(g_datawidth - 1 downto 0); + offset_en : out std_logic; + rd_en : out std_logic; + busy : out std_logic; + data_valid : out std_logic; + data_out : out std_logic_vector(g_datawidth - 1 downto 0) + ); + end component ReadoutController; + + signal readout_mode_i : std_logic_vector(1 downto 0) := "00"; + signal readout_writes_aft_trig : std_logic_vector(g_cyc_mem_address_width - 1 downto 0) := (others => '0'); + signal readout_words : std_logic_vector(g_cyc_mem_address_width - 1 downto 0) := (others => '0'); + signal sensor_id : std_logic_vector(31 downto 0) := (others => '0'); + signal multiplexer_mask : std_logic_vector(g_mupix_links - 1 downto 0) := (others => '0'); + signal multiplexer_channel_sel : integer range 0 to g_mupix_links - 1 := 0; + signal wordin_freq : std_logic_vector(32*g_mupix_links - 1 downto 0) := (others => '0'); + signal fifo_full_o : std_logic; + + signal cycl_fillcnt : std_logic_vector(g_cyc_mem_address_width downto 0); + signal cycl_inword_freq : std_logic_vector(31 downto 0); + signal cycl_outword_freq : std_logic_vector(31 downto 0); + signal cycl_empty : std_logic; + signal cycl_full : std_logic; + signal cycl_almost_empty : std_logic; + + signal fifo_mux_wren : std_logic; + signal fifo_mux_data_out : std_logic_vector(g_datawidth - 1 downto 0); + + signal start_readout_slow_to_buffer : std_logic := '0'; + signal start_readout : std_logic := '0'; + signal readout_controller_data_in : std_logic_vector(g_datawidth - 1 downto 0); + signal readout_controller_data_out : std_logic_vector(g_datawidth - 1 downto 0); + signal readout_controller_busy : std_logic; + signal readout_controller_offset_en : std_logic; + signal readout_controller_rd_en : std_logic; + signal readout_controller_data_valid : std_logic; + + type slow_readout_fsm_type is (idle, waitstate); + signal slow_readout_fsm : slow_readout_fsm_type := idle; + signal slow_data : std_logic_vector(g_datawidth - 1 downto 0) := (others => '0'); + signal start_slow_read : std_logic := '0'; + signal slow_read_busy : std_logic := '0'; + signal slow_read_done : std_logic := '0'; + begin - - start_readout <= start_readout_slow_to_buffer or trb_trigger; - - data_mux_1 : entity work.FiFoDataMux - generic map( - g_datawidth => g_datawidth, - g_inputs => g_mupix_links, - g_clockspeed => 1e8 - ) - port map( - clk => clk, - rst => rst, - fifo_empty => fifo_empty, - fifo_full => fifo_full, - fifo_datain => fifo_datain, - fifo_mask => multiplexer_mask, - fifo_rden => fifo_rden, - buff_wren => fifo_mux_wren, - dataout => fifo_mux_data_out, - wordin_freq => wordin_freq, - fifo_full_o => fifo_full_o - ); - - cycl_buffer_1 : entity work.CircularMemory - generic map( - g_datawidth => g_datawidth, - g_addresswidth => g_cyc_mem_address_width, - g_clockspeed => 1e8, - g_boundedbuf => false - ) - port map( - clk => clk, - rst => rst, - wr_en => fifo_mux_wren, - data_in => fifo_mux_data_out, - rd_en => readout_controller_rd_en, - offset_en => readout_controller_offset_en, - offset => readout_words, - data_out => readout_controller_data_in, - empty => cycl_empty, - full => cycl_full, - almost_empty => cycl_almost_empty, - almost_full => open, - fillcnt => cycl_fillcnt, - inword_freq => cycl_inword_freq, - outword_freq => cycl_outword_freq - ); - - readout_controller_1 : entity work.ReadoutController - generic map( - g_datawidth => g_datawidth, - g_addresswidth => g_cyc_mem_address_width - ) - port map( - clk => clk, - rst => rst, - start => start_readout, - mode => readout_mode_i, - writes_after_trig => readout_writes_aft_trig, - max_words => readout_words, - data_in => readout_controller_data_in, - empty => cycl_empty, - almost_empty => cycl_almost_empty, - sensor_id => sensor_id, - offset_en => readout_controller_offset_en, - rd_en => readout_controller_rd_en, - busy => readout_controller_busy, - data_valid => readout_controller_data_valid, - data_out => readout_controller_data_out - ); - - data_read_slow : process (clk) is - begin - if rising_edge(clk) then - if rst = '1' then - slow_readout_fsm <= idle; - slow_read_done <= '0'; - slow_read_busy <= '0'; - start_readout_slow_to_buffer <= '0'; - else - start_readout_slow_to_buffer <= '0'; - slow_read_done <= '0'; - case slow_readout_fsm is - when idle => - slow_readout_fsm <= idle; - slow_read_busy <= '0'; - if start_slow_read = '1' then - start_readout_slow_to_buffer <= '1'; - slow_read_busy <= '1'; - slow_data <= (others => '0'); - slow_readout_fsm <= waitstate; - end if; - when waitstate => - slow_read_busy <= '1'; - if readout_controller_data_valid = '1' then - slow_read_done <= '1'; - slow_data <= readout_controller_data_out; - slow_readout_fsm <= idle; - end if; - end case; - end if; - end if; - end process data_read_slow; - - - ------------------------------------------------------------------------------------ - --Slow Control Handling - ------------------------------------------------------------------------------------ - --0x100: readout controller mode - --0x101: readout controller writes after trigger - --0x102: readout controller numbers of words to readout - --0x103: readout controller sensor id - --0x104: readout controller start slow readout (read only) - --0x105: fifo multiplexer mask - --0x106: fifo multiplexer input frequency (write select channel, read frequency) - --0x107: fifo multiplexer full (read-only) - --0x108: circular memory empty/full flags, fill cnt (read-only) - --0x109: circular memory input word frequency (read-only) - --0x10a: circular memory output word frequency (read-only) - --0x10b: readout controller read-enable (debug read-only) - ----------------------------------------------------------------------------------- - slv_bus_handler : process(clk) is - begin - if rising_edge(clk) then - if rst = '1' then - SLV_DATA_OUT <= (others => '0'); - SLV_ACK_OUT <= '0'; - SLV_NO_MORE_DATA_OUT <= '0'; - SLV_UNKNOWN_ADDR_OUT <= '0'; - start_slow_read <= '0'; - else - SLV_DATA_OUT <= (others => '0'); - SLV_ACK_OUT <= '0'; - SLV_NO_MORE_DATA_OUT <= '0'; - SLV_UNKNOWN_ADDR_OUT <= '0'; - start_slow_read <= '0'; - - if slow_read_busy = '1' then - if slow_read_done = '1' then - SLV_DATA_OUT <= slow_data; - SLV_ACK_OUT <= '1'; - end if; - - elsif SLV_WRITE_IN = '1' then - case SLV_ADDR_IN is - when x"0100" => - readout_mode_i <= SLV_DATA_IN(1 downto 0); - SLV_ACK_OUT <= '1'; - when x"0101" => - readout_writes_aft_trig <= SLV_DATA_IN(g_cyc_mem_address_width - 1 downto 0); - SLV_ACK_OUT <= '1'; - when x"0102" => - readout_words <= SLV_DATA_IN(g_cyc_mem_address_width - 1 downto 0); - SLV_ACK_OUT <= '1'; - when x"0103" => - sensor_id <= SLV_DATA_IN; - SLV_ACK_OUT <= '1'; - when x"0105" => - multiplexer_mask <= SLV_DATA_IN(g_mupix_links - 1 downto 0); - SLV_ACK_OUT <= '1'; - when x"0106" => - multiplexer_channel_sel <= to_integer(unsigned(SLV_DATA_IN)); - SLV_ACK_OUT <= '1'; - when others => - slv_unknown_addr_out <= '1'; - end case; - elsif SLV_READ_IN = '1' then - case SLV_ADDR_IN is - when x"0100" => - SLV_DATA_OUT(1 downto 0) <= readout_mode_i; - SLV_ACK_OUT <= '1'; - when x"0101" => - SLV_DATA_OUT(g_cyc_mem_address_width - 1 downto 0) <= readout_writes_aft_trig; - SLV_ACK_OUT <= '1'; - when x"0102" => - SLV_DATA_OUT(g_cyc_mem_address_width - 1 downto 0) <= readout_words; - SLV_ACK_OUT <= '1'; - when x"0103" => - SLV_DATA_OUT <= sensor_id; - SLV_ACK_OUT <= '1'; - when x"0104" => - if cycl_empty = '0' and readout_mode_i = "00" then - start_slow_read <= '1'; - else - SLV_NO_MORE_DATA_OUT <= '1'; - end if; - when x"0105" => - SLV_DATA_OUT(g_mupix_links - 1 downto 0) <= multiplexer_mask; - SLV_ACK_OUT <= '1'; - when x"0106" => - SLV_DATA_OUT <= wordin_freq((multiplexer_channel_sel + 1)*32 - 1 downto multiplexer_channel_sel*32); - SLV_ACK_OUT <= '1'; - when x"0107" => - SLV_DATA_OUT(0) <= fifo_full_o; - SLV_ACK_OUT <= '1'; - when x"0108" => - SLV_DATA_OUT(g_cyc_mem_address_width downto 0) <= cycl_fillcnt; - SLV_DATA_OUT(31) <= cycl_empty; - SLV_DATA_OUT(30) <= cycl_full; - SLV_ACK_OUT <= '1'; - when x"0109" => - SLV_DATA_OUT <= cycl_inword_freq; - SLV_ACK_OUT <= '1'; - when x"010a" => - SLV_DATA_OUT <= cycl_outword_freq; - SLV_ACK_OUT <= '1'; - when x"010b" => - SLV_DATA_OUT(3 downto 0) <= busy & start_readout & start_readout_slow_to_buffer & trb_trigger; - SLV_ACK_OUT <= '1'; - when others => - slv_unknown_addr_out <= '1'; - end case; - end if; - end if; - end if; - end process slv_bus_handler; - - busy <= readout_controller_busy; - dataout <= readout_controller_data_out; - data_valid <= readout_controller_data_valid; - + + start_readout <= start_readout_slow_to_buffer or trb_trigger; + + data_mux_1 : entity work.FiFoDataMux + generic map( + g_datawidth => g_datawidth, + g_inputs => g_mupix_links, + g_clockspeed => 1e8 + ) + port map( + clk => clk, + rst => rst, + fifo_empty => fifo_empty, + fifo_full => fifo_full, + fifo_datain => fifo_datain, + fifo_mask => multiplexer_mask, + fifo_rden => fifo_rden, + buff_wren => fifo_mux_wren, + dataout => fifo_mux_data_out, + wordin_freq => wordin_freq, + fifo_full_o => fifo_full_o + ); + + cycl_buffer_1 : entity work.CircularMemory + generic map( + g_datawidth => g_datawidth, + g_addresswidth => g_cyc_mem_address_width, + g_clockspeed => 1e8, + g_boundedbuf => false + ) + port map( + clk => clk, + rst => rst, + wr_en => fifo_mux_wren, + data_in => fifo_mux_data_out, + rd_en => readout_controller_rd_en, + offset_en => readout_controller_offset_en, + offset => readout_words, + data_out => readout_controller_data_in, + empty => cycl_empty, + full => cycl_full, + almost_empty => cycl_almost_empty, + almost_full => open, + fillcnt => cycl_fillcnt, + inword_freq => cycl_inword_freq, + outword_freq => cycl_outword_freq + ); + + readout_controller_1 : entity work.ReadoutController + generic map( + g_datawidth => g_datawidth, + g_addresswidth => g_cyc_mem_address_width + ) + port map( + clk => clk, + rst => rst, + start => start_readout, + mode => readout_mode_i, + writes_after_trig => readout_writes_aft_trig, + max_words => readout_words, + data_in => readout_controller_data_in, + empty => cycl_empty, + almost_empty => cycl_almost_empty, + sensor_id => sensor_id, + offset_en => readout_controller_offset_en, + rd_en => readout_controller_rd_en, + busy => readout_controller_busy, + data_valid => readout_controller_data_valid, + data_out => readout_controller_data_out + ); + + data_read_slow : process (clk) is + begin + if rising_edge(clk) then + if rst = '1' then + slow_readout_fsm <= idle; + slow_read_done <= '0'; + slow_read_busy <= '0'; + start_readout_slow_to_buffer <= '0'; + else + start_readout_slow_to_buffer <= '0'; + slow_read_done <= '0'; + case slow_readout_fsm is + when idle => + slow_readout_fsm <= idle; + slow_read_busy <= '0'; + if start_slow_read = '1' then + start_readout_slow_to_buffer <= '1'; + slow_read_busy <= '1'; + slow_data <= (others => '0'); + slow_readout_fsm <= waitstate; + end if; + when waitstate => + slow_read_busy <= '1'; + if readout_controller_data_valid = '1' then + slow_read_done <= '1'; + slow_data <= readout_controller_data_out; + slow_readout_fsm <= idle; + end if; + end case; + end if; + end if; + end process data_read_slow; + + + ------------------------------------------------------------------------------------ + --Slow Control Handling + ------------------------------------------------------------------------------------ + --0x100: readout controller mode + --0x101: readout controller writes after trigger + --0x102: readout controller numbers of words to readout + --0x103: readout controller sensor id + --0x104: readout controller start slow readout (read only) + --0x105: fifo multiplexer mask + --0x106: fifo multiplexer input frequency (write select channel, read frequency) + --0x107: fifo multiplexer full (read-only) + --0x108: circular memory empty/full flags, fill cnt (read-only) + --0x109: circular memory input word frequency (read-only) + --0x10a: circular memory output word frequency (read-only) + --0x10b: readout controller read-enable (debug read-only) + ----------------------------------------------------------------------------------- + slv_bus_handler : process(clk) is + begin + if rising_edge(clk) then + if rst = '1' then + SLV_DATA_OUT <= (others => '0'); + SLV_ACK_OUT <= '0'; + SLV_NO_MORE_DATA_OUT <= '0'; + SLV_UNKNOWN_ADDR_OUT <= '0'; + start_slow_read <= '0'; + else + SLV_DATA_OUT <= (others => '0'); + SLV_ACK_OUT <= '0'; + SLV_NO_MORE_DATA_OUT <= '0'; + SLV_UNKNOWN_ADDR_OUT <= '0'; + start_slow_read <= '0'; + + if slow_read_busy = '1' then + if slow_read_done = '1' then + SLV_DATA_OUT <= slow_data; + SLV_ACK_OUT <= '1'; + end if; + + elsif SLV_WRITE_IN = '1' then + case SLV_ADDR_IN is + when x"0100" => + readout_mode_i <= SLV_DATA_IN(1 downto 0); + SLV_ACK_OUT <= '1'; + when x"0101" => + readout_writes_aft_trig <= SLV_DATA_IN(g_cyc_mem_address_width - 1 downto 0); + SLV_ACK_OUT <= '1'; + when x"0102" => + readout_words <= SLV_DATA_IN(g_cyc_mem_address_width - 1 downto 0); + SLV_ACK_OUT <= '1'; + when x"0103" => + sensor_id <= SLV_DATA_IN; + SLV_ACK_OUT <= '1'; + when x"0105" => + multiplexer_mask <= SLV_DATA_IN(g_mupix_links - 1 downto 0); + SLV_ACK_OUT <= '1'; + when x"0106" => + multiplexer_channel_sel <= to_integer(unsigned(SLV_DATA_IN)); + SLV_ACK_OUT <= '1'; + when others => + slv_unknown_addr_out <= '1'; + end case; + elsif SLV_READ_IN = '1' then + case SLV_ADDR_IN is + when x"0100" => + SLV_DATA_OUT(1 downto 0) <= readout_mode_i; + SLV_ACK_OUT <= '1'; + when x"0101" => + SLV_DATA_OUT(g_cyc_mem_address_width - 1 downto 0) <= readout_writes_aft_trig; + SLV_ACK_OUT <= '1'; + when x"0102" => + SLV_DATA_OUT(g_cyc_mem_address_width - 1 downto 0) <= readout_words; + SLV_ACK_OUT <= '1'; + when x"0103" => + SLV_DATA_OUT <= sensor_id; + SLV_ACK_OUT <= '1'; + when x"0104" => + if cycl_empty = '0' and readout_mode_i = "00" then + start_slow_read <= '1'; + else + SLV_NO_MORE_DATA_OUT <= '1'; + end if; + when x"0105" => + SLV_DATA_OUT(g_mupix_links - 1 downto 0) <= multiplexer_mask; + SLV_ACK_OUT <= '1'; + when x"0106" => + SLV_DATA_OUT <= wordin_freq((multiplexer_channel_sel + 1)*32 - 1 downto multiplexer_channel_sel*32); + SLV_ACK_OUT <= '1'; + when x"0107" => + SLV_DATA_OUT(0) <= fifo_full_o; + SLV_ACK_OUT <= '1'; + when x"0108" => + SLV_DATA_OUT(g_cyc_mem_address_width downto 0) <= cycl_fillcnt; + SLV_DATA_OUT(31) <= cycl_empty; + SLV_DATA_OUT(30) <= cycl_full; + SLV_ACK_OUT <= '1'; + when x"0109" => + SLV_DATA_OUT <= cycl_inword_freq; + SLV_ACK_OUT <= '1'; + when x"010a" => + SLV_DATA_OUT <= cycl_outword_freq; + SLV_ACK_OUT <= '1'; + when x"010b" => + SLV_DATA_OUT(3 downto 0) <= readout_controller_busy & start_readout & start_readout_slow_to_buffer & trb_trigger; + SLV_ACK_OUT <= '1'; + when others => + slv_unknown_addr_out <= '1'; + end case; + end if; + end if; + end if; + end process slv_bus_handler; + + busy <= readout_controller_busy; + dataout <= readout_controller_data_out; + data_valid <= readout_controller_data_valid; + end architecture; diff --git a/mupix/Mupix8/sources/ReadoutController.vhd b/mupix/Mupix8/sources/ReadoutController.vhd index fcc04f6..3206e58 100644 --- a/mupix/Mupix8/sources/ReadoutController.vhd +++ b/mupix/Mupix8/sources/ReadoutController.vhd @@ -16,195 +16,195 @@ use ieee.numeric_std.all; ----------------------------------------------------------------------------- entity ReadoutController is - generic( - g_datawidth : integer := 32; -- width of data words - g_addresswidth : integer := 10 -- width of address pointers, number of words is 2**g_addresswidth - ); - port( - clk : in std_logic; -- clock input - rst : in std_logic; -- reset input - start : in std_logic; -- start reading - mode : in std_logic_vector(1 downto 0); -- readout mode - writes_after_trig : in std_logic_vector(g_addresswidth - 1 downto 0); -- clock cycles after trigger before starting readout (needs to be at least two) - max_words : in std_logic_vector(g_addresswidth - 1 downto 0); -- maximum number of words to read - data_in : in std_logic_vector(g_datawidth - 1 downto 0); -- data from buffer - empty : in std_logic; --empty flag from circular buffer - almost_empty : in std_logic; --empty flag from circular buffer - sensor_id : in std_logic_vector(g_datawidth - 1 downto 0); - offset_en : out std_logic; -- set offset between read and write pointer (offset value is set directly in circular buffer) - rd_en : out std_logic; -- read enable to circular buffer - busy : out std_logic; -- readout controller busy - data_valid : out std_logic; -- data from readout controller valid - data_out : out std_logic_vector(g_datawidth - 1 downto 0)); -- data from readout controller + generic( + g_datawidth : integer := 32; -- width of data words + g_addresswidth : integer := 10 -- width of address pointers, number of words is 2**g_addresswidth + ); + port( + clk : in std_logic; -- clock input + rst : in std_logic; -- reset input + start : in std_logic; -- start reading + mode : in std_logic_vector(1 downto 0); -- readout mode + writes_after_trig : in std_logic_vector(g_addresswidth - 1 downto 0); -- clock cycles after trigger before starting readout (needs to be at least two) + max_words : in std_logic_vector(g_addresswidth - 1 downto 0); -- maximum number of words to read + data_in : in std_logic_vector(g_datawidth - 1 downto 0); -- data from buffer + empty : in std_logic; --empty flag from circular buffer + almost_empty : in std_logic; --empty flag from circular buffer + sensor_id : in std_logic_vector(g_datawidth - 1 downto 0); + offset_en : out std_logic; -- set offset between read and write pointer (offset value is set directly in circular buffer) + rd_en : out std_logic; -- read enable to circular buffer + busy : out std_logic; -- readout controller busy + data_valid : out std_logic; -- data from readout controller valid + data_out : out std_logic_vector(g_datawidth - 1 downto 0)); -- data from readout controller end entity ReadoutController; architecture RTL of ReadoutController is - constant c_frame_start : std_logic_vector(g_datawidth - 1 downto 0) := x"FABEABBA"; - constant c_frame_end : std_logic_vector(g_datawidth - 1 downto 0) := x"BEEFBEEF"; + constant c_frame_start : std_logic_vector(g_datawidth - 1 downto 0) := x"FABEABBA"; + constant c_frame_end : std_logic_vector(g_datawidth - 1 downto 0) := x"BEEFBEEF"; - --readout state type, in mode 1, 2 a header and trailer will be put - --at beginning and end of readout frame - type t_readout_state_type is (idle, header, read_single, read, wait_memory, wait_trigger, trailer); - signal readout_fsm : t_readout_state_type := idle; + --readout state type, in mode 1, 2 a header and trailer will be put + --at beginning and end of readout frame + type t_readout_state_type is (idle, header, read_single, read, wait_memory, wait_trigger, trailer); + signal readout_fsm : t_readout_state_type := idle; - signal wordcounter : unsigned(g_addresswidth - 1 downto 0) := (others => '0'); - signal framecounter : unsigned(31 downto 0) := (others => '0'); - signal headercounter : integer range 0 to 2 := 0; - signal trailercounter : integer range 0 to 1 := 0; - signal triggerwaitcounter : unsigned(g_addresswidth - 1 downto 0) := (others => '0'); - signal almost_empty_edge : std_logic_vector(1 downto 0) := (others => '0'); + signal wordcounter : unsigned(g_addresswidth - 1 downto 0) := (others => '0'); + signal framecounter : unsigned(31 downto 0) := (others => '0'); + signal headercounter : integer range 0 to 2 := 0; + signal trailercounter : integer range 0 to 1 := 0; + signal triggerwaitcounter : unsigned(g_addresswidth - 1 downto 0) := (others => '0'); + signal almost_empty_edge : std_logic_vector(1 downto 0) := (others => '0'); begin - edge_detection : process (clk) is - begin - if rising_edge(clk) then - if rst = '1' then - almost_empty_edge <= (others => '0'); - else - almost_empty_edge <= almost_empty_edge(0) & almost_empty; - end if; - end if; - end process edge_detection; - + edge_detection : process (clk) is + begin + if rising_edge(clk) then + if rst = '1' then + almost_empty_edge <= (others => '0'); + else + almost_empty_edge <= almost_empty_edge(0) & almost_empty; + end if; + end if; + end process edge_detection; - readout_proc : process(clk) is - begin - if rising_edge(clk) then - if rst = '1' then - readout_fsm <= idle; - rd_en <= '0'; - busy <= '0'; - data_valid <= '0'; - data_out <= (others => '0'); - framecounter <= (others => '0'); - headercounter <= 0; - else - busy <= '0'; - data_valid <= '0'; - data_out <= (others => '0'); - rd_en <= '0'; - offset_en <= '0'; - case readout_fsm is - when idle => - trailercounter <= 0; - wordcounter <= (others => '0'); - headercounter <= 0; - triggerwaitcounter <= (others => '0'); - headercounter <= 0; - if start = '1' then - busy <= '1'; - if mode = "00" then - if empty = '0' then - readout_fsm <= read_single; - else - data_out <= (others => '0'); - data_valid <= '1'; - readout_fsm <= idle; - end if; - elsif mode = "01" then - readout_fsm <= header; - elsif mode = "10" then - readout_fsm <= header; - else - readout_fsm <= idle; - end if; - else - readout_fsm <= idle; - end if; - when header => - busy <= '1'; - data_valid <= '1'; - headercounter <= headercounter + 1; - case headercounter is - when 0 => - data_out <= c_frame_start; - when 1 => - data_out <= sensor_id; - when 2 => - data_out <= std_logic_vector(framecounter); - framecounter <= framecounter + 1; - if mode = "01" then - if empty = '0' then - readout_fsm <= wait_memory; - rd_en <= '1'; - else - readout_fsm <= trailer; - end if; - else - readout_fsm <= wait_trigger; - end if; - end case; - when read_single => - data_valid <= '1'; - busy <= '1'; - rd_en <= '1'; - data_out <= data_in; - readout_fsm <= idle; - when wait_memory => - busy <= '1'; - if empty = '0' then - readout_fsm <= read; - rd_en <= '1'; - else - readout_fsm <= trailer; - rd_en <= '0'; - end if; - when read => - busy <= '1'; - data_valid <= '1'; - data_out <= data_in; - wordcounter <= wordcounter + 1; - readout_fsm <= read; - if mode = "01" then - if wordcounter < unsigned(max_words) - 2 and almost_empty = '0' then - rd_en <= '1'; - else - rd_en <= '0'; - end if; - if almost_empty_edge = "01" or wordcounter = unsigned(max_words) - 1 then - readout_fsm <= trailer; - end if; - else - if wordcounter < unsigned(max_words) - 2 and almost_empty = '0' then - rd_en <= '1'; - else - rd_en <= '0'; - end if; - if almost_empty_edge = "01" or wordcounter = unsigned(max_words) - 1 then - readout_fsm <= trailer; - end if; - end if; - when wait_trigger => - busy <= '1'; - offset_en <= '0'; - triggerwaitcounter <= triggerwaitcounter + 1; - if triggerwaitcounter = unsigned(writes_after_trig) - 1 then - if empty = '0' then - readout_fsm <= wait_memory; - rd_en <= '1'; - else - readout_fsm <= trailer; - end if; - end if; - if triggerwaitcounter = unsigned(writes_after_trig) - 2 then - offset_en <= '1'; - end if; - when trailer => - busy <= '1'; - data_valid <= '1'; - readout_fsm <= trailer; - trailercounter <= trailercounter + 1; - if trailercounter = 0 then - data_out(g_addresswidth - 1 downto 0) <= std_logic_vector(wordcounter); - else - data_out <= c_frame_end; - readout_fsm <= idle; - end if; - end case; - end if; - end if; - end process readout_proc; + + readout_proc : process(clk) is + begin + if rising_edge(clk) then + if rst = '1' then + readout_fsm <= idle; + rd_en <= '0'; + busy <= '0'; + data_valid <= '0'; + data_out <= (others => '0'); + framecounter <= (others => '0'); + headercounter <= 0; + else + busy <= '0'; + data_valid <= '0'; + data_out <= (others => '0'); + rd_en <= '0'; + offset_en <= '0'; + case readout_fsm is + when idle => + trailercounter <= 0; + wordcounter <= (others => '0'); + headercounter <= 0; + triggerwaitcounter <= (others => '0'); + headercounter <= 0; + if start = '1' then + busy <= '1'; + if mode = "00" then + if empty = '0' then + readout_fsm <= read_single; + else + data_out <= (others => '0'); + data_valid <= '1'; + readout_fsm <= idle; + end if; + elsif mode = "01" then + readout_fsm <= header; + elsif mode = "10" then + readout_fsm <= header; + else + readout_fsm <= idle; + end if; + else + readout_fsm <= idle; + end if; + when header => + busy <= '1'; + data_valid <= '1'; + headercounter <= headercounter + 1; + case headercounter is + when 0 => + data_out <= c_frame_start; + when 1 => + data_out <= sensor_id; + when 2 => + data_out <= std_logic_vector(framecounter); + framecounter <= framecounter + 1; + if mode = "01" then + if empty = '0' then + readout_fsm <= wait_memory; + rd_en <= '1'; + else + readout_fsm <= trailer; + end if; + else + readout_fsm <= wait_trigger; + end if; + end case; + when read_single => + data_valid <= '1'; + busy <= '1'; + rd_en <= '1'; + data_out <= data_in; + readout_fsm <= idle; + when wait_memory => + busy <= '1'; + if empty = '0' then + readout_fsm <= read; + rd_en <= '1'; + else + readout_fsm <= trailer; + rd_en <= '0'; + end if; + when read => + busy <= '1'; + data_valid <= '1'; + data_out <= data_in; + wordcounter <= wordcounter + 1; + readout_fsm <= read; + if mode = "01" then + if wordcounter < unsigned(max_words) - 2 and almost_empty = '0' then + rd_en <= '1'; + else + rd_en <= '0'; + end if; + if almost_empty_edge = "01" or wordcounter = unsigned(max_words) - 1 then + readout_fsm <= trailer; + end if; + else + if wordcounter < unsigned(max_words) - 2 and almost_empty = '0' then + rd_en <= '1'; + else + rd_en <= '0'; + end if; + if almost_empty_edge = "01" or wordcounter = unsigned(max_words) - 1 then + readout_fsm <= trailer; + end if; + end if; + when wait_trigger => + busy <= '1'; + offset_en <= '0'; + triggerwaitcounter <= triggerwaitcounter + 1; + if triggerwaitcounter = unsigned(writes_after_trig) - 1 then + if empty = '0' then + readout_fsm <= wait_memory; + rd_en <= '1'; + else + readout_fsm <= trailer; + end if; + end if; + if triggerwaitcounter = unsigned(writes_after_trig) - 2 then + offset_en <= '1'; + end if; + when trailer => + busy <= '1'; + data_valid <= '1'; + readout_fsm <= trailer; + trailercounter <= trailercounter + 1; + if trailercounter = 0 then + data_out(g_addresswidth - 1 downto 0) <= std_logic_vector(wordcounter); + else + data_out <= c_frame_end; + readout_fsm <= idle; + end if; + end case; + end if; + end if; + end process readout_proc; end architecture RTL; diff --git a/mupix/Mupix8/sources/TriggerHandler.vhd b/mupix/Mupix8/sources/TriggerHandler.vhd index 23f99ed..21175b8 100644 --- a/mupix/Mupix8/sources/TriggerHandler.vhd +++ b/mupix/Mupix8/sources/TriggerHandler.vhd @@ -12,45 +12,45 @@ use ieee.numeric_std.all; entity TriggerHandler is port ( - CLK_IN : in std_logic; - RESET_IN : in std_logic; - + CLK_IN : in std_logic; + RESET_IN : in std_logic; + --Input Triggers - TIMING_TRIGGER_IN : in std_logic; -- The raw timing Trigger Signal - LVL1_TRG_DATA_VALID_IN : in std_logic; -- Data Trigger is valid - LVL1_VALID_TIMING_TRG_IN : in std_logic; -- Timin Trigger is valid - LVL1_VALID_NOTIMING_TRG_IN : in std_logic; -- calib trigger w/o ref time - LVL1_INVALID_TRG_IN : in std_logic; - - LVL1_TRG_TYPE_IN : in std_logic_vector(3 downto 0); - LVL1_TRG_NUMBER_IN : in std_logic_vector(15 downto 0); - LVL1_TRG_CODE_IN : in std_logic_vector(7 downto 0); - + TIMING_TRIGGER_IN : in std_logic; -- The raw timing Trigger Signal + LVL1_TRG_DATA_VALID_IN : in std_logic; -- Data Trigger is valid + LVL1_VALID_TIMING_TRG_IN : in std_logic; -- Timin Trigger is valid + LVL1_VALID_NOTIMING_TRG_IN : in std_logic; -- calib trigger w/o ref time + LVL1_INVALID_TRG_IN : in std_logic; + + LVL1_TRG_TYPE_IN : in std_logic_vector(3 downto 0); + LVL1_TRG_NUMBER_IN : in std_logic_vector(15 downto 0); + LVL1_TRG_CODE_IN : in std_logic_vector(7 downto 0); + --Response from FEE - FEE_DATA_OUT : out std_logic_vector(31 downto 0); - FEE_DATA_WRITE_OUT : out std_logic; - FEE_DATA_FINISHED_OUT : out std_logic; - FEE_TRG_RELEASE_OUT : out std_logic; - FEE_TRG_STATUSBITS_OUT : out std_logic_vector(31 downto 0); - - FEE_DATA_0_IN : in std_logic_vector(31 downto 0); - FEE_DATA_WRITE_0_IN : in std_logic; - + FEE_DATA_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_WRITE_OUT : out std_logic; + FEE_DATA_FINISHED_OUT : out std_logic; + FEE_TRG_RELEASE_OUT : out std_logic; + FEE_TRG_STATUSBITS_OUT : out std_logic_vector(31 downto 0); + + FEE_DATA_0_IN : in std_logic_vector(31 downto 0); + FEE_DATA_WRITE_0_IN : in std_logic; + -- Trigger FeedBack - TRIGGER_BUSY_BUFFER_READ_IN : in std_logic; - + TRIGGER_BUSY_BUFFER_READ_IN : in std_logic; + -- OUT - VALID_TRIGGER_OUT : out std_logic; - + VALID_TRIGGER_OUT : out std_logic; + -- Slave bus - SLV_READ_IN : in std_logic; - SLV_WRITE_IN : in std_logic; - SLV_DATA_OUT : out std_logic_vector(31 downto 0); - SLV_DATA_IN : in std_logic_vector(31 downto 0); - SLV_ADDR_IN : in std_logic_vector(15 downto 0); - SLV_ACK_OUT : out std_logic; - SLV_NO_MORE_DATA_OUT : out std_logic; - SLV_UNKNOWN_ADDR_OUT : out std_logic); + SLV_READ_IN : in std_logic; + SLV_WRITE_IN : in std_logic; + SLV_DATA_OUT : out std_logic_vector(31 downto 0); + SLV_DATA_IN : in std_logic_vector(31 downto 0); + SLV_ADDR_IN : in std_logic_vector(15 downto 0); + SLV_ACK_OUT : out std_logic; + SLV_NO_MORE_DATA_OUT : out std_logic; + SLV_UNKNOWN_ADDR_OUT : out std_logic); end entity TriggerHandler; @@ -66,11 +66,11 @@ architecture behavioral of TriggerHandler is signal trigger_busy_int : std_logic := '0'; signal buffer_readout_end_int : std_logic_vector(1 downto 0) := "00"; --fee - signal fee_data_int : std_logic_vector(31 downto 0) := (others => '0'); - signal fee_data_write_int : std_logic := '0'; - signal fee_data_finished_int : std_logic := '0'; - signal fee_trg_release_int : std_logic := '0'; - signal fee_trg_statusbit_int : std_logic_vector(31 downto 0) := (others => '0'); + signal fee_data_int : std_logic_vector(31 downto 0) := (others => '0'); + signal fee_data_write_int : std_logic := '0'; + signal fee_data_finished_int : std_logic := '0'; + signal fee_trg_release_int : std_logic := '0'; + signal fee_trg_statusbit_int : std_logic_vector(31 downto 0) := (others => '0'); --event buffer --registers @@ -84,7 +84,7 @@ architecture behavioral of TriggerHandler is signal invalid_trigger_counter_t : unsigned(31 downto 0) := (others => '0'); signal valid_trigger_counter_t : unsigned(31 downto 0) := (others => '0'); signal trigger_handler_state : std_logic_vector(7 downto 0) := (others => '0'); - + --trigger types constant c_trigger_physics_type : std_logic_vector(3 downto 0) := x"1"; constant c_trigger_status_type : std_logic_vector(3 downto 0) := x"e"; @@ -103,7 +103,7 @@ architecture behavioral of TriggerHandler is ignore, wait_trigger_data_valid_a, wait_trigger_data_valid_b); - + type trigger_type_type is (t_timing, t_physics, t_status, @@ -116,218 +116,227 @@ architecture behavioral of TriggerHandler is signal wr_data_int : std_logic := '0'; signal wr_status_int : std_logic := '0'; signal wr_dummy_int : std_logic := '0'; - + begin - + Signal_Edge_Detect : process(CLK_IN) is - begin -- process Mupix_Readout_End_Detect - if rising_edge(CLK_IN) then - if reset_in = '1' then - buffer_readout_end_int <= (others => '0'); - timing_trigger_edge <= (others => '0'); - reset_trigger_state_edge <= (others => '0'); - else - buffer_readout_end_int <= buffer_readout_end_int(0) & TRIGGER_BUSY_BUFFER_READ_IN; - timing_trigger_edge <= timing_trigger_edge(0) & TIMING_TRIGGER_IN; - reset_trigger_state_edge <= reset_trigger_state_edge(1) & reset_trigger_state; - end if; - end if; - end process Signal_Edge_Detect; - - ------------------------------------------------------------ - --Handling of LVL1 triggers - ------------------------------------------------------------ - trigger_handler_proc : process(clk_in) is - begin -- process trigger_handler_proc - if rising_edge(CLK_IN) then - if reset_in = '1' or LVL1_INVALID_TRG_IN = '1' or reset_trigger_state_edge = "01" then - valid_trigger_int <= '0'; - fee_data_finished_int <= '0'; - fee_trg_release_int <= '0'; - fee_trg_statusbit_int <= (others => '0'); - trigger_busy_int <= '1'; - fee_trg_release_int <= '0'; - wr_header_int <= '0'; - wr_data_int <= '0'; - wr_status_int <= '0'; - wr_dummy_int <= '0'; - else - case trigger_handler_fsm is - when idle => - trigger_busy_int <= '0'; - trigger_handler_state <= x"01"; - if LVL1_VALID_TIMING_TRG_IN = '1' then - wr_header_int <= '1'; - if bypass_trigger = '1' then - trigger_type <= t_ignore; - trigger_handler_fsm <= ignore; - else - trigger_type <= t_timing; - trigger_handler_fsm <= timing_trigger; - end if; - elsif (LVL1_VALID_NOTIMING_TRG_IN = '1') then - wr_header_int <= '1'; - if bypass_trigger = '1' then - trigger_type <= t_ignore; - trigger_handler_fsm <= ignore; - else - trigger_handler_fsm <= check_trigger_type; - end if; - end if; - - when check_trigger_type => - trigger_handler_state <= x"02"; - if (LVL1_TRG_DATA_VALID_IN = '1') then - if (LVL1_TRG_TYPE_IN = c_trigger_status_type) then - trigger_type <= t_status; - trigger_handler_fsm <= no_timing_trigger; - elsif (LVL1_TRG_TYPE_IN = c_trigger_physics_type) then - trigger_type <= t_physics; - trigger_handler_fsm <= no_timing_trigger; - else - --unknown trigger - trigger_type <= t_unknown; - trigger_handler_fsm <= no_timing_trigger; - end if; - else - trigger_handler_fsm <= check_trigger_type; - end if; - - when timing_trigger => --starts mupix readout fsm - trigger_handler_state <= x"03"; - valid_trigger_int <= '1'; - trigger_handler_fsm <= write_data_to_ipu; - - when no_timing_trigger => - trigger_handler_state <= x"04"; - if trigger_type = t_physics then - trigger_handler_fsm <= timing_trigger; - elsif trigger_type = t_status then - trigger_handler_fsm <= status_trigger; - else - trigger_handler_fsm <= ignore; - end if; - - when ignore => - wr_dummy_int <= '1'; --write a dummy value to identify inactive FEE - trigger_handler_state <= x"05"; - trigger_handler_fsm <= wait_trigger_data_valid_b; - - when status_trigger => --dummy implementation - trigger_handler_state <= x"06"; - wr_status_int <= '1'; - trigger_handler_fsm <= wait_trigger_data_valid_b; - - when write_data_to_ipu => - trigger_handler_state <= x"0A"; - wr_data_int <= '1'; - if buffer_readout_end_int = "10" then - wr_data_int <= '0'; - trigger_handler_fsm <= wait_trigger_data_valid_a; - else - trigger_handler_fsm <= write_data_to_ipu; - end if; - - when wait_trigger_data_valid_a => - trigger_handler_state <= x"0B"; - if LVL1_TRG_DATA_VALID_IN = '1' then - trigger_handler_fsm <= wait_trigger_data_valid_b; - end if; - - when wait_trigger_data_valid_b => - trigger_handler_state <= x"0C"; - trigger_handler_fsm <= trigger_release_a; - - when trigger_release_a => - trigger_handler_state <= x"0D"; - trigger_handler_fsm <= trigger_release_b; - - when trigger_release_b => - trigger_handler_state <= x"0E"; - fee_data_finished_int <= '1'; - trigger_handler_fsm <= trigger_release_c; - - when trigger_release_c => - trigger_handler_state <= x"0F"; - fee_trg_release_int <= '1'; - trigger_handler_fsm <= wait_trigger_release; - - when wait_trigger_release => - if (LVL1_TRG_DATA_VALID_IN = '1') then - trigger_handler_fsm <= wait_trigger_release; - else - trigger_handler_fsm <= idle; - end if; - end case; - end if; - end if; - end process trigger_handler_proc; + begin -- process Mupix_Readout_End_Detect + if rising_edge(CLK_IN) then + if reset_in = '1' then + buffer_readout_end_int <= (others => '0'); + timing_trigger_edge <= (others => '0'); + reset_trigger_state_edge <= (others => '0'); + else + buffer_readout_end_int <= buffer_readout_end_int(0) & TRIGGER_BUSY_BUFFER_READ_IN; + timing_trigger_edge <= timing_trigger_edge(0) & TIMING_TRIGGER_IN; + reset_trigger_state_edge <= reset_trigger_state_edge(1) & reset_trigger_state; + end if; + end if; + end process Signal_Edge_Detect; + + ------------------------------------------------------------ + --Handling of LVL1 triggers + ------------------------------------------------------------ + trigger_handler_proc : process(clk_in) is + begin -- process trigger_handler_proc + if rising_edge(CLK_IN) then + trigger_busy_int <= '1'; + fee_trg_release_int <= '0'; + wr_header_int <= '0'; + wr_data_int <= '0'; + wr_status_int <= '0'; + wr_dummy_int <= '0'; + valid_trigger_int <= '0'; + fee_data_finished_int <= '0'; + fee_trg_release_int <= '0'; + if reset_in = '1' or LVL1_INVALID_TRG_IN = '1' or reset_trigger_state_edge = "01" then + valid_trigger_int <= '0'; + fee_data_finished_int <= '0'; + fee_trg_release_int <= '0'; + fee_trg_statusbit_int <= (others => '0'); + trigger_busy_int <= '1'; + fee_trg_release_int <= '0'; + wr_header_int <= '0'; + wr_data_int <= '0'; + wr_status_int <= '0'; + wr_dummy_int <= '0'; + else + case trigger_handler_fsm is + when idle => + trigger_busy_int <= '0'; + trigger_handler_state <= x"01"; + if LVL1_VALID_TIMING_TRG_IN = '1' then + wr_header_int <= '1'; + if bypass_trigger = '1' then + trigger_type <= t_ignore; + trigger_handler_fsm <= ignore; + else + trigger_type <= t_timing; + trigger_handler_fsm <= timing_trigger; + end if; + elsif (LVL1_VALID_NOTIMING_TRG_IN = '1') then + wr_header_int <= '1'; + if bypass_trigger = '1' then + trigger_type <= t_ignore; + trigger_handler_fsm <= ignore; + else + trigger_handler_fsm <= check_trigger_type; + end if; + end if; + + when check_trigger_type => + trigger_handler_state <= x"02"; + if (LVL1_TRG_DATA_VALID_IN = '1') then + if (LVL1_TRG_TYPE_IN = c_trigger_status_type) then + trigger_type <= t_status; + trigger_handler_fsm <= no_timing_trigger; + elsif (LVL1_TRG_TYPE_IN = c_trigger_physics_type) then + trigger_type <= t_physics; + trigger_handler_fsm <= no_timing_trigger; + else + --unknown trigger + trigger_type <= t_unknown; + trigger_handler_fsm <= no_timing_trigger; + end if; + else + trigger_handler_fsm <= check_trigger_type; + end if; + + when timing_trigger => --starts mupix readout fsm + trigger_handler_state <= x"03"; + valid_trigger_int <= '1'; + trigger_handler_fsm <= write_data_to_ipu; + + when no_timing_trigger => + trigger_handler_state <= x"04"; + if trigger_type = t_physics then + trigger_handler_fsm <= timing_trigger; + elsif trigger_type = t_status then + trigger_handler_fsm <= status_trigger; + else + trigger_handler_fsm <= ignore; + end if; + + when ignore => + wr_dummy_int <= '1'; --write a dummy value to identify inactive FEE + trigger_handler_state <= x"05"; + trigger_handler_fsm <= wait_trigger_data_valid_b; + + when status_trigger => --dummy implementation + trigger_handler_state <= x"06"; + wr_status_int <= '1'; + trigger_handler_fsm <= wait_trigger_data_valid_b; + + when write_data_to_ipu => + trigger_handler_state <= x"0A"; + wr_data_int <= '1'; + if buffer_readout_end_int = "10" then + wr_data_int <= '0'; + trigger_handler_fsm <= wait_trigger_data_valid_a; + else + trigger_handler_fsm <= write_data_to_ipu; + end if; + + when wait_trigger_data_valid_a => + trigger_handler_state <= x"0B"; + if LVL1_TRG_DATA_VALID_IN = '1' then + trigger_handler_fsm <= wait_trigger_data_valid_b; + end if; + + when wait_trigger_data_valid_b => + trigger_handler_state <= x"0C"; + trigger_handler_fsm <= trigger_release_a; + + when trigger_release_a => + trigger_handler_state <= x"0D"; + trigger_handler_fsm <= trigger_release_b; + + when trigger_release_b => + trigger_handler_state <= x"0E"; + fee_data_finished_int <= '1'; + trigger_handler_fsm <= trigger_release_c; + + when trigger_release_c => + trigger_handler_state <= x"0F"; + fee_trg_release_int <= '1'; + trigger_handler_fsm <= wait_trigger_release; + + when wait_trigger_release => + if (LVL1_TRG_DATA_VALID_IN = '1') then + trigger_handler_fsm <= wait_trigger_release; + else + trigger_handler_fsm <= idle; + end if; + end case; + end if; + end if; + end process trigger_handler_proc; ------------------------------------------------------------ --Data Output Mux ------------------------------------------------------------ Data_Out_Mux : process(clk_in) is - begin -- process Data_Out_Mux - if rising_edge(clk_in) then - if Reset_in = '1' then - fee_data_write_int <= '0'; - fee_data_int <= (others => '0'); - else - if wr_header_int = '1' then - fee_data_write_int <= '1'; --header see Hades DAQ user guide - fee_data_int <= "001" & "0" & LVL1_TRG_TYPE_IN & LVL1_TRG_CODE_IN & LVL1_TRG_NUMBER_IN; - elsif wr_data_int = '1' then - fee_data_write_int <= FEE_DATA_WRITE_0_IN; - fee_data_int <= FEE_DATA_0_IN; - elsif wr_status_int = '1' then - fee_data_int <= x"deadbeef"; - fee_data_write_int <= '1'; - elsif wr_dummy_int = '1' then - fee_data_write_int <= '1'; - fee_data_int <= x"fff00000"; - else - fee_data_write_int <= '0'; - fee_data_int <= (others => '1'); - end if; - end if; - end if; - end process Data_Out_Mux; - - + begin -- process Data_Out_Mux + if rising_edge(clk_in) then + if Reset_in = '1' then + fee_data_write_int <= '0'; + fee_data_int <= (others => '0'); + else + if wr_header_int = '1' then + fee_data_write_int <= '1'; --header see Hades DAQ user guide + fee_data_int <= "001" & "0" & LVL1_TRG_TYPE_IN & LVL1_TRG_CODE_IN & LVL1_TRG_NUMBER_IN; + elsif wr_data_int = '1' then + fee_data_write_int <= FEE_DATA_WRITE_0_IN; + fee_data_int <= FEE_DATA_0_IN; + elsif wr_status_int = '1' then + fee_data_int <= x"deadbeef"; + fee_data_write_int <= '1'; + elsif wr_dummy_int = '1' then + fee_data_write_int <= '1'; + fee_data_int <= x"ffeeddcc"; + else + fee_data_write_int <= '0'; + fee_data_int <= (others => '1'); + end if; + end if; + end if; + end process Data_Out_Mux; + + ------------------------------------------------------------ - --Trigger statistics - ------------------------------------------------------------ - Trigger_Statistics_Proc : process(clk_in) is - begin -- process Trigger_Statistics_Proc - if rising_edge(CLK_IN) then - reset_trigger_counters_edge <= reset_trigger_counters_edge(0) & reset_trigger_counters; - if reset_trigger_counters_edge = "01" or RESET_IN = '1' then - trigger_rate_acc <= (others => '0'); - invalid_trigger_counter_t <= (others => '0'); - valid_trigger_counter_t <= (others => '0'); - trigger_rate_time_counter <= (others => '0'); - else - if trigger_rate_time_counter < x"5f5e100" then --1s at 10ns clock period - --if trigger_rate_time_counter < x"000007e" then - trigger_rate_time_counter <= trigger_rate_time_counter + 1; - if valid_trigger_int = '1' then - valid_trigger_counter_t <= valid_trigger_counter_t + 1; - elsif LVL1_INVALID_TRG_IN = '1' or (trigger_busy_int = '1' and timing_trigger_edge = "01") then - invalid_trigger_counter_t <= invalid_trigger_counter_t + 1; - end if; - else - valid_trigger_counter <= valid_trigger_counter + valid_trigger_counter_t; - invalid_trigger_counter <= invalid_trigger_counter + invalid_trigger_counter_t; - trigger_rate_acc <= valid_trigger_counter_t; - trigger_rate_tot <= valid_trigger_counter_t + invalid_trigger_counter_t; - trigger_rate_time_counter <= (others => '0'); - valid_trigger_counter_t <= (others => '0'); - invalid_trigger_counter_t <= (others => '0'); - end if; - end if; - end if; - end process Trigger_Statistics_Proc; - + --Trigger statistics + ------------------------------------------------------------ + Trigger_Statistics_Proc : process(clk_in) is + begin -- process Trigger_Statistics_Proc + if rising_edge(CLK_IN) then + reset_trigger_counters_edge <= reset_trigger_counters_edge(0) & reset_trigger_counters; + if reset_trigger_counters_edge = "01" or RESET_IN = '1' then + trigger_rate_acc <= (others => '0'); + invalid_trigger_counter_t <= (others => '0'); + valid_trigger_counter_t <= (others => '0'); + trigger_rate_time_counter <= (others => '0'); + else + if trigger_rate_time_counter < x"5f5e100" then --1s at 10ns clock period + --if trigger_rate_time_counter < x"000007e" then + trigger_rate_time_counter <= trigger_rate_time_counter + 1; + if valid_trigger_int = '1' then + valid_trigger_counter_t <= valid_trigger_counter_t + 1; + elsif LVL1_INVALID_TRG_IN = '1' or (trigger_busy_int = '1' and timing_trigger_edge = "01") then + invalid_trigger_counter_t <= invalid_trigger_counter_t + 1; + end if; + else + valid_trigger_counter <= valid_trigger_counter + valid_trigger_counter_t; + invalid_trigger_counter <= invalid_trigger_counter + invalid_trigger_counter_t; + trigger_rate_acc <= valid_trigger_counter_t; + trigger_rate_tot <= valid_trigger_counter_t + invalid_trigger_counter_t; + trigger_rate_time_counter <= (others => '0'); + valid_trigger_counter_t <= (others => '0'); + invalid_trigger_counter_t <= (others => '0'); + end if; + end if; + end if; + end process Trigger_Statistics_Proc; + ------------------------------------------------------------ --TRB SLV-BUS Hanlder ------------------------------------------------------------ @@ -339,63 +348,63 @@ begin --0x125: reset counters --0x126: reset trigger state machine --0x127: bypass trigger signals flag - slv_bus_handler : process(CLK_IN) - begin - if rising_edge(CLK_IN) then - - slv_data_out <= (others => '0'); - slv_ack_out <= '0'; - slv_no_more_data_out <= '0'; - slv_unknown_addr_out <= '0'; - - if slv_write_in = '1' then - case SLV_ADDR_IN is - when x"0125" => - reset_trigger_counters <= SLV_DATA_IN(0); - slv_ack_out <= '1'; - when x"0126" => - reset_trigger_state <= SLV_DATA_IN(0); - slv_ack_out <= '1'; - when x"0127" => - bypass_trigger <= SLV_DATA_IN(0); - slv_ack_out <= '1'; - when others => - slv_unknown_addr_out <= '1'; - end case; - - elsif slv_read_in = '1' then - case slv_addr_in is - when x"0120" => - slv_data_out <= std_logic_vector(trigger_rate_acc); - slv_ack_out <= '1'; - when x"0121" => - slv_data_out <= std_logic_vector(trigger_rate_tot); - slv_ack_out <= '1'; - when x"0122" => - slv_data_out <= std_logic_vector(invalid_trigger_counter); - slv_ack_out <= '1'; - when x"0123" => - slv_data_out <= std_logic_vector(valid_trigger_counter); - slv_ack_out <= '1'; - when x"0124" => - slv_data_out <= x"000000" & trigger_handler_state; - slv_ack_out <= '1'; - when x"0127" => - slv_data_out(0) <= bypass_trigger; - slv_ack_out <= '1'; - when others => - slv_unknown_addr_out <= '1'; - end case; - end if; - end if; - end process slv_bus_handler; + slv_bus_handler : process(CLK_IN) + begin + if rising_edge(CLK_IN) then + + slv_data_out <= (others => '0'); + slv_ack_out <= '0'; + slv_no_more_data_out <= '0'; + slv_unknown_addr_out <= '0'; + + if slv_write_in = '1' then + case SLV_ADDR_IN is + when x"0125" => + reset_trigger_counters <= SLV_DATA_IN(0); + slv_ack_out <= '1'; + when x"0126" => + reset_trigger_state <= SLV_DATA_IN(0); + slv_ack_out <= '1'; + when x"0127" => + bypass_trigger <= SLV_DATA_IN(0); + slv_ack_out <= '1'; + when others => + slv_unknown_addr_out <= '1'; + end case; + + elsif slv_read_in = '1' then + case slv_addr_in is + when x"0120" => + slv_data_out <= std_logic_vector(trigger_rate_acc); + slv_ack_out <= '1'; + when x"0121" => + slv_data_out <= std_logic_vector(trigger_rate_tot); + slv_ack_out <= '1'; + when x"0122" => + slv_data_out <= std_logic_vector(invalid_trigger_counter); + slv_ack_out <= '1'; + when x"0123" => + slv_data_out <= std_logic_vector(valid_trigger_counter); + slv_ack_out <= '1'; + when x"0124" => + slv_data_out <= x"000000" & trigger_handler_state; + slv_ack_out <= '1'; + when x"0127" => + slv_data_out(0) <= bypass_trigger; + slv_ack_out <= '1'; + when others => + slv_unknown_addr_out <= '1'; + end case; + end if; + end if; + end process slv_bus_handler; --map output signals - valid_trigger_out <= valid_trigger_int; - fee_data_out <= fee_data_int; - fee_data_write_out <= fee_data_write_int; - fee_data_finished_out <= fee_data_finished_int; - fee_trg_release_out <= fee_trg_release_int; + valid_trigger_out <= valid_trigger_int; + fee_data_out <= fee_data_int; + fee_data_write_out <= fee_data_write_int; + fee_data_finished_out <= fee_data_finished_int; + fee_trg_release_out <= fee_trg_release_int; fee_trg_statusbits_out <= fee_trg_statusbit_int; end architecture behavioral; diff --git a/mupix/Mupix8/tb/MupixTRBReadoutAndTriggerTest.vhd b/mupix/Mupix8/tb/MupixTRBReadoutAndTriggerTest.vhd new file mode 100644 index 0000000..2bfbaa6 --- /dev/null +++ b/mupix/Mupix8/tb/MupixTRBReadoutAndTriggerTest.vhd @@ -0,0 +1,392 @@ +--Test bench for combined trigger and mupix trb readout +--note that some code for the slow control is omitted and not all signals will +--work as expected +--T. Weber +--Ruhr Universität Bochum + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.numeric_std.all; + +entity TriggerAndReadout is + port ( + clk : in std_logic; + reset : in std_logic; + + --trigger signals + timing_trg_in : in std_logic; + lvl1_trg_data_valid_in : in std_logic; + lvl1_valid_timing_trg_in : in std_logic; + lvl1_valid_notiming_trg_in : in std_logic; + lvl1_invalid_trg_in : in std_logic; + lvl1_trg_type_in : in std_logic_vector(3 downto 0); + lvl1_trg_number_in : in std_logic_vector(15 downto 0); + lvl1_trg_code_in : in std_logic_vector(7 downto 0); + lvl1_trg_information_in : in std_logic_vector(23 downto 0); + lvl1_int_trg_number_in : in std_logic_vector(15 downto 0); + + --TRB data connections + fee_trg_release_out : out std_logic; + fee_trg_statusbits_out : out std_logic_vector(31 downto 0); + fee_data_out : out std_logic_vector(31 downto 0); + fee_data_write_out : out std_logic; + fee_data_finished_out : out std_logic; + fee_data_almost_full_in : in std_logic; + + --Slow Control signals (slightly simplified) + slv_addr_in : in std_logic_vector(15 downto 0); + slv_data_in : in std_logic_vector(31 downto 0); + slv_data_out : out std_logic_vector(31 downto 0); + slv_read_enable_in : in std_logic; + slv_write_enable_in : in std_logic; + slv_ack_out : out std_logic; + slv_no_more_data_out : out std_logic; + slv_unknown_addr_out : out std_logic; + + --Pseudo Data Inputs + data_wr_enable : in std_logic_vector(3 downto 0); + data_in : in std_logic_vector(127 downto 0)); +end entity TriggerAndReadout; + + +architecture behavorial of TriggerAndReadout is + + component TriggerHandler is + port ( + CLK_IN : in std_logic; + RESET_IN : in std_logic; + TIMING_TRIGGER_IN : in std_logic; + LVL1_TRG_DATA_VALID_IN : in std_logic; + LVL1_VALID_TIMING_TRG_IN : in std_logic; + LVL1_VALID_NOTIMING_TRG_IN : in std_logic; + LVL1_INVALID_TRG_IN : in std_logic; + LVL1_TRG_TYPE_IN : in std_logic_vector(3 downto 0); + LVL1_TRG_NUMBER_IN : in std_logic_vector(15 downto 0); + LVL1_TRG_CODE_IN : in std_logic_vector(7 downto 0); + FEE_DATA_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_WRITE_OUT : out std_logic; + FEE_DATA_FINISHED_OUT : out std_logic; + FEE_TRG_RELEASE_OUT : out std_logic; + FEE_TRG_STATUSBITS_OUT : out std_logic_vector(31 downto 0); + FEE_DATA_0_IN : in std_logic_vector(31 downto 0); + FEE_DATA_WRITE_0_IN : in std_logic; + TRIGGER_BUSY_BUFFER_READ_IN : in std_logic; + VALID_TRIGGER_OUT : out std_logic; + SLV_READ_IN : in std_logic; + SLV_WRITE_IN : in std_logic; + SLV_DATA_OUT : out std_logic_vector(31 downto 0); + SLV_DATA_IN : in std_logic_vector(31 downto 0); + SLV_ADDR_IN : in std_logic_vector(15 downto 0); + SLV_ACK_OUT : out std_logic; + SLV_NO_MORE_DATA_OUT : out std_logic; + SLV_UNKNOWN_ADDR_OUT : out std_logic); + end component TriggerHandler; + + component MupixTRBReadout is + generic ( + g_mupix_links : natural; + g_cyc_mem_address_width : integer; + g_datawidth : integer); + port ( + clk : in std_logic; + rst : in std_logic; + fifo_empty : in std_logic_vector(g_mupix_links - 1 downto 0); + fifo_full : in std_logic_vector(g_mupix_links - 1 downto 0); + fifo_datain : in std_logic_vector(g_mupix_links*g_datawidth - 1 downto 0); + fifo_rden : out std_logic_vector(g_mupix_links - 1 downto 0); + trb_trigger : in std_logic; + dataout : out std_logic_vector(g_datawidth - 1 downto 0); + data_valid : out std_logic; + busy : out std_logic; + SLV_READ_IN : in std_logic; + SLV_WRITE_IN : in std_logic; + SLV_DATA_OUT : out std_logic_vector(31 downto 0); + SLV_DATA_IN : in std_logic_vector(31 downto 0); + SLV_ADDR_IN : in std_logic_vector(15 downto 0); + SLV_ACK_OUT : out std_logic; + SLV_NO_MORE_DATA_OUT : out std_logic; + SLV_UNKNOWN_ADDR_OUT : out std_logic); + end component MupixTRBReadout; + + component STD_FIFO is + generic ( + data_width : positive; + fifo_depth : positive); + port ( + clk : in std_logic; + rst : in std_logic; + writeen : in std_logic; + datain : in std_logic_vector (data_width - 1 downto 0); + readen : in std_logic; + dataout : out std_logic_vector (data_width - 1 downto 0); + empty : out std_logic; + full : out std_logic); + end component STD_FIFO; + + constant c_mupix_links : integer := 4; + + -- signals between trigger and and TRB Readout + signal fee_data_i : std_logic_vector(31 downto 0); + signal fee_data_write_i : std_logic; + signal trigger_buffer_busy_i : std_logic; + signal valid_trigger_i : std_logic; + + -- signals between FIFOs and TRB Readout + signal fifo_full_i : std_logic_vector(c_mupix_links - 1 downto 0); + signal fifo_empty_i : std_logic_vector(c_mupix_links - 1 downto 0); + signal fifo_rden_i : std_logic_vector(c_mupix_links - 1 downto 0); + signal fifo_dataout_i : std_logic_vector(c_mupix_links*32 - 1 downto 0); + +begin -- architecture behavorial + + TriggerHandler_1 : entity work.TriggerHandler + port map ( + clk_in => clk, + reset_in => reset, + timing_trigger_in => timing_trg_in, + lvl1_trg_data_valid_in => lvl1_trg_data_valid_in, + lvl1_valid_timing_trg_in => lvl1_valid_timing_trg_in, + lvl1_valid_notiming_trg_in => lvl1_valid_notiming_trg_in, + lvl1_invalid_trg_in => lvl1_invalid_trg_in, + lvl1_trg_type_in => lvl1_trg_type_in, + lvl1_trg_number_in => lvl1_trg_number_in, + lvl1_trg_code_in => lvl1_trg_code_in, + fee_data_out => fee_data_out, + fee_data_write_out => fee_data_write_out, + fee_data_finished_out => fee_data_finished_out, + fee_trg_release_out => fee_trg_release_out, + fee_trg_statusbits_out => fee_trg_statusbits_out, + fee_data_0_in => fee_data_i, + fee_data_write_0_in => fee_data_write_i, + trigger_busy_buffer_read_in => trigger_buffer_busy_i, + valid_trigger_out => valid_trigger_i, + slv_read_in => slv_read_enable_in, + slv_write_in => slv_write_enable_in, + slv_data_out => slv_data_out, + slv_data_in => slv_data_in, + slv_addr_in => slv_addr_in, + slv_ack_out => slv_ack_out, + slv_no_more_data_out => slv_no_more_data_out, + slv_unknown_addr_out => slv_unknown_addr_out); + + MupixTRBReadout_1 : entity work.MupixTRBReadout + generic map ( + g_mupix_links => c_mupix_links, + g_cyc_mem_address_width => 8, + g_datawidth => 32) + port map ( + clk => clk, + rst => reset, + fifo_empty => fifo_empty_i, + fifo_full => fifo_full_i, + fifo_datain => fifo_dataout_i, + fifo_rden => fifo_rden_i, + trb_trigger => valid_trigger_i, + dataout => fee_data_i, + data_valid => fee_data_write_i, + busy => trigger_buffer_busy_i, + slv_read_in => slv_read_enable_in, + slv_write_in => slv_write_enable_in, + slv_data_out => slv_data_out, + slv_data_in => slv_data_in, + slv_addr_in => slv_addr_in, + slv_ack_out => slv_ack_out, + slv_no_more_data_out => slv_no_more_data_out, + slv_unknown_addr_out => slv_unknown_addr_out); + + fifo_gen : for J in 0 to 3 generate + STD_FIFO : entity work.STD_FIFO + generic map ( + data_width => 32, + fifo_depth => 16) + port map ( + clk => clk, + rst => reset, + writeen => data_wr_enable(J), + datain => data_in((J + 1)*32 - 1 downto J*32), + readen => fifo_rden_i(J), + dataout => fifo_dataout_i((J + 1)*32 - 1 downto J*32), + empty => fifo_empty_i(J), + full => fifo_full_i(J)); + end generate fifo_gen; + +end architecture behavorial; + + +library IEEE; +use IEEE.STD_LOGIC_1164.all; +use IEEE.numeric_std.all; + +entity ReadoutAndTriggerTest is +end entity ReadoutAndTriggerTest; + + +architecture sim of ReadoutAndTriggerTest is + + component TriggerAndReadout is + port ( + clk : in std_logic; + reset : in std_logic; + timing_trg_in : in std_logic; + lvl1_trg_data_valid_in : in std_logic; + lvl1_valid_timing_trg_in : in std_logic; + lvl1_valid_notiming_trg_in : in std_logic; + lvl1_invalid_trg_in : in std_logic; + lvl1_trg_type_in : in std_logic_vector(3 downto 0); + lvl1_trg_number_in : in std_logic_vector(15 downto 0); + lvl1_trg_code_in : in std_logic_vector(7 downto 0); + lvl1_trg_information_in : in std_logic_vector(23 downto 0); + lvl1_int_trg_number_in : in std_logic_vector(15 downto 0); + fee_trg_release_out : out std_logic; + fee_trg_statusbits_out : out std_logic_vector(31 downto 0); + fee_data_out : out std_logic_vector(31 downto 0); + fee_data_write_out : out std_logic; + fee_data_finished_out : out std_logic; + fee_data_almost_full_in : in std_logic; + slv_addr_in : in std_logic_vector(15 downto 0); + slv_data_in : in std_logic_vector(31 downto 0); + slv_data_out : out std_logic_vector(31 downto 0); + slv_read_enable_in : in std_logic; + slv_write_enable_in : in std_logic; + slv_ack_out : out std_logic; + slv_no_more_data_out : out std_logic; + slv_unknown_addr_out : out std_logic; + data_wr_enable : in std_logic_vector(3 downto 0); + data_in : in std_logic_vector(127 downto 0)); + end component TriggerAndReadout; + + constant clk_period : time := 10 ns; + + signal clk : std_logic := '0'; + signal reset : std_logic := '0'; + signal timing_trg_in : std_logic := '0'; + signal lvl1_trg_data_valid_in : std_logic := '0'; + signal lvl1_valid_timing_trg_in : std_logic := '0'; + signal lvl1_valid_notiming_trg_in : std_logic := '0'; + signal lvl1_invalid_trg_in : std_logic := '0'; + signal lvl1_trg_type_in : std_logic_vector(3 downto 0) := (others => '0'); + signal lvl1_trg_number_in : std_logic_vector(15 downto 0) := (others => '0'); + signal lvl1_trg_code_in : std_logic_vector(7 downto 0) := (others => '0'); + signal lvl1_trg_information_in : std_logic_vector(23 downto 0) := (others => '0'); + signal lvl1_int_trg_number_in : std_logic_vector(15 downto 0) := (others => '0'); + signal fee_trg_release_out : std_logic; + signal fee_trg_statusbits_out : std_logic_vector(31 downto 0); + signal fee_data_out : std_logic_vector(31 downto 0); + signal fee_data_write_out : std_logic; + signal fee_data_finished_out : std_logic; + signal fee_data_almost_full_in : std_logic := '0'; + signal slv_addr_in : std_logic_vector(15 downto 0) := (others => '0'); + signal slv_data_in : std_logic_vector(31 downto 0) := (others => '0'); + signal slv_data_out : std_logic_vector(31 downto 0) := (others => '0'); + signal slv_read_enable_in : std_logic := '0'; + signal slv_write_enable_in : std_logic := '0'; + signal slv_ack_out : std_logic; + signal slv_no_more_data_out : std_logic; + signal slv_unknown_addr_out : std_logic; + signal data_wr_enable : std_logic_vector(3 downto 0) := (others => '0'); + signal data_in : std_logic_vector(127 downto 0) := (others => '0'); + +begin -- architecture sim + + TriggerAndReadout_1 : entity work.TriggerAndReadout + port map ( + clk => clk, + reset => reset, + timing_trg_in => timing_trg_in, + lvl1_trg_data_valid_in => lvl1_trg_data_valid_in, + lvl1_valid_timing_trg_in => lvl1_valid_timing_trg_in, + lvl1_valid_notiming_trg_in => lvl1_valid_notiming_trg_in, + lvl1_invalid_trg_in => lvl1_invalid_trg_in, + lvl1_trg_type_in => lvl1_trg_type_in, + lvl1_trg_number_in => lvl1_trg_number_in, + lvl1_trg_code_in => lvl1_trg_code_in, + lvl1_trg_information_in => lvl1_trg_information_in, + lvl1_int_trg_number_in => lvl1_int_trg_number_in, + fee_trg_release_out => fee_trg_release_out, + fee_trg_statusbits_out => fee_trg_statusbits_out, + fee_data_out => fee_data_out, + fee_data_write_out => fee_data_write_out, + fee_data_finished_out => fee_data_finished_out, + fee_data_almost_full_in => fee_data_almost_full_in, + slv_addr_in => slv_addr_in, + slv_data_in => slv_data_in, + slv_data_out => slv_data_out, + slv_read_enable_in => slv_read_enable_in, + slv_write_enable_in => slv_write_enable_in, + slv_ack_out => slv_ack_out, + slv_no_more_data_out => slv_no_more_data_out, + slv_unknown_addr_out => slv_unknown_addr_out, + data_wr_enable => data_wr_enable, + data_in => data_in); + + clk_gen : process is + begin -- process clk_gen + clk <= '1'; + wait for clk_period/2; + clk <= '0'; + wait for clk_period/2; + end process clk_gen; + + stimulus : process is + begin -- process stimulus + -- test of trigger bypass + wait for 100 ns; + lvl1_valid_timing_trg_in <= '1'; + wait for 2*clk_period; + lvl1_valid_timing_trg_in <= '0'; + -- deactivate trigger bypass and simulate no timing triggers + wait for 100 ns; + slv_write_enable_in <= '1'; + slv_addr_in <= x"0127"; + slv_data_in <= (others => '0'); + wait for clk_period; + slv_write_enable_in <= '0'; + slv_addr_in <= (others => '0'); + -- status trigger + lvl1_valid_notiming_trg_in <= '1'; + lvl1_trg_data_valid_in <= '1'; + lvl1_trg_type_in <= x"e"; + wait for 10*clk_period; + lvl1_valid_notiming_trg_in <= '0'; + lvl1_trg_data_valid_in <= '0'; + lvl1_trg_type_in <= (others => '0'); + wait for 100 ns; + -- configure the readout controller + slv_write_enable_in <= '1'; + slv_addr_in <= x"0100"; + slv_data_in <= x"00000001"; + wait for clk_period; + slv_write_enable_in <= '1'; + slv_addr_in <= x"0102"; + slv_data_in <= x"0000000a"; + wait for clk_period; + slv_write_enable_in <= '1'; + slv_addr_in <= x"0103"; + slv_data_in <= x"caadcaad"; + wait for clk_period; + slv_write_enable_in <= '1'; + slv_addr_in <= x"0105"; + slv_data_in <= x"0000000f"; + wait for clk_period; + slv_write_enable_in <= '0'; + -- fill some data into the fifos + for i in 0 to 10 loop + data_wr_enable <= (others => '1'); + for J in 0 to 3 loop + data_in((J + 1)*32 - 1 downto J*32) <= x"CA" & std_logic_vector(to_unsigned(J, 8)) & std_logic_vector(to_unsigned(i, 16)); + end loop; -- J + wait for clk_period; + end loop; -- i + -- physics trigger + lvl1_valid_notiming_trg_in <= '1'; + lvl1_trg_data_valid_in <= '1'; + lvl1_trg_type_in <= x"1"; + wait for 40*clk_period; + lvl1_valid_notiming_trg_in <= '0'; + lvl1_trg_data_valid_in <= '0'; + lvl1_trg_type_in <= (others => '0'); + + wait; + end process stimulus; + +end architecture sim;