137 lines
3.3 KiB
VHDL
137 lines
3.3 KiB
VHDL
|
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;
|