119 lines
3.2 KiB
VHDL
119 lines
3.2 KiB
VHDL
library ieee;
|
|
use ieee.std_logic_1164.all;
|
|
use ieee.numeric_std.all;
|
|
|
|
entity fifo is
|
|
generic (
|
|
DEPTH : positive := 1024
|
|
);
|
|
port
|
|
(
|
|
aclr : in std_logic;
|
|
clock : in std_logic;
|
|
sclr : in std_logic;
|
|
data : in std_logic_vector( 31 downto 0 );
|
|
rdreq : in std_logic;
|
|
wrreq : in std_logic;
|
|
empty : out std_logic;
|
|
full : out std_logic;
|
|
q : out std_logic_vector( 31 downto 0 );
|
|
usedw : out std_logic_vector( 9 downto 0 )
|
|
);
|
|
end entity fifo;
|
|
|
|
architecture rtl of fifo is
|
|
|
|
type Operation is (
|
|
OPERATION_IDLE,
|
|
OPERATION_CLEAR,
|
|
OPERATION_READ,
|
|
OPERATION_WRITE,
|
|
OPERATION_READ_WRITE
|
|
);
|
|
|
|
signal is_empty : boolean;
|
|
signal is_full : boolean;
|
|
|
|
signal is_read : boolean;
|
|
signal is_write : boolean;
|
|
signal is_read_write : boolean;
|
|
|
|
signal next_operation : Operation;
|
|
|
|
signal fifo_data : work.reg32.RegArray( 0 to DEPTH - 1 );
|
|
|
|
signal write_index : integer range 0 to DEPTH - 1;
|
|
signal read_index : integer range 0 to DEPTH - 1;
|
|
signal item_count : integer range 0 to DEPTH;
|
|
|
|
function increment_with_overflow( value : integer; max : integer ) return integer
|
|
is
|
|
begin
|
|
if ( value < max - 1 ) then
|
|
return value + 1;
|
|
end if;
|
|
return 0;
|
|
end function increment_with_overflow;
|
|
|
|
begin
|
|
|
|
c_is_empty: is_empty <= item_count = 0;
|
|
c_is_full: is_full <= item_count = DEPTH;
|
|
|
|
c_is_read: is_read <= rdreq = '1' and not is_empty;
|
|
c_is_write: is_write <= wrreq = '1' and not is_full;
|
|
c_is_read_write: is_read_write <= is_read and is_write;
|
|
|
|
c_next_operation: next_operation <= OPERATION_CLEAR when sclr
|
|
else OPERATION_READ_WRITE when is_read_write
|
|
else OPERATION_READ when is_read
|
|
else OPERATION_WRITE when is_write
|
|
else OPERATION_IDLE;
|
|
|
|
sync: process( clock, aclr ) is
|
|
begin
|
|
if ( aclr = '1' ) then
|
|
write_index <= 0;
|
|
read_index <= 0;
|
|
item_count <= 0;
|
|
elsif ( rising_edge( clock ) ) then
|
|
|
|
case next_operation is
|
|
when OPERATION_IDLE =>
|
|
null;
|
|
|
|
when OPERATION_CLEAR =>
|
|
write_index <= 0;
|
|
read_index <= 0;
|
|
item_count <= 0;
|
|
|
|
when OPERATION_READ =>
|
|
item_count <= item_count - 1;
|
|
read_index <= increment_with_overflow( read_index, DEPTH );
|
|
|
|
when OPERATION_WRITE =>
|
|
fifo_data( write_index ) <= data;
|
|
item_count <= item_count + 1;
|
|
write_index <= increment_with_overflow( write_index, DEPTH );
|
|
|
|
when OPERATION_READ_WRITE =>
|
|
read_index <= increment_with_overflow( read_index, DEPTH );
|
|
|
|
fifo_data( write_index ) <= data;
|
|
write_index <= increment_with_overflow( write_index, DEPTH );
|
|
end case;
|
|
|
|
end if;
|
|
end process;
|
|
|
|
c_assign_q: q <= data when ( is_empty and is_write ) else
|
|
fifo_data( read_index );
|
|
|
|
c_assign_usedw:
|
|
usedw <= std_logic_vector( to_unsigned( item_count, usedw'length ) );
|
|
|
|
full <= '1' when is_full else '0';
|
|
empty <= '1' when is_empty else '0';
|
|
end architecture rtl;
|
|
|