--- /dev/null
+--------------------------------------------------------------------------------
+-- FIFO Data Multiplexer for n input channels to 1 output channels
+-- This module also converts the 40 bit input data of the mupix into
+-- 32 bit portions + padding of the last word for readout with the TRB
+-- TODO: after adding the hit time sorter the data width conversion should be moved there
+-- TODO: make width conversion more flexible
+-- T. Weber, Ruhr University Bochum
+-------------------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.StdTypes.all;
+use work.Constants.all;
+
+entity FiFoDataMux is
+ generic(
+ g_datawidthfifo : integer := 40; -- data width of input fifos
+ g_datawidthtrb : integer := 32; -- data width of trb data bus
+ g_inputs : integer := 4; -- number of inputs to multiplexer
+ g_clockspeed : integer := 1e8 -- fpga clock speed
+ );
+ port(
+ clk : in std_logic; -- clock input
+ rst : in std_logic; -- reset input
+ fifo_empty : in std_logic_vector(g_inputs - 1 downto 0); -- input FIFO empty flags
+ fifo_full : in std_logic_vector(g_inputs - 1 downto 0); -- input FIFO full flags
+ fifo_datain : in std_logic_vector(g_inputs*g_datawidthfifo - 1 downto 0); -- input data from FIFOs
+ fifo_mask : in std_logic_vector(g_inputs - 1 downto 0); -- enable mask for FIFO inputs
+ fifo_rden : out std_logic_vector(g_inputs - 1 downto 0); -- read enable to FIFOs
+ buff_wren : out std_logic; -- write enable to output buffer
+ dataout : out std_logic_vector(g_datawidthtrb - 1 downto 0); -- data output
+ wordin_freq : out std_logic_vector(32*g_inputs - 1 downto 0); -- number of input words from FIFOs
+ fifo_full_o : out std_logic -- or over input fifo full flags
+ );
+end entity FiFoDataMux;
+
+
+architecture RTL of FiFoDataMux is
+
+ signal ticks_counter : unsigned(f_log2(g_clockspeed) - 1 downto 0) := (others => '0');
+ signal inword_counter : t_counter_array(0 to g_inputs - 1) := (others => (others => '0'));
+ signal increase_counter : std_logic_vector(g_inputs - 1 downto 0) := (others => '0');
+
+ signal fifo_full_i : std_logic;
+
+ signal fifo_sel_i : integer range - 1 to g_inputs - 1 := -1;
+ signal fifo_sel_reg : integer range 0 to g_inputs - 1 := 0;
+
+ signal request_i : std_logic_vector(g_inputs - 1 downto 0);
+ signal grant_i : std_logic_vector(g_inputs - 1 downto 0);
+
+ type t_mux_state is (idle, wait_fifo, write);
+ signal mux_fsm : t_mux_state := idle;
+
+ component RoundRobinArbiter
+ generic(g_num_channels : integer := 4);
+ port(
+ clk : in std_logic;
+ requests : in std_logic_vector(g_num_channels - 1 downto 0);
+ grant : out std_logic_vector(g_num_channels - 1 downto 0)
+ );
+ end component RoundRobinArbiter;
+
+ --data width converter signals
+ constant padding_0 : std_logic_vector(23 downto 0) := (others => '0');
+ constant padding_1 : std_logic_vector(15 downto 0) := (others => '0');
+ constant padding_2 : std_logic_vector(7 downto 0) := (others => '0');
+ type convert_mem_type is array (0 to 1) of std_logic_vector(c_mupixhitsize - 1 downto 0);
+ signal data_shift : convert_mem_type := (others => (others => '0'));
+ signal conversioncounter : integer range 0 to 6 := 0;
+ signal empty_delay : std_logic_vector(1 downto 0) := (others => '0');
+
+begin
+
+ request_i <= not fifo_empty and fifo_mask;
+
+ arbiter_1 : component RoundRobinArbiter
+ generic map(
+ g_num_channels => g_inputs
+ )
+ port map(
+ clk => clk,
+ requests => request_i,
+ grant => grant_i);
+
+ fifo_select_proc : process(grant_i) is
+ variable sel : integer range -1 to g_inputs - 1;
+ begin
+ sel := -1;
+ for i in 0 to g_inputs - 1 loop
+ if grant_i(i) = '1' then
+ sel := i;
+ end if;
+ end loop;
+ fifo_sel_i <= sel;
+ end process fifo_select_proc;
+
+ full_flag_proc : process(fifo_full) is
+ variable full : std_logic := '0';
+ begin
+ full := '0';
+ for i in 0 to fifo_full'length - 1 loop
+ full := full or fifo_full(i);
+ end loop;
+ fifo_full_i <= full;
+ end process full_flag_proc;
+
+ input_freq : process (clk) is
+ begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ ticks_counter <= (others => '0');
+ inword_counter <= (others => (others => '0'));
+ else
+ if increase_counter(fifo_sel_reg) = '1' then
+ inword_counter(fifo_sel_reg) <= inword_counter(fifo_sel_reg) + 1;
+ else
+ inword_counter(fifo_sel_reg) <= inword_counter(fifo_sel_reg);
+ end if;
+ if ticks_counter = g_clockspeed - 1 then
+ inword_counter <= (others => (others => '0'));
+ ticks_counter <= (others => '0');
+ wordin_freq <= counter_array_to_stdvec(inword_counter);
+ else
+ ticks_counter <= ticks_counter + 1;
+ end if;
+ end if;
+ end if;
+ end process input_freq;
+
+
+ mux_proc : process(clk) is
+ begin
+ if rising_edge(clk) then
+ if rst = '1' then
+ fifo_sel_reg <= 0;
+ fifo_rden <= (others => '0');
+ dataout <= (others => '0');
+ buff_wren <= '0';
+ mux_fsm <= idle;
+ else
+ empty_delay <= empty_delay(0) & fifo_empty(fifo_sel_reg);
+ case mux_fsm is
+ when idle =>
+ fifo_rden <= (others => '0');
+ conversioncounter <= 0;
+ fifo_sel_reg <= 0;
+ mux_fsm <= idle;
+ dataout <= (others => '0');
+ buff_wren <= '0';
+ if fifo_sel_i /= -1 then
+ fifo_sel_reg <= fifo_sel_i;
+ mux_fsm <= wait_fifo;
+ fifo_rden(fifo_sel_i) <= '1';
+ end if;
+ when wait_fifo =>
+ fifo_rden(fifo_sel_reg) <= '1';
+ mux_fsm <= write;
+ when write =>
+ mux_fsm <= write;
+ fifo_rden(fifo_sel_reg) <= '1';
+ increase_counter(fifo_sel_reg) <= '1';
+ -- width conversion
+ conversioncounter <= conversioncounter + 1;
+ data_shift(1) <= data_shift(0);
+ data_shift(0) <= fifo_datain((fifo_sel_reg + 1)*g_datawidthfifo - 1 downto g_datawidthfifo*fifo_sel_reg);
+ if empty_delay = "11" then
+ mux_fsm <= idle;
+ end if;
+ case conversioncounter is -- also controls fifo readout
+ when 0 =>
+ buff_wren <= '0';
+ dataout <= (others => '0');
+ when 1 =>
+ buff_wren <= '1';
+ dataout <= data_shift(0)(c_mupixhitsize - 1 downto 8);
+ when 2 =>
+ buff_wren <= '1';
+ if empty_delay = "11" then
+ dataout <= data_shift(1)(7 downto 0) & padding_0;
+ else
+ dataout <= data_shift(1)(7 downto 0) & data_shift(0)(c_mupixhitsize - 1 downto 16);
+ end if;
+ fifo_rden(fifo_sel_reg) <= '0';
+ when 3 =>
+ buff_wren <= '1';
+ if empty_delay = "11" then
+ dataout <= data_shift(1)(15 downto 0) & padding_1;
+ else
+ dataout <= data_shift(1)(15 downto 0) & data_shift(0)(c_mupixhitsize - 1 downto 24);
+ end if;
+ fifo_rden(fifo_sel_reg) <= '0';
+ when 4 =>
+ buff_wren <= '1';
+ if empty_delay = "11" then
+ dataout <= data_shift(1)(23 downto 0) & padding_2;
+ else
+ dataout <= data_shift(1)(23 downto 0) & data_shift(0)(c_mupixhitsize - 1 downto 32);
+ end if;
+ fifo_rden(fifo_sel_reg) <= '0';
+ when 5 =>
+ buff_wren <= '1';
+ dataout <= data_shift(1)(31 downto 0);
+ fifo_rden(fifo_sel_reg) <= '0';
+ when 6 =>
+ fifo_rden(fifo_sel_reg) <= '1';
+ conversioncounter <= 0;
+ buff_wren <= '0';
+ dataout <= (others => '0');
+ mux_fsm <= wait_fifo;
+ end case;
+ end case;
+ end if;
+ end if;
+ end process mux_proc;
+
+
+ fifo_full_o <= fifo_full_i;
+
+end architecture RTL;