Block RAM (BRAM)
Master the RAMB36E1 primitive — dual-port modes, width configurations, ECC error correction, FIFO mode, and cascade techniques for on-chip memory in Xilinx 7-series FPGAs.
What is Block RAM?
Block RAM (BRAM) is a dedicated on-chip SRAM resource embedded in the FPGA fabric. Unlike LUT-based memory, BRAM is a fixed silicon block optimized purely for data storage. In 7-series Xilinx devices, the core primitive is RAMB36E1 — a 36 Kb dual-port synchronous SRAM that can also be split into two independent 18 Kb blocks (RAMB18E1).
BRAMs are arranged in columns throughout the FPGA fabric, interleaved between CLB columns. They are the go-to solution for FIFOs, packet buffers, coefficient tables, and frame memories — anything that needs dense, fast on-chip storage.
RAMB36E1 — Block Diagram
Width Configurations
Each RAMB36E1 port can be independently configured for different aspect ratios. The total bit capacity stays constant at 36Kb (plus 4Kb parity):
| Width Mode | Depth | Data Bits | Address Bits | Parity Bits | Notes |
|---|---|---|---|---|---|
| ×1 | 32K | 1 | 15 | 0 | Deepest configuration |
| ×2 | 16K | 2 | 14 | 0 | |
| ×4 | 8K | 4 | 13 | 0 | |
| ×9 | 4K | 8 | 12 | 1 | Parity bit for ECC |
| ×18 | 2K | 16 | 11 | 2 | Common FIFO width |
| ×36 | 1K | 32 | 10 | 4 | Widest per-port config |
| ×72 (SDP) | 512 | 64 | 9 | 8 | SDP mode only — 72-bit ECC |
Dual-Port Modes
| Mode | Port A | Port B | Max Width | Best Use Case |
|---|---|---|---|---|
| Simple Dual-Port (SDP) | Write only | Read only | 72-bit (combined) | FIFOs, streaming buffers |
| True Dual-Port (TDP) | Read + Write | Read + Write | 36-bit each port | Shared memory, CDC buffers |
In SDP mode, ports A and B are combined: Port A becomes the full-width write port and Port B becomes the full-width read port. This allows a maximum width of 72 bits (64 data + 8 parity) — ideal for FIFOs. In TDP mode, both ports operate independently, each up to 36 bits wide, and can use different clocks. This enables true shared memory between two clock domains.
Read/Write Collision Modes
When both ports access the same address simultaneously, the behavior is determined
by the READ_WIDTH_A/B and write mode settings:
| Mode | Simultaneous Read+Write Behavior | Best For |
|---|---|---|
| READ_FIRST | Old data is read before new data is written. Output shows previous value. | Collision-safe register files |
| WRITE_FIRST | New written data is immediately forwarded to the read output (transparent). | Look-ahead FIFOs |
| NO_CHANGE | Read output does not change during a write. Previous output is held. | Power saving; most FIFOs |
ECC — Error Correction Code
RAMB36E1 implements
SECDED (Single-Error Correct, Double-Error Detect) ECC in 72-bit
wide mode. The 8 parity bits in the ×9 width configuration store syndrome bits for
error detection and correction. Enable via EN_ECC_READ and
EN_ECC_WRITE generic parameters. ECC status pins
SBITERR and DBITERR signal single-bit and double-bit
errors.
Initialization
BRAMs can be pre-loaded with data at FPGA configuration time using
INIT_00 through INIT_7F parameters. Each parameter is a
256-bit hex string. This makes BRAMs ideal for ROM coefficient tables, boot code
storage, and lookup tables:
FIFO Mode
RAMB36E1 can operate as a built-in FIFO with dedicated read/write pointers and
flags: EMPTY, FULL, ALMOST_EMPTY,
ALMOST_FULL, RDCOUNT, WRCOUNT. Both
synchronous (single-clock) and asynchronous (dual-clock) FIFO modes are supported.
Xilinx FIFO Generator IP and the xpm_fifo_sync/xpm_fifo_async
macros use this mode internally.
BRAM Capacity — Across Device Families
Cascade
Multiple BRAMs can be cascaded to build deeper or wider memories. RAMB36E1 provides
CASCADEOUTA/CASCADEOUTB and CASCADEINA/CASCADEINB
pins for address extension, allowing two 36Kb BRAMs to form a 72Kb×1 deep memory
without routing overhead.
A: SDP (Simple Dual-Port) combines both RAMB36E1 ports to create one full-width write port and one full-width read port, enabling up to 72-bit wide access — the most common configuration for FIFOs. TDP (True Dual-Port) gives two fully independent ports, each capable of read and write with separate clocks, enabling shared memory between two independent clock domains at up to 36-bit width each.
Knowledge Check
1. What is the data capacity of one RAMB36E1 primitive (excluding parity bits)?
- A 18 Kb
- B 36 Kb
- C 40 Kb
- D 72 Kb
2. Which BRAM mode allows both ports to independently read AND write, making it suitable for shared memory between two clock domains?
- A Simple Dual-Port (SDP)
- B True Dual-Port (TDP)
- C Single-Port (SP)
- D FIFO mode
3. What ECC scheme does RAMB36E1 implement in 72-bit mode?
- A CRC-32
- B Hamming(7,4)
- C SECDED (Single-Error Correct, Double-Error Detect)
- D Reed-Solomon
4. Which generic parameter set is used to pre-initialize BRAM contents at configuration time?
- A ROM_CONTENT_00 through ROM_CONTENT_FF
- B INIT_00 through INIT_7F
- C PRELOAD_00 through PRELOAD_FF
- D MEM_INIT_0 through MEM_INIT_7
5. What is the standard read latency of a RAMB36E1 with output registers enabled?
- A 0 cycles (combinational)
- B 1 cycle
- C 2 cycles
- D 4 cycles
Practical Exercise
BRAM Design Challenge
-
Design a 1024×32-bit synchronous FIFO using BRAM in Vivado. Use
xpm_fifo_syncwith FIFO_DEPTH=1024 and DATA_WIDTH=32. - Verify the FIFO can run at 250MHz by checking the Vivado timing report after implementation. What is the worst negative slack?
- Check the Vivado utilization report: how many RAMB36E1 (or RAMB18E1) primitives does the FIFO consume?
- Enable ECC (set ECC_MODE="en_ecc"). What happens to the data width? How does BRAM count change? What extra output signals become available?