Line 39... |
Line 39... |
library neorv32;
|
library neorv32;
|
use neorv32.neorv32_package.all;
|
use neorv32.neorv32_package.all;
|
|
|
entity neorv32_fifo is
|
entity neorv32_fifo is
|
generic (
|
generic (
|
FIFO_DEPTH : natural := 4; -- number of fifo entries; has to be a power of two; min 1
|
FIFO_DEPTH : natural; -- number of fifo entries; has to be a power of two; min 1
|
FIFO_WIDTH : natural := 32; -- size of data elements in fifo
|
FIFO_WIDTH : natural; -- size of data elements in fifo
|
FIFO_RSYNC : boolean := false; -- false = async read; true = sync read
|
FIFO_RSYNC : boolean; -- false = async read; true = sync read
|
FIFO_SAFE : boolean := false -- true = allow read/write only if data available
|
FIFO_SAFE : boolean -- true = allow read/write only if entry available
|
);
|
);
|
port (
|
port (
|
-- control --
|
-- control --
|
clk_i : in std_ulogic; -- clock, rising edge
|
clk_i : in std_ulogic; -- clock, rising edge
|
rstn_i : in std_ulogic; -- async reset, low-active
|
rstn_i : in std_ulogic; -- async reset, low-active
|
clear_i : in std_ulogic; -- sync reset, high-active
|
clear_i : in std_ulogic; -- sync reset, high-active
|
|
level_o : out std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- fill level
|
-- write port --
|
-- write port --
|
wdata_i : in std_ulogic_vector(FIFO_WIDTH-1 downto 0); -- write data
|
wdata_i : in std_ulogic_vector(FIFO_WIDTH-1 downto 0); -- write data
|
we_i : in std_ulogic; -- write enable
|
we_i : in std_ulogic; -- write enable
|
free_o : out std_ulogic; -- at least one entry is free when set
|
free_o : out std_ulogic; -- at least one entry is free when set
|
-- read port --
|
-- read port --
|
Line 69... |
Line 70... |
type fifo_t is record
|
type fifo_t is record
|
we : std_ulogic; -- write enable
|
we : std_ulogic; -- write enable
|
re : std_ulogic; -- read enable
|
re : std_ulogic; -- read enable
|
w_pnt : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- write pointer
|
w_pnt : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- write pointer
|
r_pnt : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- read pointer
|
r_pnt : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- read pointer
|
|
level : std_ulogic_vector(index_size_f(FIFO_DEPTH) downto 0); -- fill count
|
data : fifo_data_t; -- fifo memory
|
data : fifo_data_t; -- fifo memory
|
|
datas : std_ulogic_vector(FIFO_WIDTH-1 downto 0);
|
match : std_ulogic;
|
match : std_ulogic;
|
empty : std_ulogic;
|
empty : std_ulogic;
|
full : std_ulogic;
|
full : std_ulogic;
|
free : std_ulogic;
|
free : std_ulogic;
|
avail : std_ulogic;
|
avail : std_ulogic;
|
Line 116... |
Line 119... |
end if;
|
end if;
|
end if;
|
end if;
|
end process fifo_control;
|
end process fifo_control;
|
|
|
-- status --
|
-- status --
|
fifo.match <= '1' when (fifo.r_pnt(fifo.r_pnt'left-1 downto 0) = fifo.w_pnt(fifo.w_pnt'left-1 downto 0)) else '0';
|
fifo.match <= '1' when (fifo.r_pnt(fifo.r_pnt'left-1 downto 0) = fifo.w_pnt(fifo.w_pnt'left-1 downto 0)) or (FIFO_DEPTH = 1) else '0';
|
fifo.full <= '1' when (fifo.r_pnt(fifo.r_pnt'left) /= fifo.w_pnt(fifo.w_pnt'left)) and (fifo.match = '1') else '0';
|
fifo.full <= '1' when (fifo.r_pnt(fifo.r_pnt'left) /= fifo.w_pnt(fifo.w_pnt'left)) and (fifo.match = '1') else '0';
|
fifo.empty <= '1' when (fifo.r_pnt(fifo.r_pnt'left) = fifo.w_pnt(fifo.w_pnt'left)) and (fifo.match = '1') else '0';
|
fifo.empty <= '1' when (fifo.r_pnt(fifo.r_pnt'left) = fifo.w_pnt(fifo.w_pnt'left)) and (fifo.match = '1') else '0';
|
fifo.free <= not fifo.full;
|
fifo.free <= not fifo.full;
|
fifo.avail <= not fifo.empty;
|
fifo.avail <= not fifo.empty;
|
|
fifo.level <= std_ulogic_vector(to_unsigned(FIFO_DEPTH, fifo.level'length)) when (fifo.full = '1') else std_ulogic_vector(unsigned(fifo.w_pnt) - unsigned(fifo.r_pnt));
|
|
|
-- status output --
|
-- status output --
|
|
level_o <= fifo.level;
|
free_o <= fifo.free;
|
free_o <= fifo.free;
|
avail_o <= fifo.avail;
|
avail_o <= fifo.avail;
|
|
|
|
|
-- FIFO Memory ----------------------------------------------------------------------------
|
-- FIFO Memory ----------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
fifo_memory_write: process(clk_i)
|
fifo_memory_write: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if (fifo.we = '1') then
|
if (fifo.we = '1') then
|
|
if (FIFO_DEPTH = 1) then
|
|
fifo.datas <= wdata_i;
|
|
else
|
fifo.data(to_integer(unsigned(fifo.w_pnt(fifo.w_pnt'left-1 downto 0)))) <= wdata_i;
|
fifo.data(to_integer(unsigned(fifo.w_pnt(fifo.w_pnt'left-1 downto 0)))) <= wdata_i;
|
end if;
|
end if;
|
end if;
|
end if;
|
|
end if;
|
end process fifo_memory_write;
|
end process fifo_memory_write;
|
|
|
-- asynchronous read --
|
-- asynchronous read --
|
fifo_read_async:
|
fifo_read_async:
|
if (FIFO_RSYNC = false) generate
|
if (FIFO_RSYNC = false) generate
|
rdata_o <= fifo.data(to_integer(unsigned(fifo.r_pnt(fifo.r_pnt'left-1 downto 0))));
|
rdata_o <= fifo.datas when (FIFO_DEPTH = 1) else fifo.data(to_integer(unsigned(fifo.r_pnt(fifo.r_pnt'left-1 downto 0))));
|
end generate;
|
end generate;
|
|
|
-- synchronous read --
|
-- synchronous read --
|
fifo_read_sync:
|
fifo_read_sync:
|
if (FIFO_RSYNC = true) generate
|
if (FIFO_RSYNC = true) generate
|
fifo_memory_read: process(clk_i)
|
fifo_memory_read: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if (fifo.re = '1') then
|
if (fifo.re = '1') then
|
|
if (FIFO_DEPTH = 1) then
|
|
rdata_o <= fifo.datas;
|
|
else
|
rdata_o <= fifo.data(to_integer(unsigned(fifo.r_pnt(fifo.r_pnt'left-1 downto 0))));
|
rdata_o <= fifo.data(to_integer(unsigned(fifo.r_pnt(fifo.r_pnt'left-1 downto 0))));
|
end if;
|
end if;
|
end if;
|
end if;
|
|
end if;
|
end process fifo_memory_read;
|
end process fifo_memory_read;
|
end generate;
|
end generate;
|
|
|
|
|
end neorv32_fifo_rtl;
|
end neorv32_fifo_rtl;
|