11.4.10.1 Register-Based FIFO
The following example show the behavioral model for an 8x8 FIFO. This code was designed to imitate the behavior of the Microchip DX family dual-port SRAM based FIFO and to be synthesizeable to a register-based FIFO. To modify the width or depth, simply modify the listed parameters in the code. However, the code does assume that you want to use posedge clk and negedge reset. Modify the always blocks if that is not the case.
VHDL
-- *************************************************
-- Behavioral description of dual-port FIFO with :
-- Active High write enable (WE)
-- Active High read enable (RE)
-- Active Low asynchronous clear (Aclr)
-- Rising clock edge (Clock)
-- Active High Full Flag
-- Active Low Empty Flag
-- *************************************************
library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity reg_fifo is
generic (width : integer:=8;
depth : integer:=8;
addr : integer:=3);
port (Data : in std_logic_vector (width-1 downto 0);
Q : out std_logic_vector (width-1 downto 0);
Aclr : in std_logic;
Clock : in std_logic;
WE : in std_logic;
RE : in std_logic;
FF : out std_logic;
EF : out std_logic);
end reg_fifo;
library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
architecture behavioral of reg_fifo is
type MEM is array(0 to depth-1) of std_logic_vector(width-1 downto 0);
signal ramTmp : MEM;
signal WAddress : std_logic_vector (addr-1 downto 0);
signal RAddress : std_logic_vector (addr-1 downto 0);
signal words : std_logic_vector (addr-1 downto 0);
begin
-- ########################################################
-- # Write Functional Section
-- ########################################################
WRITE_POINTER : process (Aclr, Clock)
begin
if (Aclr = '0') then
WAddress <= (others => '0');
elsif (Clock'event and Clock = '1') then
if (WE = '1') then
if (WAddress = words) then
WAddress <= (others => '0');
else
WAddress <= WAddress + '1';
end if;
end if;
end if;
end process;
WRITE_RAM : process (Clock)
begin
if (Clock'event and Clock = '1') then
if (WE = '1') then
ramTmp (conv_integer (WAddress)) <= Data;
end if;
end if;
end process;
-- ########################################################
-- # Read Functional Section
-- ########################################################
READ_POINTER : process (Aclr, Clock)
begin
if (Aclr = '0') then
RAddress <= (others => '0');
elsif (Clock'event and Clock = '1') then
if (RE = '1') then
if (RAddress = words) then
RAddress <= (others => '0');
else
RAddress <= RAddress + '1';
end if;
end if;
end if;
end process;
READ_RAM : process (Clock)
begin
if (Clock'event and Clock = '1') then
if (RE = '1') then
Q <= ramTmp(conv_integer(RAddress));
end if;
end if;
end process;
-- ########################################################
-- # Full Flag Functional Section : Active high
-- ########################################################
FFLAG : process (Aclr, Clock)
begin
if (Aclr = '0') then
FF <= '0';
elsif (Clock'event and Clock = '1') then
if (WE = '1' and RE = '0') then
if ((WAddress = RAddress-1) or
((WAddress = depth-1) and (RAddress = 0))) then
FF <= '1';
end if;
else
FF <= '0';
end if;
end if;
end process;
-- ########################################################
-- # Empty Flag Functional Section : Active low
-- ########################################################
EFLAG : process (Aclr, Clock)
begin
if (Aclr = '0') then
EF <= '0';
elsif (Clock'event and Clock = '1') then
if (RE = '1' and WE = '0') then
if ((WAddress = RAddress+1) or
((RAddress = depth-1) and (WAddress = 0))) then
EF <= '0';
end if;
else
EF <= '1';
end if;
end if;
end process;
end behavioral;Verilog
`timescale 1 ns/100 ps
//########################################################
//# Behavioral description of FIFO with :
//# Active High write enable (WE)
//# Active High read enable (RE)
//# Active Low asynchronous clear (Aclr)
//# Rising clock edge (Clock)
//# Active High Full Flag
//# Active Low Empty Flag
//#######################################################
module reg_fifo (Data, Q, Aclr, Clock, WE, RE, FF, EF);
parameter width = 8;
parameter depth = 8;
parameter addr = 3;
input Clock, WE, RE, Aclr;
input [width-1:0] Data;
output FF, EF;//Full & Empty Flags
output [width-1:0] Q;
reg [width-1:0] Q;
reg [width-1:0] mem_data [depth-1:0];
reg [addr-1:0] WAddress, RAddress;
reg FF, EF;
// #########################################################
// # Write Functional Section
// #########################################################
// WRITE_ADDR_POINTER
always @ (posedge Clock or negedge Aclr)
begin
if(!Aclr)
WAddress = #2 0;
else if (WE)
WAddress = #2 WAddress + 1;
end
// WRITE_REG
always @ (posedge Clock)
begin
if(WE)
mem_data[WAddress] = Data;
end
//#########################################################
//# Read Functional Section
//#########################################################
// READ_ADDR_POINTER
always @ (posedge Clock or negedge Aclr)
begin
if(!Aclr)
RAddress = #1 0;
else if (RE)
RAddress = #1 RAddress + 1;
end
// READ_REG
always @ (posedge Clock)
begin
if (RE)
Q = mem_data[RAddress];
end
//#########################################################
//# Full Flag Functional Section : Active high
//#########################################################
always @ (posedge Clock or negedge Aclr)
begin
if(!Aclr)
FF = #1 1'b0;
else if ((WE & !RE) && ((WAddress == RAddress-1) ||
((WAddress == depth-1) && (RAddress == 1'b0))))
FF = #1 1'b1;
else
FF = #1 1'b0;
end
//#########################################################
//# Empty Flag Functional Section : Active low
//#########################################################
always @ (posedge Clock or negedge Aclr)
begin
if(!Aclr)
EF = #1 1'b0;
else if ((!WE & RE) && ((WAddress == RAddress+1) ||
((RAddress == depth-1) && (WAddress == 1'b0))))
EF = #1 1'b0;
else
EF = #1 1'b1;
end
endmodule