112 lines
3.7 KiB
VHDL
112 lines
3.7 KiB
VHDL
|
-- 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;
|