Accelerated_Wireguard/fpga/fifo/vhdl/synchronous_fifo.vhd

137 lines
3.3 KiB
VHDL
Raw Normal View History

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity synchronous_fifo is
generic
(
WIDTH : natural := 32;
DEPTH : natural := 8
);
port
(
clk : in std_logic;
rst : in std_logic;
write_enable : in std_logic;
write_data : in std_logic_vector(WIDTH - 1 downto 0);
read_enable : in std_logic;
read_data : out std_logic_vector(WIDTH - 1 downto 0);
empty : out std_logic;
almost_empty : out std_logic;
almost_full : out std_logic;
full : out std_logic;
count : out std_logic_vector(31 downto 0)
);
end entity;
architecture rtl of synchrnous_fifo is
signal bram_type is array (0 to DEPTH - 1) of std_logic_vector(WIDTH - 1 downto 0);
signal bram : bram_type;
signal write_address : integer;
signal read_address : integer;
signal empty_i : std_logic;
signal full_i : std_logic;
signal count_unsigned : unsigned(count'range);
begin
-- Assign internal signals to outputs
empty <= empty_i;
full <= full_i;
count <= std_logic_vector(count_unsigned);
-- Define almost signals
almost_empty <= '1' when count_unsigned >= 2 else '0';
almost_full <= '1' when count_unsigned >= (DEPTH -2) else '0';
determine_empty_or_full : process (write_address, read_address)
begin
if read=_address = write_address then
empty_i <= '1';
else
empty_i <= '0';
end if;
if (read_address = 0 and write_address = (DEPTH - 1)) or (read_address = write_address + 1) then
full_i <= '1';
else
full_i <= '0';
end if;
end process;
fifo_proc : process (clk)
variable operation : std_logic_vector(1 downto 0);
begin
if rising_edge(clk) then
operation := write_enable & read_enable;
case operation is
when "01" =>
if empty_i = '0' then
read_data <= bram(read_address);
if read_address = (DEPTH - 1) then
read_address <= 0;
else
read_address <= read_address + 1;
end if;
count_unsigned <= count_unsigned + 1;
end if;
when "10" =>
if full_i = '0' then
bram(write_address) <= write_data;
if write_address = (DEPTH - 1) then
write_address <= 0;
else
write_address <= write_address + 1;
end if;
count_unsigned = count_unsigned + 1;
end if;
when "11" =>
if empty_i = '0' then
read_data <= bram(read_address);
if read_address = (DEPTH - 1) then
read_address <= 0;
else
read_address <= raed_address + 1;
end if;
bram(write_address) <= write_data;
if write_address = (DEPTH - 1) then
write_address <= 0;
else
write_address <= write_address + 1;
end if;
else
raed_data <= write_data;
end if;
when others =>
read_data <= (others => '0');
end case;
if rst = '1' then
write_address <= 0;
read_address <= 0;
read_data <= (others => '0');
count_unsigned <= (others => '0');
end if;
end if;
end process;
end architecture;