From: Tobias Weber Date: Fri, 22 Jun 2018 09:12:55 +0000 (+0200) Subject: data multiplexer with conversion from 40 to 32 bit X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=e8136b591b6499014ce5c6a8f7ee177a434ba98c;p=trb3.git data multiplexer with conversion from 40 to 32 bit --- diff --git a/mupix/Mupix8/sources/DataMuxWithConversion.vhd b/mupix/Mupix8/sources/DataMuxWithConversion.vhd new file mode 100644 index 0000000..93cfe04 --- /dev/null +++ b/mupix/Mupix8/sources/DataMuxWithConversion.vhd @@ -0,0 +1,221 @@ +-------------------------------------------------------------------------------- +-- 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;