In FPGA design, a FIFO (First-In, First-Out buffer) is typically implemented using dedicated FPGA resources like Block RAM (BRAM) and logic for control. You can either build your own FIFO manually in HDL (Verilog/VHDL) or generate one automatically using vendor-provided IP cores/tools.
How an FPGA Generates a FIFO
There are two main ways:
1. Using FIFO IP Generator (Recommended for most users)
FPGA vendors provide FIFO Generator IPs that are highly optimized, configurable, and easy to use.
Tools:
- Xilinx: FIFO Generator IP
- Intel (Altera): [FIFO IP in Platform Designer or IP Catalog]
- Lattice: IPexpress or Lattice Propel
Configuration Options:
- FIFO type: synchronous or asynchronous
- Data width and depth
- Read/write clock domains
- Almost full/empty flags
- First-word fall-through (FWFT)
- Output registers and latency options
How It Works:
Use the IP wizard to configure the FIFO's parameters.
The tool generates:
- HDL wrapper files
- Synthesizable RTL
- Simulation models
- Block RAM/logic mapping
- Instantiate the FIFO in your design and connect write/read logic.
Advantage: Fast, safe, optimized, easy to integrate.
2. Custom HDL-Based FIFO (Manual Approach)
If you want full control or need a lightweight FIFO for small use cases, you can implement it in Verilog or VHDL.
Key Components:
- Memory array (implemented using registers or inferred as Block RAM)
- Write pointer and read pointer
- Full and empty status flags
- Optional: Gray-coded pointers for async FIFOs
Example (Simple Synchronous FIFO Logic):
verilog
module fifo #(parameter DEPTH = 16, WIDTH = 8) (
input clk,
input rst,
input wr_en,
input rd_en,
input [WIDTH-1:0] din,
output [WIDTH-1:0] dout,
output full,
output empty
);
reg [WIDTH-1:0] mem [0:DEPTH-1];
reg [$clog2(DEPTH):0] wr_ptr = 0;
reg [$clog2(DEPTH):0] rd_ptr = 0;
reg [$clog2(DEPTH+1):0] count = 0;
assign full = (count == DEPTH);
assign empty = (count == 0);
assign dout = mem[rd_ptr];
always @(posedge clk) begin
if (rst) begin
wr_ptr <= 0;
rd_ptr <= 0;
count <= 0;
end else begin
if (wr_en && !full) begin
mem[wr_ptr] <= din;
wr_ptr <= wr_ptr + 1;
count <= count + 1;
end
if (rd_en && !empty) begin
rd_ptr <= rd_ptr + 1;
count <= count - 1;
end
end
end
endmodule
Advantage: Fully customizable
Disadvantage: More prone to bugs and timing issues, especially for async FIFOs
How the FPGA Implements the FIFO Internally
When synthesized:
- The memory array is mapped to Block RAM or Distributed RAM.
- The pointers and control logic are mapped to flip-flops and LUTs.
- Timing constraints ensure reliable operation, especially for async designs.
Summary Table