--- /dev/null
+------------------------------------------------------------------
+--FIFO Data Multiplexer for n input channels to 1 output channels
+--T. Weber, Ruhr Universität Bochum
+------------------------------------------------------------------
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.StdTypes.all;
+
+entity FiFoDataMux is
+ generic(
+ g_datawidth : integer := 32; -- data width
+ 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_datawidth - 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_datawidth - 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;
+
+ type t_mux_state is (idle, wait_fifo, write);
+ signal mux_fsm : t_mux_state := idle;
+
+begin
+
+ fifo_select_proc : process(fifo_empty, fifo_mask) is
+ variable sel : integer range -1 to g_inputs - 1;
+ begin
+ sel := -1;
+ for i in 0 to g_inputs - 1 loop
+ if fifo_empty(i) = '0' and fifo_mask(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;
+ buff_wren <= '0';
+ dataout <= (others => '0');
+ fifo_rden <= (others => '0');
+ else
+ case mux_fsm is
+ when idle =>
+ fifo_rden <= (others => '0');
+ buff_wren <= '0';
+ dataout <= (others => '0');
+ if fifo_sel_i /= -1 then
+ fifo_sel_reg <= fifo_sel_i;
+ fifo_rden(fifo_sel_i) <= '1';
+ mux_fsm <= wait_fifo;
+ else
+ fifo_sel_reg <= 0;
+ mux_fsm <= idle;
+ end if;
+ when wait_fifo =>
+ fifo_rden(fifo_sel_i) <= '1';
+ mux_fsm <= write;
+ when write =>
+ dataout <= fifo_datain((fifo_sel_reg + 1)*g_datawidth - 1 downto g_datawidth*fifo_sel_reg);
+ if fifo_empty(fifo_sel_reg) = '0' then
+ mux_fsm <= write;
+ fifo_rden(fifo_sel_reg) <= '1';
+ buff_wren <= '1';
+ increase_counter(fifo_sel_reg) <= '1';
+ else
+ mux_fsm <= idle;
+ fifo_rden(fifo_sel_reg) <= '0';
+ buff_wren <= '1';
+ increase_counter <= (others => '0');
+ end if;
+ end case;
+ end if;
+ end if;
+ end process mux_proc;
+
+
+ fifo_full_o <= fifo_full_i;
+
+end architecture RTL;
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.StdTypes.all;
+
+entity DataMuxTest is
+end entity DataMuxTest;
+
+architecture sim of DataMuxTest is
+
+ 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 STD_FIFO
+ generic(
+ DATA_WIDTH : positive := 8;
+ FIFO_DEPTH : positive := 256
+ );
+ 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_datawidth : integer := 8;
+ constant c_inputs : integer := 2;
+ constant c_clockspeed : integer := 1e3;
+ constant c_fifo_depth : integer := 16;
+
+ constant c_clk_period : time := 10 ns;
+
+ signal clk : std_logic;
+ signal rst : std_logic := '0';
+ signal WriteEn : std_logic_vector(c_inputs - 1 downto 0) := (others => '0');
+ signal DataIn : std_logic_vector(c_inputs*c_datawidth - 1 downto 0) := (others => '0');
+ signal ReadEn : std_logic_vector(c_inputs - 1 downto 0);
+ signal DataOut : std_logic_vector(c_inputs*c_datawidth - 1 downto 0);
+ signal Empty : std_logic_vector(c_inputs - 1 downto 0);
+ signal Full : std_logic_vector(c_inputs - 1 downto 0);
+ signal fifo_mask : std_logic_vector(c_inputs - 1 downto 0) := (others => '0');
+ signal buff_wren : std_logic;
+ signal wordin_freq : std_logic_vector(32*c_inputs - 1 downto 0);
+ signal fifo_full_o : std_logic;
+ signal dataout_buf : std_logic_vector(c_datawidth - 1 downto 0);
+
+begin
+
+ generate_fifo : for i in 0 to c_inputs - 1 generate
+ fifo :component STD_FIFO
+ generic map(
+ DATA_WIDTH => c_datawidth,
+ FIFO_DEPTH => c_fifo_depth
+ )
+ port map(
+ CLK => clk,
+ RST => rst,
+ WriteEn => WriteEn(i),
+ DataIn => DataIn((i + 1)*c_datawidth - 1 downto i*c_datawidth),
+ ReadEn => ReadEn(i),
+ DataOut => DataOut((i + 1)*c_datawidth - 1 downto i*c_datawidth),
+ Empty => Empty(i),
+ Full => Full(i)
+ );
+ end generate generate_fifo;
+
+ dut : component FiFoDataMux
+ generic map(
+ g_datawidth => c_datawidth,
+ g_inputs => c_inputs,
+ g_clockspeed => c_clockspeed
+ )
+ port map(
+ clk => clk,
+ rst => rst,
+ fifo_empty => Empty,
+ fifo_full => Full,
+ fifo_datain => dataout,
+ fifo_mask => fifo_mask,
+ fifo_rden => ReadEn,
+ buff_wren => buff_wren,
+ dataout => dataout_buf,
+ wordin_freq => wordin_freq,
+ fifo_full_o => fifo_full_o
+ );
+
+ clk_gen : process is
+ begin
+ clk <= '0';
+ wait for c_clk_period/2;
+ clk <= '1';
+ wait for c_clk_period/2;
+ end process clk_gen;
+
+ stimulus : process is
+ begin
+ wait for 100 ns;
+ fifo_mask <= "11";
+ --write to single fifo
+ for i in 0 to 10 loop
+ WriteEn(1) <= '1';
+ DataIn(2*c_datawidth - 1 downto c_datawidth) <= x"A" & std_logic_vector(to_unsigned(i, 4));
+ wait for c_clk_period;
+ end loop;
+ WriteEn(1) <= '0';
+ DataIn(2*c_datawidth - 1 downto c_datawidth) <= (others => '0');
+ wait for 100 ns;
+ --write to both fifos at same time, reading should start at last fifo
+ for i in 0 to 10 loop
+ WriteEn <= "11";
+ DataIn <= x"A" & std_logic_vector(to_unsigned(i, 4)) & x"B" & std_logic_vector(to_unsigned(i, 4));
+ wait for c_clk_period;
+ end loop;
+ WriteEn <= (others => '0');
+ DataIn <= (others => '0');
+ wait for 200 ns;
+ --start writing into first fifo then in second fifo, state machine should finish reading fifo 1 and then start reading other fifo
+ for i in 0 to 10 loop
+ if i < 5 then
+ WriteEn(0) <= '1';
+ DataIn(c_datawidth - 1 downto 0) <= x"B" & std_logic_vector(to_unsigned(i, 4));
+ else
+ WriteEn <= "11";
+ DataIn <= x"A" & std_logic_vector(to_unsigned(i, 4)) & x"B" & std_logic_vector(to_unsigned(i, 4));
+ end if;
+ wait for c_clk_period;
+ end loop;
+ WriteEn <= (others => '0');
+ DataIn <= (others => '0');
+ wait;
+ end process stimulus;
+
+
+end architecture sim;