ULA: The Spectrum's Heart
One chip to rule them all
The Ferranti ULA combined display generation, memory access, keyboard scanning, and I/O into a single gate array—making the ZX Spectrum affordable and iconic.
Overview
The Uncommitted Logic Array (ULA) was Sinclair’s masterstroke of cost engineering. Instead of multiple discrete chips, a single custom IC handled video generation, memory contention, keyboard matrix scanning, tape I/O, and the border colour. This integration made the £125 Spectrum possible.
Fast facts
- Manufacturer: Ferranti (later versions by other fabs).
- Function: display, memory arbitration, I/O.
- Video output: PAL composite via RF modulator.
- Colour depth: 8 colours × 2 brightness levels = 15 unique colours.
Display generation
The ULA reads display memory and generates the video signal:
| Memory region | Size | Purpose |
|---|---|---|
| $4000-$57FF | 6KB | Pixel data (256×192, 1bpp) |
| $5800-$5AFF | 768B | Attribute data (32×24 cells) |
Screen layout quirks
The pixel data isn’t linearly arranged—it’s interleaved by character rows:
Address = $4000 + ((y & 0xC0) << 5) + ((y & 0x07) << 8) + ((y & 0x38) << 2) + (x >> 3)
This unusual layout made scrolling challenging but matched the ULA’s line-drawing requirements.
Attribute format
Each 8×8 cell has one attribute byte:
| Bits | Purpose |
|---|---|
| 0-2 | INK (foreground) colour |
| 3-5 | PAPER (background) colour |
| 6 | BRIGHT (affects both ink and paper) |
| 7 | FLASH (swap ink/paper every 16 frames) |
Colour clash
The one-attribute-per-cell design created the Spectrum’s infamous colour clash:
- Each 8×8 pixel block can only have two colours.
- Multicoloured sprites crossing cell boundaries show jarring colour changes.
- Games designed around this—or embraced the monochrome look.
Memory contention
The ULA and CPU share the same RAM:
- During active display, the ULA takes priority.
- CPU access to $4000-$7FFF is delayed during certain T-states.
- Contention follows a predictable pattern per scanline.
- Demo coders exploit this for precise timing.
Contention pattern (per 8 T-states)
T-state: 0 1 2 3 4 5 6 7
Delay: 6 5 4 3 2 1 0 0
I/O ports
| Port | Read | Write |
|---|---|---|
| $FE | Keyboard + ear input | Border colour + mic/ear |
| $FF | Floating bus (video data) | — |
Keyboard scanning
Half-row selection via address lines:
| A8-A15 | Keys read at $FE |
|---|---|
| $FEFE | SHIFT, Z, X, C, V |
| $FDFE | A, S, D, F, G |
| $FBFE | Q, W, E, R, T |
| $F7FE | 1, 2, 3, 4, 5 |
| $EFFE | 0, 9, 8, 7, 6 |
| $DFFE | P, O, I, U, Y |
| $BFFE | ENTER, L, K, J, H |
| $7FFE | SPACE, SYM, M, N, B |
Border colour
Writing to port $FE sets the border:
ld a, 2 ; red
out ($fe), a ; set border colour
Bits 0-2 select the colour (0-7). Games used border stripes for loading screens and effects.
Cultural impact
The ULA’s compromises—colour clash, contention, limited colours—became the Spectrum’s identity. Programmers learnt to work with these constraints, creating a distinct visual style. The techniques developed here still inform retro game design.