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;
-----------------------------------------------------------------------------
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;
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;
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
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";
ignore,
wait_trigger_data_valid_a,
wait_trigger_data_valid_b);
-
+
type trigger_type_type is (t_timing,
t_physics,
t_status,
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
------------------------------------------------------------
--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;
--- /dev/null
+--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;