SRAM & Memory Design
Memories fill most of a modern SoC's area. Learn the 6T SRAM cell, read and write operations, read stability and writability (cell ratio, pull-up ratio), static noise margin, array organisation (rows, columns, decoders, sense amplifiers), bitline timing, memory compilers, register files, DRAM and non-volatile memories, and how RTL infers memories.
An SRAM bit is two cross-coupled inverters (storing Q and Q̄) plus two access transistors connecting it to a pair of bitlines when its wordline is raised: six transistors per bit. It is fast and uses the standard logic process, which is why caches and on-chip buffers are SRAM.
Designing SRAM is a balancing act: the cell must be strong enough not to flip during a read, yet weak enough to be overwritten during a write — while being as small as the process allows, because there are billions of them.
An analogy
An SRAM cell is a light switch held in place by two springs (the cross-coupled inverters). Reading is peeking at the switch without bumping it; writing is pushing hard enough to flip it. The access transistors are the door you open to peek or push.
The 6T cell
Two inverters in a loop hold a value indefinitely while powered. Two NMOS access transistors, gated by the wordline, connect the storage nodes to bitlines BL and BLB. Many cells share each bitline (a column) and each wordline (a row).
Read and write
Read: precharge both bitlines to VDD, raise the wordline; the side storing 0 slowly discharges its bitline; a sense amplifier detects the small difference. Write: drive one bitline to 0 and raise the wordline; the access transistor overpowers the cell's pull-up and flips it. Sizing ratios make both operations reliable across process variation.
Array organisation
A memory macro is more than cells:
- Row decoder selects one wordline from the address
- Column multiplexer selects words from wide rows
- Precharge, sense amplifiers and write drivers per column
- Timing control generates self-timed read/write pulses
- Redundant rows/columns repair manufacturing defects
Variation, assist circuits and other memories
At advanced nodes random V_t variation threatens stability, so SRAMs add read/write assists (wordline under-drive, negative bitline), use 8T cells with separate read ports, or separate voltage rails. Register files use multi-port cells; DRAM stores charge on a capacitor (1T1C, dense but needs refresh); Flash, MRAM and ReRAM are non-volatile. Memory BIST tests every cell at production.
Formulas
- Read stability:
Cell ratio β ≳ 1.2–2 keeps the '0' node from rising enough to flip - Writability:
Pull-up ratio ≲ 1.8 lets the access device overpower the pull-up - Bitline swing time:
t = C_BL · ΔV / I_cell - Bitline capacitance:
C_BL ≈ rows · C_cell + C_wire - Capacity:
bits = 2^(address bits) × word width
Worked example: Capacity
Given: 12 address bits, 32-bit words
Find: Capacity.
- 2¹² = 4096 words × 32 bits
Answer: 131 072 bits = 16 KiB
Worked example: Bitline time
Given: 256 rows, 0.5 fF/cell, 50 fF wire, 40 µA, ΔV = 100 mV
Find: Swing time.
- C_BL = 178 fF
- t = 178 fF × 0.1 V / 40 µA
Answer: ≈ 0.445 ns
Worked example: Cell ratio
Given: Pull-down W/L = 2, access W/L = 1.2
Find: β and read stability.
- β = 2/1.2 = 1.67
Answer: β ≈ 1.67 — within the typical stable range
Synchronous single-port RAM that tools map to an SRAM macro
// Synchronous single-port RAM (behavioural model that synthesis maps to
// an SRAM macro / block RAM). One read or write per clock.
module sp_ram #(
parameter AW = 8, // address width -> 2**AW words
parameter DW = 32 // word width
) (
input wire clk,
input wire we, // write enable
input wire [AW-1:0] addr,
input wire [DW-1:0] wdata,
output reg [DW-1:0] rdata
);
reg [DW-1:0] mem [0:(1<<AW)-1];
always @(posedge clk) begin
if (we) mem[addr] <= wdata;
rdata <= mem[addr]; // read-first behaviour
end
endmoduleA registered read port is what lets synthesis recognise a memory (Yosys infers a single $mem cell here). In ASIC flows this behavioural model is replaced by a memory-compiler macro with the same ports.
Bitline timing estimate
# SRAM read: time for the cell to develop a sense-amp swing on the bitline
rows = 256
c_cell, c_wire = 0.5e-15, 50e-15 # F per attached cell, F of wire
I_cell = 40e-6 # read current, A
dV = 0.1 # required bitline swing, V
C_bl = rows * c_cell + c_wire
t = C_bl * dV / I_cell
print(f"bitline C = {C_bl*1e15:.0f} fF, swing time = {t*1e9:.3f} ns")
for rows in (128, 512):
C_bl = rows * c_cell + c_wire
print(f"{rows} rows/bitline -> {C_bl*dV/I_cell*1e9:.3f} ns")
# bitline C = 178 fF, swing time = 0.445 ns
# 128 rows/bitline -> 0.285 ns
# 512 rows/bitline -> 0.765 nsA tiny cell current must discharge the whole bitline; taller arrays are slower. That is why arrays are split into banks and why sense amplifiers detect ~100 mV instead of waiting for a full swing.
Common mistakes
- Wrong: Asynchronous reads in RTL for large memories. — Right: Register the read so tools infer SRAM/BRAM instead of flip-flops.
- Wrong: Ignoring read-during-write behaviour. — Right: Specify read-first/write-first/no-change to match the macro.
- Wrong: Very tall arrays for density. — Right: Bank the array to keep bitlines short and fast.
Applications
- CPU caches: L1/L2/L3 caches are large SRAM arrays.
- AI accelerators: On-chip SRAM buffers weights and activations.
- FPGA block RAM: Configurable dual-port SRAM blocks.
- Register files: Multi-ported SRAM-like arrays in processors.
Key takeaways
- 6T cell: cross-coupled inverters + 2 access devices.
- β for read stability, pull-up ratio for writability.
- Bitline C and cell current set read time.
- Register reads in RTL to infer memories.
Going further
- Butterfly curve: SNM measured as the largest square fitting between inverter VTCs.
- Memory compilers: Generate macros of any size with timing/power models.
- Compute-in-memory: Performing MACs inside SRAM arrays for AI.