-- This is a MUX for avalon_st_128 signals -- This allows us to combine multiple avalon_st_128 streams into a single stream library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library work; use work.avalon_st_pkg.all; entity avalon_st_128_mux is generic ( NUMBER_OF_INPUTS : natural := 2; FIFO_DEPTH : natural := 5; BACKPRESSURE_MARGIN : natural := 4 ); port ( clk : in std_logic; rst : in std_logic; mux_in : in AVALON_ST_128_ARRAY_TYPE(NUMBER_OF_INPUTS - 1 downto 0); mux_in_rdy : out std_logic_vector(NUMBER_OF_INPUTS - 1 downto 0); mux_out : out AVALON_ST_128; mux_out_rdy : in std_logic ); end entity; architecture rtl of avalon_st_128_mux is signal fifo_output : AVALON_ST_128_ARRAY_TYPE(NUMBER_OF_INPUTS - 1 downto 0); signal fifo_output_rdy : std_logic_vector(NUMBER_OF_INPUTS - 1 downto 0); signal internal_fifo_empty : std_logic_vector(NUMBER_OF_INPUTS - 1 downto 0); signal target_input_port : unsigned(log_ceil(NUMBER_OF_INPUTS) - 1 downto 0); signal mux_out_i : AVALON_ST_128; begin -- Generate a fifo per input input_fifo_gen : for i in 0 to (NUMBER_OF_INPUTS - 1) generate input_fifo : entity avalon_st_128_synchronous_fifo generic map ( LOG2_DEPTH => FIFO_DEPTH, BACKPRESSURE_MARGIN => BACKPRESSURE_MARGIN ) port map ( clk => clk, rst => rst, input => mux_in(i), input_rdy => mux_in_rdy(i), output => fifo_output(i), output_rdy => fifo_output_rdy(i), fill => open, full => open, empty => internal_fifo_empty(i) ); end generate; targetting_proc : process (clk) begin if rising_edge(clk) then if mux_out_rdy = '1' then if internal_fifo_empty(to_integer(target_input_port)) /= '0' then -- stay on port until the last cycle of data has egressed, then switch if mux_out_i.endofpacket = '1' and mux_out_i.valid = '1' then if to_integer(target_input_port) < NUMBER_OF_INPUTS - 1 then target_input_port <= target_input_port + 1; else target_input_port <= (others => '0'); end if; end if; else -- increment the target port if not at max port, else loop around to the lowest port if to_integer(target_input_port) < NUMBER_OF_INPUTS - 1 then target_input_port <= target_input_port + 1; else target_input_port <= (others => '0'); end if; end if; end if; if rst = '1' then target_input_port <= (others => '0'); end if; end if; end process; -- map the fifo outputs to the actual output(exploded view as the valid has some extra conditions) mux_out_i.data <= fifo_output(to_integer(target_input_port)).data when rst /= '1' else (others => '0'); mux_out_i.startofpacket <= fifo_output(to_integer(target_input_port)).startofpacket when rst /= '1' else '0'; mux_out_i.endofpacket <= fifo_output(to_integer(target_input_port)).endofpacket when rst /= '1' else '0'; mux_out_i.empty <= fifo_output(to_integer(target_input_port)).empty when rst /= '1' else (others => '0'); mux_out_i.error <= fifo_output(to_integer(target_input_port)).error when rst /= '1' else '0'; mux_out_i.valid <= fifo_output(to_integer(target_input_port)).valid and mux_out_rdy when rst /= '1' else '0'; mux_out <= mux_out_i; rdy_control_gen : for i in 0 to (NUMBER_OF_INPUTS - 1) generate fifo_output_rdy(i) <= mux_out_rdy when to_integer(target_input_port) = i and rst /= '1' else '0'; end generate; end architecture;