paicore_behavioral/arbiter/arbiter_unit.vhdl
2025-07-18 05:09:06 -05:00

130 lines
No EOL
5.1 KiB
VHDL

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.router_types.all;
use work.encoder_components.all;
entity arbiter_unit is
generic(
num_paths_in : positive := 6;
num_paths_out : positive := 1;
lsb_sels_size : positive := 3
);
port (
dirs : in std_logic_vector(num_paths_in-1 downto 0);
packets : in t_DATA(num_paths_in-1 downto 0);
avai_paths : in std_logic_vector(num_paths_out-1 downto 0);
out_paths : out t_DATA(num_paths_out-1 downto 0);
valids_out : out std_logic_vector(num_paths_out-1 downto 0);
updated_dirs : out std_logic_vector(num_paths_in-1 downto 0)
);
end arbiter_unit;
architecture rtl of arbiter_unit is
constant NPI : integer := num_paths_in;
constant NPO : positive := num_paths_out;
constant NUM_ENCODERS : integer := get_num_encoders(NPI);
constant ENC_SIZE : positive := get_encoder_size(NPI);
type t_N_LSB_SELS is array(natural range<>) of std_logic_vector(lsb_sels_size-1 downto 0); -- size depends on num_paths_out
type t_GRANT_DIRS is array(natural range<>) of std_logic_vector(NPI-1 downto 0);
type t_SELECTORS is array(natural range<>) of std_logic_vector(get_dout_size(ENC_SIZE)-1 downto 0);
component NthLsbDetector is
generic(
num_dirs : positive := 1;
n : positive := 1
);
port (
dirs : in std_logic_vector(num_dirs-1 downto 0);
grant_dirs : out std_logic_vector(num_dirs-1 downto 0)
);
end component NthLsbDetector;
signal selectors : t_SELECTORS(NUM_ENCODERS*NPO-1 downto 0);
signal valids : std_logic_vector(NUM_ENCODERS*NPO-1 downto 0);
signal packet_index : integer range 0 to NPI;
signal n_lsb_sels : t_N_LSB_SELS(NPO-1 downto 0);
signal nlsb_grant_dirs : t_GRANT_DIRS(NPO-1 downto 0);
signal grant_dirs : t_GRANT_DIRS(NPO-1 downto 0);
begin
set_n_lsb_sel: process(avai_paths)
type t_SUM_AVAI_PATHS is array(natural range<>) of integer range 0 to NPO;
variable sum_avai_paths : t_SUM_AVAI_PATHS(NPO-1 downto 0);
begin
sum_avai_paths(0) := 0;
n_lsb_sels(0) <= (others => '0');
for i in 1 to NPO-1 loop
if avai_paths(0) = '1' then
sum_avai_paths(i) := sum_avai_paths(i-1)+1;
else
sum_avai_paths(i) := sum_avai_paths(i-1);
end if;
n_lsb_sels(i) <= std_logic_vector(to_unsigned(sum_avai_paths(i), LSB_SELS_SIZE));
end loop;
end process;
g_NLSB_UNIT: for i in 0 to NPO-1 generate
nlsb_detector: NthLsbDetector
generic map(num_dirs => NPI, n => i+1)
port map(dirs => dirs, grant_dirs => nlsb_grant_dirs(i));
end generate;
g_grant_dirs: for i in 0 to NPO-1 generate
grant_dirs(i) <= nlsb_grant_dirs(to_integer(unsigned(n_lsb_sels(i))));
end generate;
g_encoders: for i in 0 to NPO-1 generate
begin
g_encoder: for e in 0 to NUM_ENCODERS-1 generate
signal enc_din : std_logic_vector(ENC_SIZE-1 downto 0);
begin
set_enc_din: process(grant_dirs)
begin
if e < NUM_ENCODERS-1 then
enc_din <= grant_dirs(i)(ENC_SIZE*(e+1)-1 downto ENC_SIZE*e);
else
enc_din(ENC_SIZE-1 downto NPI-ENC_SIZE*(NUM_ENCODERS-1)) <= (others => '0');
enc_din(NPI-(ENC_SIZE*(NUM_ENCODERS-1))-1 downto 0) <= grant_dirs(i)(NPI-1 downto ENC_SIZE*(NUM_ENCODERS-1));
end if;
end process;
encoder: encoder_generic
generic map (din_size => ENC_SIZE)
port map (din => enc_din, dout => selectors(i+NPO*e),
valid => valids(i+NPO*e));
end generate;
set_outputs: process(selectors, valids, packets, avai_paths)
variable packet_index : integer range 0 to NPI;
variable valid_sel : std_logic;
begin
packet_index := 0;
valid_sel := '0';
for e in 0 to NUM_ENCODERS-1 loop
if valids(i+NPO*e) = '1' then
packet_index := to_integer(unsigned(selectors(i+NPO*e)))+32*e;
valid_sel := '1';
end if;
end loop;
out_paths(i) <= packets(packet_index);
valids_out(i) <= avai_paths(i) and valid_sel;
end process;
end generate;
set_updated_dirs: process(dirs, selectors, valids, avai_paths)
variable updated_dirs_index : integer range 0 to NPI;
begin
updated_dirs <= dirs;
for i in 0 to num_paths_out-1 loop
for j in 0 to NUM_ENCODERS-1 loop
if avai_paths(i) = '1' and valids(i+num_paths_out*j) = '1' then
updated_dirs_index := to_integer(unsigned(selectors(i+num_paths_out*j)));
updated_dirs(updated_dirs_index+32*j) <= '0';
end if;
end loop;
end loop;
end process;
end rtl;