Block RAM, ROM, and FIFOs
FPGAs contain dedicated memory blocks. Use them. Building every memory from flip-flops or LUTs is wasteful and often slower.
Learning Objectives
You will learn to:
- distinguish distributed RAM, block RAM, ROM, and FIFOs;
- infer a small ROM or RAM in HDL;
- understand synchronous read behavior;
- choose FIFO structures for buffering and CDC.
Memory Types
| Type | Built from | Best for |
|---|---|---|
| Registers | flip-flops | tiny state, control flags |
| Distributed RAM | LUT fabric | small tables, shallow buffers |
| Block RAM | dedicated memory blocks | buffers, FIFOs, frame data, lookup tables |
| ROM | RAM initialized with fixed content | constants, fonts, sine tables |
| FIFO | RAM plus read/write pointers | streaming queues and rate matching |
Synchronous RAM Model
Many FPGA memories read synchronously: address is sampled on a clock edge and data appears after that edge.
module simple_ram #(
parameter AW = 8,
parameter DW = 8
) (
input wire clk,
input wire we,
input wire [AW-1:0] addr,
input wire [DW-1:0] din,
output reg [DW-1:0] dout
);
reg [DW-1:0] mem [0:(1<<AW)-1];
always @(posedge clk) begin
if (we)
mem[addr] <= din;
dout <= mem[addr];
end
endmodule
ROM Example
always @* begin
case (addr)
4'd0: data = 8'h3f;
4'd1: data = 8'h06;
4'd2: data = 8'h5b;
4'd3: data = 8'h4f;
default: data = 8'h00;
endcase
end
Small ROMs may map to LUTs. Larger ROMs are often initialized block RAM.
FIFO Concept
A FIFO stores data in order. Write pushes data in. Read pops data out. Full and empty flags protect against overflow and underflow.
Asynchronous FIFOs
When write and read sides use different clocks, the FIFO must handle CDC. A safe asynchronous FIFO typically uses:
- separate write and read pointers;
- gray-coded pointer synchronization;
- two-flop synchronizers for pointer crossing;
- full and empty calculations in the correct clock domains.
Do not invent an async FIFO casually. Use a proven design or vendor IP until you have studied the details.
Worked Example: UART Receive Buffer
A UART receiver may produce one byte at irregular intervals. Firmware or another FPGA block may read bytes later. A FIFO decouples those rates:
- UART side writes when a byte is valid.
- Consumer side reads when ready.
- Empty prevents reading invalid data.
- Full warns that the consumer is too slow.
Common Mistakes
- Expecting block RAM reads to be combinational.
- Forgetting one-cycle memory latency.
- Ignoring full/empty flags.
- Crossing FIFO status flags without CDC discipline.
- Using thousands of flip-flops for a buffer that should be BRAM.
Summary
FPGA memories are architectural resources. Use registers for tiny state, LUT RAM for small structures, block RAM for real buffers and tables, ROMs for fixed data, and FIFOs for ordered queues. Respect memory latency and CDC rules.
Next: Building Peripherals.
Further Reading
- Vendor block RAM user guides
- FIFO generator documentation from FPGA vendors
- Clifford Cummings: Simulation and Synthesis Techniques for Asynchronous FIFO Design