paicore_behavioral/router/fifo.vhdl
2025-07-15 14:37:28 -05:00

70 lines
No EOL
2.6 KiB
VHDL
Executable file

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--------------------------------------------------------
entity fifo is
generic (
WIDTH : positive := 32;
DEPTH : positive := 8;
F_PTR_SIZE : positive := 4
);
port(
arstN, clk, wr_req, rd_req : in std_logic;
full, empty : out std_logic;
data_in : in std_logic_vector(WIDTH-1 downto 0);
data_out : out std_logic_vector(WIDTH-1 downto 0)
);
end fifo;
--------------------------------------------------------
architecture impl of fifo is
constant one : unsigned(DEPTH-1 downto 0) := to_unsigned(1, DEPTH);
type T_FIFO is array (0 to DEPTH-1) of std_logic_vector(WIDTH-1 downto 0);
signal wr_ptr, rd_ptr : unsigned(F_PTR_SIZE-1 downto 0);
signal wr_ptr_nxt, rd_ptr_nxt : unsigned(F_PTR_SIZE-1 downto 0);
signal data_out_nxt : std_logic_vector(WIDTH-1 downto 0);
signal s_full, s_empty : std_logic;
signal s_full_nxt, s_empty_nxt : std_logic;
signal fifo, fifo_nxt : T_FIFO;
signal fifo_sel : std_logic_vector(DEPTH-1 downto 0);
begin
update_registers: process(arstN, clk)
begin
if arstN = '0' then
wr_ptr <= (others => '0');
rd_ptr <= (others => '0');
fifo <= (others => (others => '0'));
data_out <= (others => '0');
elsif clk'event and clk='1' then
fifo <= fifo_nxt;
wr_ptr <= wr_ptr_nxt;
rd_ptr <= rd_ptr_nxt;
data_out <= data_out_nxt;
s_full <= s_full_nxt;
s_empty <= s_empty_nxt;
end if;
end process;
g_write_mux: for i in 0 to DEPTH-1 generate
fifo_nxt(i) <= data_in when fifo_sel(i) = '1' else fifo(i);
end generate;
fifo_sel <= std_logic_vector(shift_left(one, to_integer(wr_ptr(F_PTR_SIZE-2 downto 0))))
when wr_req = '1' and s_full = '0' else (others => '0');
data_out_nxt <= fifo(to_integer(rd_ptr(F_PTR_SIZE-2 downto 0)));
s_full_nxt <= '1' when
rd_ptr_nxt(F_PTR_SIZE-2 downto 0) = wr_ptr_nxt(F_PTR_SIZE-2 downto 0) and
rd_ptr_nxt(F_PTR_SIZE-1) /= wr_ptr_nxt(F_PTR_SIZE-1) else '0';
s_empty_nxt <= '1' when rd_ptr_nxt = wr_ptr_nxt else '0';
rd_ptr_nxt <= rd_ptr + 1 when rd_req = '1' and s_empty = '0' else rd_ptr;
wr_ptr_nxt <= wr_ptr + 1 when wr_req = '1' and s_full = '0' else wr_ptr;
full <= s_full;
empty <= s_empty;
end impl;