11.1 ROM: Read-Only Memory and Lookup Tables

Explain how ROM stores fixed data as a decoder-driven array, read an address/data table correctly, and identify where ROM belongs in a digital system.

Read-Only Memory (ROM) is a digital storage device whose contents are fixed — normally at the time of manufacture or programming — and cannot be changed by ordinary write operations during normal system operation. A ROM behaves like a large combinational lookup table: you present an address on its address lines, and after a propagation delay the corresponding stored data word appears on its data output lines. There is no write control input needed for normal use, no clock is required for the read itself, and the same address always produces the same data. ROM is needed anywhere a system must remember something permanently across power cycles — boot code, character-generator fonts, fixed lookup tables for math functions, state machine encodings, and microcode — because ordinary flip-flop-based memory (RAM) loses its contents the instant power is removed. Conceptually, a ROM is nothing more than an address decoder feeding a fixed OR-plane: each address line combination activates exactly one internal row, and that row's fixed pattern of connections determines which data-output bits read as 1.

Core concept: address in, data out

A ROM with N address lines can select 2^N unique locations, and each location stores a fixed word of W bits, usually described as an N × W ROM (sometimes written 2^N × W). For example, a ROM with 10 address lines and an 8-bit data bus is a 1024 × 8 ROM — 1024 distinct addresses, each holding one byte. The address lines act purely as selectors: internally, a full 1-of-2^N decoder converts the binary address into a single active row line, and that row's hard-wired pattern of connections to the output lines is what the decoder 'reads out' onto the data bus.

Because there is no write path exercised during normal operation, ROM read access is a pure combinational operation from the digital designer's point of view: apply an address, wait for propagation delay (the read access time), and the data is valid and stable at the output. This is why ROM is often modeled functionally as a lookup table (LUT) in RTL or software simulation — given an input pattern, it returns a pre-defined output pattern, with no internal state that changes over time.

• Read-only storage — data is fixed and does not change during normal operation • Address lines select one of 2^N stored locations via an internal decoder • Data output lines present the stored word for the currently selected address • Used as a lookup table: any fixed input→output mapping can be implemented directly as a ROM

Step-by-step working of a read cycle

Step 1: the external circuit places a binary value on the ROM's N address inputs. Step 2: the internal address decoder converts this N-bit pattern into one active output line out of 2^N possible lines (this is exactly the decoder circuit studied in combinational logic — an N-to-2^N decoder). Step 3: the single activated line enables the fixed connections belonging to that row, which drive the ROM's W data-output lines high or low according to the permanently stored pattern for that address. Step 4: after the decoder delay plus the output-driver delay (together the 'access time'), the data lines settle to valid, stable logic levels that downstream logic can safely sample.

Because the mapping from address to data is fixed at manufacture (mask-programmed ROM) rather than being written electrically in the field, a plain ROM has no write cycle at all — the 'write' happened once, at the factory, by physically including or omitting a connection at each row/column intersection of the internal array.

Practical application: lookup tables and fixed code storage

The most common real use of ROM-style storage is a lookup table: instead of computing a function (sine, a CRC polynomial step, a 7-segment display pattern, a character bitmap) with logic gates every time, you pre-compute every possible output and store it, indexed by input. Reading becomes a single-cycle table lookup rather than a multi-gate computation, trading storage capacity for speed and simplicity — a classic space/time trade-off in digital design.

In real hardware today, pure mask-programmed ROM is mostly used for extremely high-volume, never-changing data (game cartridges historically, or fixed boot vectors baked into a chip at the foundry) because a factory mask change is expensive; but the conceptual model — address decoder plus fixed data array — is exactly the same model used inside PROM, EPROM, EEPROM, and Flash, which only differ in how (and whether) the array contents can later be altered.

ROM sizing notation

Address lines determine how many distinct words can be stored (2^N). Data lines determine how wide each stored word is (W bits). Total bit capacity is always (number of locations) × (word width).

ROM size notation:  2^N × W
  N = number of address lines  → 2^N addressable locations
  W = data output width (bits per word)

Example:
  10 address lines, 8-bit data bus  →  2^10 × 8 = 1024 × 8 ROM
  Total stored bits = 2^N × W = 1024 × 8 = 8192 bits (1 KB)

Code Examples

This is the ROM acting as a pure lookup table: the function 'double mod 16' was never computed by a multiplier — each possible answer was pre-stored at the address equal to its input, so a read is just a table lookup.

Address 10 → decoder activates row 2 → data output = 0100

4-address x 4-bit ROM used as a lookup table (e.g. "double the input, mod 16"):

Address (A1 A0) | Data (D3 D2 D1 D0) | Decimal
       00       |      0000          |   0
       01       |      0010          |   2
       10       |      0100          |   4
       11       |      0110          |   6

Read cycle for address 10:
  1. Apply A1=1, A0=0 to the address inputs
  2. Internal decoder activates row "2" only
  3. Row 2's fixed pattern drives D3D2D1D0 = 0100
  4. After access time, data bus reads 0100 (decimal 4)

ROM internal structure

Every ROM variant (ROM/PROM/EPROM/EEPROM/Flash) shares this decoder + fixed-array structure; they differ only in how the array is programmed.

Address bus (N lines)
            │
            ▼
  ┌───────────────────┐
  │  N-to-2^N Decoder  │
  └─────────┬──────────┘
            │  one active row of 2^N
            ▼
  ┌───────────────────────────┐
  │  Fixed storage array       │
  │  (row × column connections)│
  └─────────┬──────────────────┘
            ▼
      Data bus (W lines, output only)

Important Rules

A ROM is characterized as 2^N × W: N address lines give 2^N locations, W data lines give the word width.

Reads are purely combinational from the address — no clock is required to read stored data.

Normal operation provides no write path; contents are fixed once programmed.

The same address always returns the same data until the device is reprogrammed (if reprogrammable) or replaced.

Where ROM shows up in real systems

Classic ROM lookup tables appear in 7-segment display decoders, fixed math tables (sine/cosine tables in early synthesizers), character generator fonts for older text terminals, and fixed boot vectors in microcontrollers. The lookup-table idea itself lives on inside FPGAs, where every logic cell is literally a small configurable ROM (a LUT) used to implement arbitrary Boolean functions.

Treating a ROM's address lines as if more address lines make the stored words wider.

Address line count (N) sets the number of locations (2^N); data line count (W) sets the word width — they are independent dimensions.

Confusing the two dimensions leads to miscalculating a chip's total capacity; always compute capacity as (2^N locations) × (W bits/location).

[conceptual] What determines the number of distinct addressable locations in a ROM? A. The width of the data bus (W) B. The number of address lines (N), giving 2^N locations C. The clock frequency applied to the ROM D. The number of write cycles performed

B. The number of address lines (N), giving 2^N locations — Address lines feed an N-to-2^N decoder; N address lines therefore select among 2^N unique storage locations, independent of data width.

[interview] Why is a ROM read described as a 'combinational' operation rather than a 'sequential' one? A. Because ROM requires a clock edge to latch the address B. Because the output depends only on the current address input (after propagation delay), with no internal stored state that changes over time during reads C. Because ROM cannot be used in synchronous systems D. Because ROM outputs are always tri-stated

B. Because the output depends only on the current address input (after propagation delay), with no internal stored state that changes over time during reads — A read from ROM has no memory of previous reads and needs no clock: given a stable address, the data output settles to a fixed value determined purely by the address, which is the defining property of combinational logic (as opposed to sequential logic, which also depends on stored state).

A ROM has 12 address lines and a 16-bit data bus. (a) How many addressable locations does it have? (b) What is its total storage capacity in bits, and in kilobytes?

2^12 = 4096 locations. Total bits = 4096 × 16 = 65,536 bits = 8192 bytes = 8 KB.

Capacity = 2^N locations × W bits per location; then convert bits to bytes (÷8) and bytes to KB (÷1024).