Lookup Tables (LUT)
Understand how a 64-bit SRAM cell implements any Boolean function — the heart of every FPGA logic block. Learn LUT6 structure, truth tables, distributed RAM, shift register, and chaining modes.
What is a LUT?
A Look-Up Table (LUT) is a small SRAM that stores the truth table of any Boolean function. A 6-input LUT (LUT6) contains 26 = 64 memory cells, each holding one bit. The six address inputs A1–A6 select one of the 64 cells, and the stored value appears at the output. This single mechanism allows an FPGA to implement any logic function — AND, OR, XOR, complex combinational expressions — without using physical logic gates.
During bitstream loading, the synthesis and implementation tools program each LUT's 64 SRAM cells with the correct truth table values. A new bitstream reprograms those cells to implement a completely different function — this is the core of FPGA reconfigurability.
LUT6 Internal Structure
The LUT6 in Xilinx 7-series (and later families) has the following internal organization:
- Memory array: 64 × 1-bit SRAM cells
- Address inputs: A1–A6 (6-bit address, 26 = 64 entries)
- O6 output: Full LUT6 mode — uses all 64 bits, all 6 inputs active
- O5 output: LUT5 mode — uses only the first 32 bits (A1–A5 address), A6 ignored
- Dual-output mode: O5 and O6 can implement two independent 5-input functions simultaneously if they share inputs A1–A5
Truth Table and INIT String
The INIT parameter is the 64-bit hexadecimal value programmed into the LUT. Each bit in the INIT string corresponds to one row of the truth table, with bit position equal to the decimal value of {A6,A5,A4,A3,A2,A1}.
Example — 6-input AND gate: The output is 1 only when all six inputs are 1, which is address 63 (binary 111111). So only bit 63 of INIT is 1:
// 6-input AND gate — only address 63 (all inputs high) gives output 1 INIT = 64'h8000000000000000 // 3-input AND (A1, A2, A3) — address 7 (binary 000111) gives output 1 INIT = 64'h0000000000000080 // 6-input XOR — output 1 when odd number of inputs are high INIT = 64'h6996966996696996 // 4-input MUX (A5=select, A1-A4=data) // Automatically inferred by synthesis from Verilog: assign y = sel ? d1 : d0;
LUT as a 2:1 Multiplexer
When A6 acts as a select signal, the LUT6 naturally implements a 2:1 MUX between two independent 5-input functions computed on A1–A5. This is fundamental to how wide multiplexers and priority encoders are built in FPGA fabric. A 4:1 MUX uses two LUTs plus the F7MUX.
LUT Chaining — F7MUX and F8MUX
Each Slice contains dedicated multiplexers that chain LUT6 outputs:
- F7MUX: Combines two LUT6 O6 outputs with a select signal → implements any 7-input function
- F8MUX: Combines two F7MUX outputs → implements any 8-input function
- These paths use dedicated silicon wires, not the general routing matrix — adding only ~0.1ns delay
- Critical for wide address decoding: 16:1 MUX uses 2 F7MUXes + 1 F8MUX = 4 LUTs
LUT as Distributed RAM (Slice M Only)
In Slice M (not Slice L), the LUT SRAM can be written — making it a 64×1-bit RAM. Key properties:
- Write port: Synchronous — write occurs on clock edge when write enable is asserted
- Read port: Asynchronous by default — data available immediately without waiting for a clock
- Combining LUTs: Four LUTs in a Slice M → 256×1-bit RAM (or 64×4-bit RAM)
- Use cases: Small register files, FIFOs, coefficient tables, shift registers
LUT as Shift Register (SRL)
A single LUT6 in Slice M can be configured as a 32-bit shift register (SRL32) or 16-bit shift register (SRL16E):
- Synchronous shift operation on clock edge
- Dynamic tap selection via 5-bit address input — read any bit position at runtime
- Extremely efficient: replaces 32 flip-flops with 1 LUT for delay lines
- Used for: pipeline delay compensation, audio buffers, deserializers
A: 264 distinct 6-input Boolean functions. Every possible truth table configuration of 6 inputs can be stored in the 64 SRAM cells. This is why LUT6 can implement literally any 6-input logic function.
LUT Operating Modes
| Mode | Address Bits | Memory Depth | Output | Use Case |
|---|---|---|---|---|
| LUT6 Logic | A1–A6 (6-bit) | 64 bits | O6 | Any 6-input Boolean function |
| LUT5 Logic | A1–A5 (5-bit) | 32 bits | O5 | Any 5-input Boolean function (A6 unused) |
| Dual 5-input | A1–A5 shared | 32+32 bits | O5 + O6 | Two independent 5-input functions simultaneously |
| Distributed RAM | A1–A6 (write addr) | 64×1-bit SRAM | O6 (async read) | Small LUTs, register files (Slice M only) |
| SRL32 | 5-bit tap select | 32-bit shift reg | Tap output | Delay lines, FIFOs, pipeline alignment |
| ROM | A1–A6 | 64 bits (fixed) | O6 | Coefficient tables, constant lookup |
LUT Size Comparison Across FPGA Vendors
| Vendor / Family | LUT Inputs | SRAM Cells | Dual Output | Notes |
|---|---|---|---|---|
| Xilinx 7-series / UltraScale (AMD) | 6 | 64 | Yes (O5+O6) | Industry-leading — LUT6 dual output for fractioning |
| Intel (Altera) ALM | 8 (adaptive) | 256 (shared) | Yes (2×4-input) | Adaptive Logic Module — configures as two 4-input or one 6-input |
| Lattice ECP5 | 4 | 16 | No | Simpler LUT4; more LUTs needed for 5-6 input functions |
| Lattice iCE40 | 4 | 16 | No | Ultra-low power; basic LUT4 architecture |
| Microchip PolarFire | 4 | 16 | Partial | 4-input LUT with carry and optional register |
LUT Utilization Reporting in Vivado
After synthesis or implementation, Vivado's Utilization Report shows:
+----------------------------+-------+------+------------+ | Site Type | Used | Avail | Util% | +----------------------------+-------+------+------------+ | Slice LUTs | 4832 | 20800 | 23.23 | | LUT as Logic | 4120 | 20800 | 19.81 | | LUT as Memory | 512 | 9600 | 5.33 | | LUT as Distributed RAM | 384 | 9600 | 4.00 | | LUT as Shift Register | 128 | 9600 | 1.33 | +----------------------------+-------+------+------------+
Each Slice contains 4 LUTs. A design using 4832 Slice LUTs occupies approximately 1208 Slices. "LUT as Logic" is pure combinational/sequential logic. "LUT as Memory" means the SRAM write capability is used (Slice M only).
Interactive LUT Simulator
Toggle inputs A1–A6 to see which truth table address is selected and what the LUT output is. Choose a preset function to load its INIT value.
Preset Functions
Input Values
INIT Value (64-bit hex)
Truth Table (scroll to see all 64 rows)
| Addr | A6 | A5 | A4 | A3 | A2 | A1 | Out |
|---|
Knowledge Check
- 16
- 32
- 64
- 128
- The default output value when all inputs are 0
- The 64-bit hexadecimal truth table value programmed into the LUT
- The initialization delay in nanoseconds
- The number of inputs used by the function
- 16
- 32
- 48
- 64
- No — one LUT can only produce one output
- Yes — using O5 and O6 outputs for two 5-input functions sharing A1–A5
- Yes — but only for XOR functions
- Only with external multiplexers
- Slice L only
- Slice M only
- Both Slice L and Slice M
- Any Slice with a BRAM adjacent
- Connecting two CLBs across the routing matrix
- Multiplexing flip-flop outputs to I/O pins
- Combining two LUT6 outputs for 7-input functions
- Selecting between clock domains
Practical Exercise
Manual LUT Mapping
(a) Write the 64-bit INIT value for a 3-input majority function. The output is 1 when 2 or more of A1, A2, A3 are high. Which address entries (0–63) should have output = 1? (Hint: {A3,A2,A1} must have popcount ≥ 2.)
(b) Write the INIT for a 6-input XOR gate. The output is 1 when an odd number of inputs are high. (Hint: try toggling inputs in the simulator above — the XOR preset shows you the answer.)
(c) In Vivado, create a Verilog module:
assign y = a & b & c;
After synthesis, open the schematic (F4), double-click the LUT primitive, and find
its INIT value in the properties panel. Does it match your hand-calculated value?
(d) Change the logic to a 7-input AND. Re-synthesize. How many LUTs does Vivado use now? What F7/F8 MUX structures appear in the schematic?