Accelerated_Wireguard/fpga/avalon_st/vhdl/avalon_st_128_mux.vhd

112 lines
3.7 KiB
VHDL
Raw Normal View History

-- 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;