◈ computers mapVol 1 · Ch 09/19
How Computers Work from the transistor up · chapter 09

09Addressable Memory (RAM)

Chapter 8 ended on a small triumph and a big limitation. The triumph: we built a register — eight flip-flops on one clock — that snapshots a whole word at a single edge and holds it rock-steady. The limitation is that it holds one word, and only one. That's fine for a running total. But it falls apart the moment a computation needs several numbers alive at the same time. Almost every computation does. So here is the question this chapter turns on: how do you build not one register but a thousand of them, and hand yourself the power to say "give me slot number 617" and get exactly that one back? The answer has a name you already half-know: RAM, random-access memory. Open it up and there is no new physics inside. It's a bank of registers — the very ones we just built — plus one genuinely new circuit. That circuit does something we haven't needed until now. It takes an address, a plain binary number, and lights up exactly one of the registers, leaving every other one dark. That circuit is the decoder, and it's the whole trick. Around it, reading turns out to be an old friend in disguise: AND to mask, OR to merge. That's nothing but the multiplexer from Chapter 3 grown wide. And writing turns out to hide a genuine trap — the trap that motivates the clean design real chips actually use. No magic. Just registers we own, a decoder that picks one, and the honest hazard that comes with letting a machine write to itself.

01One register can't hold a computation

Let's start by holding on to what we already have, so the gap we're about to hit is unmistakable. Here is a single register from last chapter: eight D flip-flops sharing one clock, capturing a whole byte on one rising edge. It's a solid one-word memory. Load a byte into it below, and remember its one hard limit: whatever you put in replaces whatever was there. It has room for exactly one number.

D inputs — click a bit to set the wires on the wires · 0 CLK Q outputs — the byte held in the register held · 0
wires ≠ register — hit CLOCK to store
Eight flip-flops, eight separate D wires, one clock. Change the D bits all you like — Q won’t budge until the single rising edge, and then all eight snap over together. That instant is when a whole number first gets stored.
Eight flip-flops = a register. Each of the eight D flip-flops watches its own input wire, but they all share a single clock line. Set the byte on the wires by clicking the D bits — nothing reaches the Q outputs yet. Press CLOCK and one rising edge makes all eight flip-flops sample at the very same instant, latching the whole byte at once. That shared-edge capture is the first device that stores a complete number: the register.

Now watch that one-number limit bite. Take a computation only a hair more ambitious than a running total — say (a + b) − (c + d). Trace it and count how many values have to be alive at once. You need a, b, c, and d all sitting somewhere, plus room for partial results as you go. A single register can hold exactly one of them. The moment you load b, your a is gone. Follow the values below and watch them pile up with nowhere to live.

( a + b ) ( c + d ) with  a=7 · b=2 · c=4 · d=1 a machine with 1 register · each holds one value alive now: 0  ·  peak this trace: 3
We’ll evaluate (a+b) − (c+d) one micro-step at a time. Press Step ▶ and watch how many values must stay alive at once.
step 0 / 7
ready — press Step to begin
Fig 2. Step through a computation as small as (a+b) − (c+d) and count the values that have to be alive at the same time. Read a, and b still can’t be dropped; add them, and the partial 9 has to be held while you go fetch c and d — at the peak, three values need a home at once. A single register holds exactly one, so the extras spill into the orange “nowhere to live” zone. Bump registers available up to 3 and the pile finally fits — which is the whole reason a machine needs somewhere to put its working values: bulk, addressable storage.

So the need is plain. We want many registers, and a way to talk to a specific one without a separate wire running to each. Here's the mental model to hold for the rest of the chapter, and it's deliberately mundane: a numbered table. Every row is one word of storage. Every row has an address — a number that names it, 0 at the top, counting down. And the whole device offers just two verbs: read (name an address, get its word back) and write (name an address, drop a new word in). That's it. That table, made real in silicon, is RAM. Browse it below: pick an address, see the one word that lives there.

But how does a row actually get picked? That word address is hiding a step, and it's worth stopping on. Start with the dumbest thing that could work. Give every register its own select line — a private wire running from you straight to that register's door, with nothing else on it. Raise line 5 and register 5 wakes up. Every other register stays dark. No code, no cleverness, no new circuit. And it works perfectly. Now scale it and count. A thousand registers means a thousand select lines leaving the chip. A thousand pins. A thousand traces on the board, one per slot, forever. Sit with that number until you recoil, because the recoil is the point. The dumb selector is completely correct and completely unbuildable, and both halves of that will matter.

RAM · a numbered table of words addr the word stored there (8 bits) hex char READ name an address → get its word address 2 010 the word 01001101 0x4D · 'M' word to drop in 00000000 into slot 2
read(2) → 01001101 · the slot holds one word, and only that word
Fig 3. Memory is nothing fancier than a numbered table: rows of words, each pinned to an address. There are only two verbs. Read — name an address and the slot hands back the one word it holds (drag the address slider or click a row; watch the readout on the right). Write — flip to write mode, dial up a byte, and drop it into the slot, overwriting whatever was there. That's the whole contract of RAM: every slot has a name, holds exactly one word, and answers to just read and write.

The word "random-access" in the name is worth demystifying right now, because it sounds fancier than it is. It doesn't mean the memory is random. It means you can jump to any address in one step. The 900th slot is no harder to reach than the 3rd. Compare that to a tape, which you'd have to spool through in order. Random access = direct access: any slot, same cost. That single promise is exactly what the decoder we're about to build delivers.

02A table with a shape — depth × width

Before we build anything, let's give the table its two honest dimensions. Every real memory chip is spec'd by exactly these two numbers. Down its height it has some number of slots — that's its depth, how many words it can hold. Across each slot it has some number of bits — that's its width, the size of one word. A memory that is 16 slots deep and 8 bits wide holds sixteen bytes. Multiply the two and you get its total capacity. Depth and width are independent knobs. Grab both below and watch the grid grow.

width = 8 bits depth = 8 slots each row = one addressable slot   ·   each column = one bit 8 slots · depth × 8 bits each · width 64 bits total · capacity = 8 bytes 3 address lines
8 slots × 8 bits = 64 bits (8 bytes)
Two independent dials. The same capacity can be a tall-thin memory or a short-wide one — depth × width is all that fixes the total.
Every memory has two independent dimensions. Depth is how many slots it holds — each with its own address, counted down the left. Width is how many bits live in each slot, counted across the top. Multiply them and you get the one number that fixes the total: capacity = depth × width bits. Drag either dial and the grid grows in that direction alone — a memory can be tall and narrow or short and wide and still store exactly the same number of bits.

Now the piece that makes the whole thing tick. The address is itself just a binary number, so its bit-count is what caps the depth. This is the Chapter 4 place-value idea wearing a job. With k address lines you can write 2ᵏ distinct patterns — 00, 01, 10, 11 for two lines — and each pattern names one slot. So two address wires reach four slots. Four wires reach sixteen. Ten wires reach a thousand and change. Run it backward: to address N slots you need ⌈log₂N⌉ lines. Address width and depth are locked together. Slide the number of address lines below and watch how many slots it can name leap upward.

address bus 4 lines decoder nameable slots — one step per line added 1 line 16 lines 16 2^4 = 16 slots
4 lines → 24 = 16 slots · highest address 1111
one more line would double it to 32
Address width and depth are locked together: k lines can name exactly 2k slots — no more, no fewer.
Fig 5. An address is just a binary number, and each wire is one bit of it. Slide the address lines from 1 to 16 and watch the staircase climb one equal step at a time — but the slot count printed on top doubles at every step: 2, 4, 8, 16… 65,536. That's the lock: k lines name exactly 2k slots, so to reach N slots you need ⌈log₂N⌉ lines. Address width and depth aren't two knobs — they're one. The only way to name more memory is to run more wires.

Notice what that costs us and what it buys us. It buys the "random-access" promise cheaply: naming any of a thousand slots takes just ten wires, not a thousand. But it hands us a job we haven't done before. Those ten wires arrive as a coded number, and the storage array underneath speaks in one wire per slot. Something has to translate the compact binary address into a single "this one" signal aimed at the right register. That translator is the decoder, and it's next.

Before we build it, say the objection out loud, because it's the right one to have. We just squeezed a thousand select lines down to ten address wires. Now the decoder's whole job is to turn those ten back into a thousand. So what did we actually buy? Here's the answer, and it's the reason the scheme is worth anything at all. The ten wires are the ones that travel. They cross the chip, ride inside an instruction, sit written down in a program you'll write later. The thousand never leave the memory's own doorstep. They're local fan-out — short hops from the decoder to the registers standing right beside it. We compressed the expensive part and decompressed the cheap part. That's the whole trade, and it's a bargain.

03The decoder — pick exactly one

Here's the problem stated at the metal. We have, say, four registers and a 2-bit address on two wires, A₁ and A₀. We need four output lines, one per register. The address 00 should light only line 0, 01 should light only line 1, and so on. First, one piece of wiring that shapes everything you're about to see. Each address bit runs past the gates on two rails, not one: the bit itself, and its inverse through a NOT gate. We mark the inverted rail with a bar over it, so A̅₁ is the wire that is high exactly when A₁ is 0. Now the building block, and it's one you already trust: the AND gate, which goes high only when all its inputs are high. Wire line 0's AND to fire on "A₁ is 0 and A₀ is 0" — feed it both address bits inverted, which is to say the rails A̅₁ and A̅₀. Wire line 1's AND to fire on "A₁ is 0 and A₀ is 1," and so on down. Each register gets an AND gate watching for its own binary address, tapping the two rails that are high for its code. Before you look: which two rails must line 3's gate tap? Then check yourself against the 2-to-4 decoder below: four AND gates, each matching one code.

A1 A0 = 0 0 A1 0 A0 0 A1 A̅1 A0 A̅0 0 1 0 1 four AND gates · one-hot select · exactly one line goes high
Set the address here, or click the A1 / A0 pads in the figure. Each AND gate is pre-wired to watch one code — via the straight or the inverted (A̅) copy of each bit.
A1 A0 = 00 → gate 00 fires → register 0 selected.
Predict first: for the address 10, which single gate sees 1·1 on both inputs — and why do the other three each catch a 0?
A 2-to-4 decoder, built from nothing but AND gates. Two address bits enter on the left; each is copied straight and, through a NOT gate, inverted (the A̅ lines) — giving four signal lines. Each AND gate is hard-wired to one code: gate 00 watches A̅1·A̅0, gate 11 watches A1·A0, and so on. For any address, exactly one gate finds both its inputs high and fires — a one-hot select line that switches on that register alone.

Before you touch it, predict. Set any address in your head. How many of the four output lines light? Here's the answer, and it's the one worth carving into stone. For any address you set, exactly one output line is high and all the others are low. Not two, not zero — precisely one. This is called the one-hot property, and it isn't luck. It falls straight out of the four gates you just wired, in two strokes. Never two: each AND gate demands a different combination of the address bits, so pick any two gates and no address can satisfy both. Never zero: four gates, four possible addresses, one each — no address is an orphan. Exclusive plus exhaustive forces exactly one — at four lines, at sixteen, at any width, including the widths you could never sit and check by hand. So the decoder converts a compact number into a single unambiguous pointer. And it answers the promise we made earlier. Every AND gate is watching the address at the same instant. The address is broadcast to all of them at once. It never travels to the slot. That's why no slot is nearer than another. Set the address below and watch it: only one line ever lights.

address = 5 binary 101 A2 A1 A0 lines HIGH 1
Flip the three address bits. Each output line is an AND of the three rails it taps — it fires only when all three are lit. Watch the count: it is always 1.
one-hot ✓ — exactly one line is high
Fig 7. A 3-to-8 address decoder, wired the way real memory is. Each output line is an AND of one rail from every pair — line 5 taps A2, A1', A0, so it fires only for 101. Flip the bits or sweep all 8 and the tally never moves off 1: never two, because no two lines demand the same pattern; never zero, because every one of the eight patterns belongs to some line. That single lit wire is how an address picks exactly one cell to read or write.

And nothing about "four" was special, so let's state the general machine. An n-to-2ⁿ decoder takes n address bits in and produces 2ⁿ output lines out, always exactly one hot. Three bits fan out to eight lines. Four bits fan out to sixteen. The k lines that named 2ᵏ slots a moment ago are exactly the k inputs of a k-to-2ᵏ decoder. The address width, the slot count, and the decoder's fan-out are one and the same number. That's the through-line of the whole chapter. Widen the decoder below and watch the address bits and the output lines grow in lockstep, one-hot the whole way.

address bits (n) decoder output lines (2ⁿ) 3 → 8 one-hot decoder
Nothing was special about four. Drag decoder width and the address bits and the output lines double together — always exactly one line hot. Click a bit to flip it, or sweep the address.
1 hot · 7 cold
n = 3 bits  →  23 = 8 lines  ·  address 101₂ = 5  →  line 5 is the one that fires
one address in, one line out — one-hot
Fig 8. The same machine at every size. Slide decoder width from n=1 to n=5 and three numbers move as one: the stack of address bits grows by one, the count of output lines doubles to 2ⁿ, and the decoder's fan-out doubles with it. Flip a bit or sweep the address and watch the single hot line walk the stack — never two lit, never none. Address width, slot count, and fan-out were never three facts to memorize; they're one number, n, wearing three hats.

04Reading — mask, then merge

We can point at one register now. But pointing isn't reading. Every register is still sitting there with its stored bits, and we need only the pointed-one's bits to actually come out. The first half of the answer is a gate you met as plumbing back in Chapter 3: the AND gate as a valve. Feed a register's data bit into one leg of an AND and its decoder line into the other. When the decoder line is 0, this register isn't selected: the valve is shut and the AND outputs a flat 0, no matter what the register holds. When the line is 1, the valve opens and the data bit walks straight through. Re-meet the AND-as-valve below: the enable leg decides whether the data survives.

Hold on, though — why do we need a valve at all? The instinct is to just tie all four registers' bit-0 outputs onto one wire and let the selected one drive it. Try it, and you learn a rule this book leans on from here to the end. A gate output always drives. It never abstains and never lets go. Every moment it's powered, it is either pushing high or pulling low. Tie four of them together and three of them are still shoving. You haven't selected a register. You've started an argument on a wire, between outputs that cannot back down. So the order is forced. You silence first and merge second, and the AND valve is how you silence.

pipe SHUT — output pinned to 0 ENABLE leg 0 0 DATA leg 0 OUTPUT
enable
data
enable 0 · data 0 → output 0 — pipe shut
Try this: leave enable at 0 and flip the data leg — the output won't budge. Now set enable to 1 and flip data again: the output copies it exactly. One leg of an AND is just an on/off valve for the other.
Fig. An AND gate is a valve. The enable leg works the wheel: turn it to 0 and the sluice drops across the pipe — the data signal knocks against the gate but the output stays pinned at 0, no matter how you flip the data leg. Turn enable to 1 and the gate lifts: now the pipe is open and the output simply copies whatever the data leg is doing. One leg gates; the other passes. That is the whole trick behind using AND to switch a signal on and off.

So the decoder's one hot line arms exactly one register's valves and shuts everyone else's. Every unselected register is now masked to a clean 0, and only the selected register's real bits are alive. Now we just need to collect them onto one output. That's the other Chapter 3 friend: the OR gate as a merge, where several inlets join into one pipe. OR together the corresponding bit from all four registers. Three of them are forced to 0 by their shut valves, so they contribute nothing. The survivor's bit — a 0 or a 1 — passes through the merge untouched. Re-meet the OR-as-merge below: any live inlet reaches the tap, and here only one inlet is ever live.

an OR wired as a merge — at most one inlet is ever live the merge 0 A 0 B 0 OR A = 0 · B = 0 → OR = 0
nothing to carry — output rests at 0
Predict first: light just one inlet — does the merge care which one, or does whichever is live simply reach the tap?
You can only feed one at a time here. That "at most one is ever 1" promise is exactly what lets a plain OR do the mux's final combine.
Fig. An OR gate, drawn as plumbing: two inlet pipes A and B join at one junction and continue as a single output. Feed either inlet and the live signal streams through the merge to the tap — the junction never asks which pipe it came from, it just passes whatever arrives. Because at most one inlet is ever live here, the OR does no real deciding; it simply combines two lines into one. That's the final step of a multiplexer: the address gate lights exactly one input, and this merge carries it home.

Put the two halves together and you have the whole read path, one bit-column at a time. The decoder lights one line. That line opens one register's AND valves and slams the rest shut. The deselected registers all mask to 0. Then a big OR merges the column, so the lone survivor emerges on the output wire. Do that for every bit-column in parallel and the selected word appears whole. Trace one read below: set an address, watch one line go hot, the others mask to zero, and the OR carry the survivor out.

2→4 DECODER A1 A0
address 10 → word line 2 is hot
line 2 hot · registers 0,1,3 mask to 0 · each column’s OR passes register 2 → word 1100
Fig 11. The whole read, end to end. Pick an address: the 2→4 decoder lights exactly one word line gold and leaves the other three cold. A hot line throws open that register’s AND valves so its stored bits spill downward; every deselected register is clamped shut and masks to 0. In each bit-column a big OR merges all four rows — three zeros and one survivor — so the survivor emerges unharmed. Run that OR once per column and the entire word appears at the bottom. Click a bit-column to watch a single bit get built.

Now step back and look at what we just built, because it isn't new. It's an old device grown up. "Steer one of several inputs to a single output, chosen by a control code" is the exact definition of the multiplexer from Chapter 3. A 2-to-1 mux picked between two inputs with one select bit. This read multiplexer picks between many registers with a whole address. And here's the honest part, because there are two different ways to scale a selector up wide. You can stack 2-to-1 muxes into a tree, each layer halving the field until one input survives. Or you can go flat: one decoder, an AND-mask, an OR-merge — which is exactly what we just built. The two roads compute the identical function. Memory takes the flat one for a plain reason: the decoder is already sitting there, because the write path is going to need it anyway. See the tree road below, as three stacked 2-to-1 muxes: same answer, different shape.

pair A · picks D0 / D1 pair B · picks D2 / D3 final · picks A / B 2:1 2:1 2:1 0 1 0 1 0 1 sel s0=0 sel s0=0 sel s1=0 D0 0 D1 0 D2 0 D3 0 M0=0 M1=0 0 output Y
The two select bits are a 2-bit address. Predict which D reaches Y — then flip data bits and watch only the addressed one move it.
MUX‑A → M00
MUX‑B → M10
MUX‑C → Y0
address 00 → picks D0 · Y = 0
Click any Dn pad on the left to flip its bit.
Fig 12. There are two ways to build a wide selector, and they compute the identical function. The flat one is the one you just built with your own hands: a decoder raises one line, an AND‑mask lets only that line's bits through, an OR‑merge collects them. The tree one is this: no decoder, no AND‑mask, no one‑hot line anywhere — just three copies of the 2‑to‑1 MUX you already built, stacked. Two boxes each pick within a pair; a third picks between the pairs. The two select bits are a 2‑bit address, high bit first: s1 s0 read as a binary number names D s1s0, so 00 fetches D0 and 11 fetches D3. Flip the data inputs and only the addressed one moves the output — the rest are wired in, computed, and ignored. If both work, why does memory use the flat form? Not because the tree is wrong — because the decoder is already sitting there for the write path, so the flat selector is nearly free. That's the whole reason. Once a circuit is a box, you stop caring what's inside it: no gates in sight; just boxes commanding boxes.

So there's the reader, complete and honest: an address in, one word out, any slot reachable in a single step. Try it end to end below. Type an address and watch that one register's stored word flow out onto the data lines, while every other register stays silently masked. This is "random access" made physical: slot 12 is no more work to fetch than slot 1.

ADDRESS IN 3→8 DECODER SHARED DATA LINES ↓ ONE WORD OUT ↓ STORED
WORD OUT
0101 0010
0x52 · ‘R’
addr 0 → slot 0 drives the bus
reach cost: 1 step · slot 7 is no farther than slot 0
Fig 13. The complete reader. Eight registers hang off one set of data lines. Feed an address into the decoder and it raises exactly one word line — that register alone pushes its byte onto the bus, while all seven others sit masked, saying nothing. Address in, one word out. And here is the quiet miracle of random access: slot 7 is reached in the very same single step as slot 0 — no scanning, no winding forward. Any slot, one hop, made physical.

05Writing — the enable, and the hazard

Reading was the gentle half: it disturbs nothing. Writing is where memory earns its keep, and where the real subtlety lives, so let's do it carefully. Recall first the ritual by which a single register accepts a new value. You present the data on D and it waits there at the door. The register captures it on the next rising clock edge, and only if its enable says so at that moment. Everywhere else in time, the register just holds. Re-watch that one-register write ritual below: data waits at the door until the clock edge comes and the enable lets it in.

Before we scale that to a whole bank, two words have to come apart, because everything ahead hangs on the difference. A clock edge says when. It's the drumbeat, and it alone decides the instant a register samples its input. An enable says whether. It's a yes-or-no vote about that instant, and it has no power to create one. Chapter 8's register captures on an edge and at no other time. It is not a door that hangs open while you feed it. Hold that line hard: when versus whether. Every knot left in this chapter is those two words quietly collapsing back into one.

Q fed back — with EN low the register reloads itself 2-to-1 mux 0 1 → 0 select 0 EN · load-enable · low 1 D · data you set this Q · D flip-flop · moves only on the edge 0 D Q 0 CLK · global · edge 0
CLK is global and free-running; EN is low, so the mux is feeding Q back into itself. Raise EN — then watch Q do nothing until you tick.
Fig 14. A register bit, built the way this chapter builds every one of them: edge-triggered, with the enable kept well away from the clock. CLK is global — it runs into the flip-flop through no logic at all, it ticks whether you want it to or not, and it is the only thing in this picture that can ever move Q. EN is a level: it steers a 2-to-1 mux on the flip-flop's D pin, choosing between the new bit and Q reloading itself. So raise EN and watch nothing happen — the mux swings, the D pin changes, and Q sits there until the next rising edge. Then drop EN and tick anyway: the edge still lands, the flip-flop still captures, and what it captures is its own old value, so the bit rides through untouched. The enable changes what gets captured; the clock alone decides when. Q never follows D; it only ever samples it.

Now scale it to the bank, and the decoder pays off a second time. We put the same data word on a shared set of input wires running past every register at once. But we only want one of them to actually swallow it. So we take each register's write-enable and gate it with that register's decoder line ANDed with a global write signal. When you assert write, only the addressed register — the one whose decoder line is hot — sees its enable go high and latches the data. All the others see a low enable and hold their old contents, untouched. Write one slot below and watch the other three bystanders sit perfectly still.

shared DATA (click bits to set) 2→4 decoder addr 00 WRITE = 0 one bus, all four
gate rule
bystanders that moved this run: 0
Set the bits, pick a slot, pulse WRITE — only that one latches.
The data is offered to every register at once. What decides who catches it is each register's own enable: its decoder line AND the global write line. Flip to write only to see why the AND matters.
Fig 15. The data bus runs down past every register at once, so each slot sees the value to be written — yet only one catches it. Each register's load enable is its own decoder line AND the global write line. Pick a slot, click the bits, and pulse WRITE: the addressed register's gate goes &=1, its cells flash green and update, while the other three sit perfectly still — their enable never left 0. Flip the rule to write only and pulse again: with no address-AND, the write line alone opens all four and clobbers the whole bank. That single AND gate per register is the entire trick of addressable memory.

Here's a fork in the design worth naming. The naive version has a bug, and the clean version is what real chips do. The tempting shortcut is to gate the clock: feed each register a clock that only ticks when it's selected. It seems to work, but it's fragile. You're now manufacturing clock edges out of AND gates, and any glitch on the address or write line can forge a stray edge. The cleaner discipline keeps the true clock global — every register ticks on the same real edge, always. Instead it gates a separate write-enable input, which decides whether the register loads new data or reloads its own output on that edge. Same clock for all; only the enable is steered. Compare the two schemes below: gated clock versus global clock with a steered enable.

That phrase — reloads its own output — earns more than a clause, because it's the strangest move in the chapter. Every rising edge, the register captures something. It has no choice: the clock never stops and never asks permission. The write-enable only picks what gets captured. Either the new data on D, or the register's own Q, looped back around into its own input. So holding a value isn't the absence of writing. Holding is writing, over and over, with yourself as the source. And look at what does the picking: one of two inputs, chosen by a control bit. That's a 2-to-1 mux, the thing you rebuilt one section ago, now wired with its own output as one of its inputs. That's the whole fix in one sentence: the enable changes what is captured, never when.

① Naive fix — gate the clock D CLK EN & CLK·EN → clock D-FF 0 Q ⚡ glitch write! ② Clean standard — global clock + write-enable D mux sel = EN CLK clock always ticks — EN just steers the mux D-FF 0 Q reload own value when EN=0 timeline — same CLK & EN feed both CLK EN CLK·EN gated ↑ = a register capture · orange ✗ = an edge the AND gate manufactured (glitch write)
clock
inputs
gated reg Q = 0 · global reg Q = 0agree
both idle — flip EN then pulse CLK to load D
Fig 16. Two ways to build a register that only writes when told. ① Gate the clock: feed CLK·EN through an AND gate into the flip-flop — obvious, and wrong. Hit ⚡ manufacture a glitch (it parks CLK high, then raises EN): the AND output swings 0→1 with no real clock edge, and that phantom rising edge clocks the left register — a write nobody asked for. ② Global clock + write-enable: the clock runs straight to every flip-flop, and EN steers a mux that picks load-new D vs reload-own Q. The clock never passes through logic, so it can never grow a spurious edge; enable changes what gets captured, never when. Run both, toggle EN and D, and watch the timeline: the two registers agree on every honest edge — and split the instant the gated clock invents one.

And now the trap the gated-clock scheme sets, because feeling it is the best argument for the clean one. Suppose write is held high and you change the address while it's still asserted. As the address bits flip, the decoder's hot line jumps from the old register to the new one. In that jump, a line that was low goes high. To a register whose write is gated by that rising line, a low-to-high transition looks exactly like a clock edge. It latches — even though you never meant to write to it. That's the spurious-write hazard: a rogue rising edge, born from moving the address mid-write, corrupting a slot you never addressed on purpose. Trigger it below: hold write high, slide the address, and watch a register you didn't choose quietly capture garbage. One honest note, since the figure below says real chips gate the clock and this chapter says don't. Both are true, and the gap between them is the whole discipline. A real SRAM does gate a line into its cells. But the edge it gates with belongs to a write pulse, generated by the chip's own timing chain, fired only once the address has been latched and allowed to settle. The address never gets to make the edge. So what we're banning isn't the AND gate. It's letting a signal that moves whenever it likes decide when a register samples. When the pulse owns the edge, gating is safe. When the address owns it, you get the hazard you just triggered.

WRITE = 0 DATA BUS (D) 0b1010 2 → 4 DEC addr 0
Each register's clock is gated: clk = select & WRITE. Hold WRITE high, then slide the address — the decoder's hot line jumps old→new, and that 0→1 edge clocks a register you only meant to point at.
slots clobbered: 0
safe: WRITE=0 — sliding the address only picks who to read.
A real RAM cheats to save gates: instead of giving every register the global clock and a private write-enable mux, it gates the clock — each register is clocked by select & WRITE. That works only if WRITE pulses cleanly. Hold WRITE high and slide the address, and the decoder's hot line jumps from the old slot to the new one; that low-to-high transition is a clock edge to the register you just addressed, so it latches whatever garbage is floating on the data bus — a slot you only meant to read. The fix is to make the write pulse, not the address, own the clock edge.

Last, lift your eyes from the wires to the shape of what you've made, because it's a landmark. Every input we've been toggling by hand — the address lines, the write line, the data going in — is a control signal. Its job is not to carry a number but to steer the machine: to say which slot and whether to write. And the registers, the decoder, the read multiplexer, the data wires threading them — that's a datapath, the roads the numbers travel. Right now you are the thing setting those control signals. Hold that thought: a human punching address-and-write is a job a circuit could do instead, and that circuit is the seed of a control unit a few chapters out. See the whole RAM as one block below, its control lines named.

ADDR 00 which cell same address also steers the read mux → SEL 2 → 4 decoder word / select lines WE write-enable · 0 0 1 2 3 0000 0000 0000 0000 register file — the memory DATA-IN value to store · 1010 read mux 0000 DATA-OUT = 0
WE is low — the write pulse is gated off.
Read is live: the addressed cell flows through the mux to DATA-OUT.
You set ADDR, flip WE, and pulse write by hand. That hand — deciding what happens when — is the seed of a control unit.
The whole RAM, one block, its lines named. Two families of wire run through it. The control linesADDR, WE, and the decoder’s word-lines — carry no data at all; they only steer, deciding which cell is chosen and whether a write may happen. The datapath — the registers, the data-in bus, the register outputs, the read mux and data-out — is what actually carries the bits. Slide address and the same signal steers both the write-decoder and the read-mux; notice a write only lands when WE is high and you pulse write. Toggle control lines / datapath to see each family alone. And the thing setting ADDR, raising WE, choosing the moment to pulse — that’s you. Automate that hand and you’ve built a control unit.

And that's Chapter 9 — the chapter where one word became a thousand, addressable. We started stuck: a lone register holds exactly one number, and any real computation needs several alive at once. The fix was to picture a numbered tableRAM — with just two verbs, read and write, and two honest dimensions, depth and width. Its address is a plain binary number whose bit-count caps the depth (k lines name 2ᵏ slots). The one new circuit was the decoder: n address bits in, 2ⁿ lines out, always exactly one hot. That's the one-hot property, guaranteed because no two AND terms can be satisfied together (never two) and every address owns a gate (never zero). Reading turned out to be an old friend: AND to mask the deselected registers to zero, OR to merge the survivor. That's the Chapter 3 multiplexer grown wide into a read multiplexer. And writing hid a real trap — the spurious-write hazard of a gated clock — which is exactly why real memory keeps the clock global and steers a clean write-enable instead. Underneath it all we spotted the two things every computer is made of: a datapath the numbers ride, and the control signals that steer them. But look at how we wired it. Every register's output runs to the read multiplexer, and its input runs from the data lines. Inside this RAM that count stays honest: add a register, and you add one output and one input. The wires grow in step with the parts, no faster. The squeeze starts one level up. A computer isn't one bank. It's a CPU, a RAM, an I/O port and more, and each of them needs to reach every other. Wire that mesh point-to-point and N parts need N(N−1)/2 links, growing as the square of the components. There's a trick that collapses that rat's nest to a single shared connection per part. It's called a bus — and it comes with a way to physically short-circuit your own hardware. That's next.

iolinked.com
Written by Ajai Raj