How Computers Work from the transistor up · chapter 12
12Instructions
At the end of the last chapter I made you a promise. The bytes sitting in RAM were about to stop being numbers and start being commands. This is where that happens, and it's stranger than it sounds. Take the pattern 00010010. Read it as a number and it's plainly 18 — one 16, one 2, done. But hand that exact pattern to the right circuit and it means something completely different: load register A from memory address 2. Nothing in the bits changed. Not one voltage moved. All that changed is which part of the machine is looking at them, and how. That is the whole idea of an instruction. Once you see it, the gap between "a pile of logic" and "a computer running your code" closes in a single step. In this chapter we'll lay the machine out as labelled blocks. We'll add the two registers that turn it from a calculator into a code-runner. We'll split one byte into an opcode and an operand, and walk a real instruction through its moves — timed, at last, by a clock we'll finally stop taking on faith and actually build.
01The machine, every wire named
Let's start from the thing you already built by hand. Last chapter you ran a little arithmetic program by pushing buttons. A pair of registers, an ALU, and an output, all hanging off one shared bus the way old handsets hung off a party telephone line. You enforced one rule yourself, by hand: only one device may talk on the wire at a time. Here it is again, with the hand-written timing program tacked to the wall like sheet music.
beat · do this
Aₒ
A→bus
Aᵢ
bus→A
Bₒ
B→bus
Bᵢ
bus→B
Σₒ
sum→bus
Oᵢ
bus→OUT
panel idle · 0 / 3
Nothing is asserted yet — every switch is down, the bus floats (hi-Z). Step through the score below.
Read it as sheet music for a wire: each row says who drives the bus and who latches it this beat. You are the machine right now — throwing the switches by hand.
Fig. 1. A little computer, laid bare: registers A and B, an adder, and an OUT register, all hanging off one shared bus — and only one thing may talk on it at a time. Below sits the whole program: a timing table, one row per clock beat, marking which out-enable line drives the bus (•) and which load-enable line latches it. Step through it and you are the machine, throwing those switches by hand. Notice beats 1 and 2 are the identical row, thrown twice — repeated addition, counting up by three. Now press let it run: the score plays itself, no hand on the panel. Freeze those rows onto a turning drum and wire it to the switches and you've built the thing that punches the panel for you — a program counter and a control ROM. That machine is the next chapter.
It works, but notice who's doing the thinking. You are. You read each line of the program, and you pulse the control lines that make it happen. The machine has no idea what it's doing. It's a datapath, and you're the driver. To hand it a whole program and step back, we have to add the parts that let it read commands out of memory and act on them itself. So let's draw the full machine. This time we include RAM, and we name every control line on it. Two honest warnings about that map. First, don't try to memorise the wall of two-letter tags. Each one only ever means "this block, talk" or "this block, listen", and we'll work a handful of them — the enables on the RAM, on the two new registers, and on register A. Second, a few of them are for blocks that don't exist yet. CO, CE and J belong to a program counter and a jump unit we haven't built. They're on the map because the finished machine has them, not because this chapter uses them. You meet those next chapter.
out-enable · drives the busload-enable · reads the buscontrol · no bus traffic
out-enables — put a byte ON the bus
load-enables — take a byte OFF the bus
control — steer, don't carry data
Click any control line to light the wire it drives. Hover a block to read what it does — or run a real bus transfer below to watch a byte move.
watch a transfer · one out-enable + one load-enable
Hover any block for its job.
Fig. 2. Here is the whole machine at once — every block that matters, wired around one shared 8-bit bus. The vocabulary of this chapter is the set of control lines: the orange out-enables (CO, RO, IO, AO, EO) that shove a byte onto the bus, the green load-enables (MI, RI/WE, II, AI, BI, OI, J) that latch one off it, and the gold control lines (CE, SU) that steer without carrying data. Click any line to light exactly the wire it drives; hover a block to hear its job. Then run a transfer: every move inside a CPU is just one out-enable feeding the bus while one load-enable drinks from it — and an instruction is nothing more than a timed list of which lines to raise.
Two blocks in there are new, and neither is a new kind of part. Both are plain registers you already own, each one hired to do a single job. But before we meet them, look hard at the block they both talk to — the RAM, the same addressable memory from Chapter 9. Feed it an address and it hands back the byte living in that cell. Everything a program will ever do begins with naming a cell.
WE is low — the write pulse is gated off.
Read is live: the addressed cell flows through the mux to DATA-OUT.
control — steers, carries no datadatapath — carries the bits
You set ADDR, flip WE, and pulse write by hand. That hand — deciding what happens when — is the seed of a control unit.
Fig. 3.The whole RAM, one block, its lines named. Two families of wire run through it. The control lines — ADDR, 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.
There's one thing to notice about that address input: it's not free-floating. An address is just a binary number on a handful of wires. The count of wires is what sets how many cells you can name at all. Four address wires reach exactly sixteen cells — 0000 through 1111. Slide the width and watch the reach.
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. 4. 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.
So let's stop treating that as an example and make it a decision. This machine gets 16 cells of RAM — and that choice settles the wiring for us. Sixteen cells need sixteen names, and sixteen names need four bits, so we run four address wires. Hold onto that number — four address wires, sixteen cells — and bank it as a fact about our machine, not as an illustration. It comes back the moment we split an instruction. When it does, it will decide the shape of every instruction we write. Now for the first new block. To feed RAM an address, we need somewhere to put that address and hold it steady while RAM reads. That's a register. But a register wired onto a shared bus needs two separate controls. This is worth re-seeing, because both new blocks are built exactly this way.
DRIVE
LISTEN
FLOAT
OUT-ENABLEdrive the bus?
LOAD-ENABLElatch from the bus?
float · the register sits off the bus, holding 170
THE OTHER DEVICEso LISTEN has something to hear
One wire, many devices — so a register needs two gates. The out-enable is a tri-state buffer: only when it’s on does the register push its value onto the bus; off, its output goes high-impedance and vanishes electrically. The load-enable latches whatever the bus is showing back into the register. Two drivers at once → contention. Nobody driving → the bus floats.
Fig. 5. One register on a shared bus. A plain latch isn’t enough — because dozens of devices share the same wires, a bus-connected register needs two enables. The out-enable is a tri-state buffer: switch it on and the register drives its value onto the bus; switch it off and its output goes high-impedance — electrically absent, as if unplugged. The load-enable latches whatever the bus is showing back into the register. That gives three clean postures: drive (out-enable on), listen (load-enable on, someone else driving), and float (both off — holding its value, hands off the wire). Break the discipline and the bus tells you: two drivers at once is contention, and latching a bus nobody drives captures pure noise.
There it is. A bus register has a load-enable (latch what's on the bus, on the clock edge) and an out-enable (a tri-state buffer that drives the bus, or lets go). Notice the words on the clock edge doing quiet work in there. That's the IOU I asked you to sign back in Chapter 8, when I told you a tick exists and asked you to take it on faith. Hold the discomfort; we settle that debt in section 04. Wire one of these so its output goes to RAM's address input instead of back to the bus, and you have the MAR — the memory address register. Its whole life is simple: catch an address off the bus, and hold it against RAM's address pins so RAM knows which cell we mean. Nothing exotic. A register with a destination.
02When a number becomes a command
Now for the reinterpretation the whole chapter turns on. We keep saying a byte "is" a number, but that was always a choice about how to read it. You've already seen one byte wear two faces. The same eight switches that sum to a number can, through one agreed lookup, spell a letter. Watch it again, and this time hold the question in your head: what decides which face you get? Answer it before you read on, and be honest about your first instinct. Mine was that the number is the real value and the letter is a costume painted over it. Hold that answer somewhere you can see it. We're about to check it.
0the number · 0–255
maps to
·the letter · via ASCII
00000000
nothing switched on — the byte is 0
the agreed table (ASCII) — your byte points at one row
▾
Fig. 6. Eight switches, each worth double its neighbour — so one byte counts from 0 to 255. Flip them and the lit place-values sum to a number; then one agreed lookup table, ASCII, turns that number into a character. Set the byte to 65 and it points at A. Nothing about 65 is the letter A — everyone just agreed it would stand in for it.
You just watched one agreed lookup dress the number 65 up as a letter. Now run the experiment that settles the prediction you made a moment ago. Below sits one byte on eight live wires, plus a lever that swings those wires between three readers. Aim them at the ALU, then at a font chip, then at the machine's control logic. Watch what each reader swears the very same voltages mean.
Swing the lever, then watch the switches: not one flips. The greyed readers aren’t off — their inputs just aren’t fed, the same quiet absence as a tri-state driver in Hi-Z.
Three circuits, one bundle — the wiring is the meaning.
The eight switches set eight voltages once; the lever only chooses which reader those wires feed.
The ALU treats each wire as a place value and sums them.
The decoder cuts the byte in two — top nibble picks the opcode, low nibble names a RAM cell — and steers control lines.
The font ROM uses the byte as an index into a glyph table — and honestly reports when a code has no picture. Click any bit to flip it: all three verdicts change at once, because all three were only ever readings of the same wires.
Fig. 7. Eight switches, one wire bundle, three sworn witnesses. Swing the lever to → decoder and back to → ALU, and keep your eye on the switches: not one voltage moves, yet the byte 00010010 is the number 18 (one 16, one 2) to the ALU, the order LDA 2 — opcode 0001, operand 0010, A ← RAM[2] — to the decoder, and to the font ROM the honest nothing of DC2, a control code with no picture. Press the 01000001 · 65 preset and the font suddenly has something to say: the glyph A. The pinned strip counts the swings while the bits sit still, because there is no true reading underneath — meaning is the wiring downstream. That is why one RAM can hold your numbers, your text, and the program itself: the bytes never had to be any one of them.
The bits don't decide. The reader decides. Route those eight wires into the ALU and they're a number to be added. Route them into an ASCII font and they're a glyph. Route them into the machine's control logic and they become an instruction. Same voltages, three meanings, chosen entirely by where the wires go. So there is no true reading hiding underneath. 18 was a costume too. Now let's build the reading that makes the byte a command — and let the machine size it for us. You have exactly eight bits, and two jobs to pay for: what to do, and what to do it to. Start with the second one, because it has a price you already know. It has to name any of our sixteen cells, and you already proved that naming sixteen cells costs four bits. So the bottom four are spent, and that half has a name: the operand. Now subtract, and you're holding the answer. Four bits left, one job left to buy with them — the top four are the opcode.
Notice what just happened there. Nobody agreed to four and four. You subtracted. And that means the boundary is not fixed — it moves when the machine moves. Build a RAM with eight cells instead of sixteen and what to do it to costs only three bits, which leaves five for what to do: a 32-operation instruction set on a machine with eight cells to point at. Widen the memory instead and the opcode starves. The two halves are eating off one plate, and the plate is eight bits wide. So an instruction format isn't tradition and it isn't taste. It's subtraction, done against the memory you built. Ours has sixteen cells, so ours is four and four. Split it and colour it.
not the number 18 — it's op 1 (LDA) on cell 2
Click any bit to flip it. One byte, cut in two: the top four bits name an action, the bottom four name the memory cell it acts on.
Fig. 8. The same eight switches from Chapter 1 — but a CPU doesn't read them as one number. It cuts the byte in two. The top nibble is the opcode: what to do (0001 = LDA). The bottom nibble is the operand: what to do it to (0010 = cell 2). So 00010010 stops being 18 and becomes op 1 on cell 2 — a verb and its target, packed in one byte. Flip any bit and watch the halves recolour and the instruction re-decode. That single cut is the whole idea of a machine instruction.
That four-and-four cut looks like a law, yet you watched it get computed. Memory billed its four bits first, and the opcode pocketed the change — so test the rule on machines we never built. Drag the RAM from 2 cells up to 128 and watch the boundary slide across the byte. Every slide trades instructions for reachable cells, because the format is subtraction, recomputed for each machine.
operand bits⌈log₂16⌉=4
opcode bits8−4=4
instructions2⁴=16
guess — opcode bits left at 32 cells?
home base — our 4+4 machine
Nobody chooses the cut. Memory bills ⌈log₂N⌉ bits to name a cell; the opcode keeps the change — 8−k bits, 28−k verbs. Resize the RAM and the boundary has no choice but to move.
Fig. 9. Drag memory depth through 2, 4, 8, 16, 32, 64, 128 cells and do the machine designer's arithmetic yourself. The RAM column grows, and every doubling bills the operand one more bit — the wire count under the byte says why: ⌈log₂N⌉ address wires, no fewer. The opcode keeps whatever change is left, 8−k bits, and the instruction set doubles or halves with it: our 16-cell machine lands on 4+4 and 2⁴ = 16 instructions; at 8 cells the cut slides to 3+5 and 32 ops appear; at 128 cells one opcode bit survives — a two-verb machine; at 2 cells you get 128 verbs and almost nothing to point at. Before you reach 32, lock in a guess on the chip and watch it settle. The gold CUT is nobody's decision — an instruction format is subtraction against the memory you built, not a convention anyone agreed on.
Read 00010010 that way and it's no longer 18. The opcode 0001 names an operation. The operand 0010 is the number 2. Put them together and the byte says "do operation 1 to the thing at 2." A quick word on terms, because they blur into each other easily. The opcode is the operation code: the verb of the machine's little sentence, the thing to do. The operand is the value that verb acts on: its object, the cell being pointed at. And argument is just a looser everyday word for that same operand. Now, how many different operations can a 4-bit opcode name? This is a counting question you've answered before: every bit you add doubles the possibilities.
combination 00 — reach all four
Fig. 10. Two switches, and only four places they can land: 00, 01, 10, 11. Flip them until you've lit all four — then add a third bit and watch the count leap to eight. Every bit you add doubles the states, because each old combination splits in two.
Four opcode bits give 2⁴ = 16 distinct instructions — a small but real instruction set. Now watch the two sixteens carefully, because they are not the same fact and it is easy to let them blur into one. Sixteen cells is the machine's shape, and it is a cause: it forced the operand to four bits. The operand is four bits, which reaches exactly sixteen values, so a 4-bit operand is precisely wide enough to name any cell in our RAM — the same sixteen cells, reached by the same four wires. Sixteen operations is not a cause at all. It's the change from the purchase: what four leftover bits happen to buy, once the memory has taken its share. One number sized the instruction. The other is what was left over afterwards. Now for the second new block. Something has to catch the fetched byte and hold it split — opcode one way, operand the other — while the machine acts on it. That's the IR, the instruction register.
Set a byte and press LATCH to catch it in the register.
The opcode fans to control logic the instant it's latched — it never touches the bus. IR-out gates a tri-state buffer that puts only the operand on the low four bus lines; the high four are forced to 0.
Fig. 11.The instruction register. A fetched byte lands in the IR and is held split down the middle. The high four bits — the opcode — run straight to the control logic the moment they're latched; they never ride the bus. The low four — the operand — sit behind a tri-state buffer. Assert IR-out and only that nibble is driven onto the low bus lines (the high lines are forced to 0). Edit the byte, LATCH it, then toggle IR-out and watch which half goes where.
The IR is one more register, but wired with a twist, and the twist has a reason. Its opcode nibble runs off to the control logic to steer what happens next. Notice the opcode never touches the bus at all, and ask why: the bus carries cargo, values on their way to some register or pin. The opcode is not cargo — it is the hand on the switches, choosing which enable lines get pulsed. Steering rides its own wires; freight rides the bus. Meanwhile its out-enable drives only the operand, the low four bits, onto the bus. That's the detail that lets an instruction carry an address with it. When the machine wants the operand, the IR pushes just those four bits onto the wire, straight toward the MAR. Opcode to the brain, operand to the bus. One register, two exits.
One thing before we run anything, because it's the question you're already asking. The IR is empty. Something has to put a byte into it, and nothing we have built does. Think about what that would take. The machine would need to hold an address of its own — not one an instruction handed it, but one it keeps for itself — pass that address to the MAR, and then drink RAM's answer into the IR instead of into register A. That move has a name: the fetch. Now the honest admission. In this chapter I am putting the byte into the IR by hand, the same way you've been pulsing every other control line. The part that would do it for us has to remember where it is in the program, and that is a program counter — the next chapter's whole job. So you didn't miss a paragraph. I'm the one holding the byte.
03Running one instruction: LDA
So we have enough to run the execute half of a real instruction — the half that happens once the byte is already in hand. Let's take the one hiding inside 00010010: opcode 0001, which we'll call LDA — load A. Its meaning is exactly this: A ← RAM[operand]. Go to the memory cell the operand names, pull the byte living there, and drop it into register A. Here's the path that value has to travel, lit up across the datapath.
LDA means A ← RAM[operand] — go to the cell the operand names, pull its byte, drop it into A.
T1 · IR.oe=1 → bus → MAR.le=1 (operand lands in the MAR)
the path is lit — operand → MAR → RAM → bus → A
Every block here was built in an earlier chapter. No new hardware — LDA is just a fixed route across parts you already have, on the one shared bus.
Fig. 12.LDA is nothing but a route across parts you already own. Pick it and the path lights up: the IR pushes its operand onto the shared bus, the MAR latches it and hands that address to RAM; then RAM drives the addressed byte back onto the bus and register A catches it — exactly A ← RAM[operand]. Slide the operand to load a different cell, and step the two beats: because the bus is one wire, T1 (operand → MAR) and T2 (RAM → A) can't happen at once — that ordering, not new hardware, is the whole trick.
One box in that route should bother you: the MAR. The IR already holds the operand, so why copy the address into a second register at all? Delete the middle-man and find out. Wire RAM's address pins straight onto the shared bus, step the two beats, and watch what happens the instant RAM starts answering.
the bus carries the address in T1, the data in T2 — whatever sits on RAM's address pins must remember T1.
T1 · IR.oe=1 → bus carries 0010 → MAR.le=1 latches it
MAR latched 2 — the address is parked off the bus
The MAR isn't furniture. One bus means address and data take turns — and something has to hold the address while the data takes its turn. Click RAM cells and re-run thrifty T2: every byte pattern traces a different chase.
Fig. 13. Try to fire the MAR. Flip to thrifty: pins tap the bus and run T1 — it works: the bus shows 0010, cell 2 lights, and the register looks like dead weight. Then press T2. RAM drives cell 2's byte 85 onto the bus — and the address pins, still wired to that same bus, instantly read its low nibble: RAM re-addresses itself off its own output, 2→5→4→15, until the clock edge slams A shut on 159 instead of 85. Click cells to store different bytes and every pattern chases a different tail. Flip the MAR back in: T2 runs clean because the MAR ignores the bus once loaded — one wire can carry the address or the data, never both in one beat, so something at RAM's door must remember what the bus said last beat. That memory is the MAR. It isn't furniture; it's forced.
Nothing in there is a new part. It's the MAR, the RAM, the bus, and register A, all built in earlier chapters. They're wired so a value can flow operand → MAR → RAM → bus → A. The only question left is timing: which control lines go high, in what order, so exactly one thing drives the bus at each moment. Set an opcode and operand and route it yourself. Flip enables and watch the value move (or get stuck, if you let two drivers fight).
1 · drive the source2 · assert LD · reg D3 · clock the tick
Nothing is driving the wire yet. Flip OE · operand to put the operand on the bus.
A tri-state driver either pushes its value onto the wire (enabled) or lets go entirely (Hi-Z). Enable two at once and they fight for the same copper — that's a short.
Fig. 14. The bus is a single stretch of copper shared by everything hanging off it, so exactly one driver may push a value onto it at a time. Pick an instruction, dial the operand, then flip the enables in order: drive one source onto the wire, assert the destination's load-enable, and clock the tick to move the value. Turn on two out-enables at once and watch the bus go red — two drivers fighting one wire is a short, with no clean value to latch. Routing data is just sequencing these enables correctly.
Play with it and you feel the constraint that shapes everything. The bus is a single shared wire, so the moves must happen in sequence. You cannot put the operand on the bus and read RAM onto the bus in the same instant. So LDA breaks into micro-steps, each one a single clean bus transaction, and each one landing on a tick. That tick is still the thing I asked you to take on faith in Chapter 8. Keep noticing that you're owed it. Step through them.
Ready. LDA = load A from memory. The address lives in the instruction; the data lives in RAM. It takes two clean bus moves.
One shared bus, so the iron rule is one driver at a time: each tick exactly one box is enabled OUT onto the wires and exactly one box latches them IN. Two enablers at once would be a short — bus contention.
Fig. 15.LDA in micro-steps. "Load A from address 2" isn't one magic move — it's two plain bus
transactions on two clock ticks. Tick ①: the instruction register drives its address field
onto the shared bus and the memory-address register latches it. Tick ②: RAM (now pointed at
cell 2 by MAR) drives that word onto the bus and register A latches it. Step through and
watch the rule hold every tick: one source drives, one destination latches — because the bus
is a single shared wire, and two things talking at once would just be a short.
Two beats, and you now know the single bus forces them: one wire, one transaction per tick. But forced is not the same as without alternatives. Suppose we spent more copper and ran four dedicated address wires beside the eight-wire data bus. Then the address and the data could travel in the same instant, and LDA would land in one beat. Toggle the extra copper in and out, run it both ways, and count what each design pays.
copper
8wires
time
2beats/LDA
shared
0
split
0
race bars = loads finished · number = beats spent
Shared bus: 8 wires, 2 beats per LDA. Press run LDA ▸.
blue carries the address, gold the data. One shared bus = one cargo per beat, so they queue — and the MAR exists only to hold the address across that queue. Pay 4 more wires and both travel at once.
Fig. 16.Buy the beat back with copper. Same machine, two dress codes. Toggle between
one shared bus (8 wires) and + a dedicated address bus (12 wires), and run LDA in each.
Shared: 2 beats — address then data must queue for the same wires, and the MAR exists to hold
the address across the queue. Split: 1 beat — the IR feeds the address wires while RAM feeds
the data bus in the same instant, and the MAR greys out to IDLE: the IR still holds the address, and dedicated copper delivers it
straight to RAM. Then press race and watch 100 loads cost 200 beats against 100. The second beat was
never physics — it was thrift. Four more wires buy it back, and that is exactly the trade real CPUs
make: separate address and data buses, copper for speed.
Two beats. On the first, the IR drives the operand onto the bus and the MAR latches it — now RAM knows which cell. On the second, RAM drives that cell's byte onto the bus and register A latches it — the load is done. Each micro-step is one source talking and one destination listening, marched forward by one tick of a clock. That raises the question we've dodged for four chapters: what is that tick, really?
04What keeps the beat
Back in Chapter 8 I asked you to take the clock on faith — a steady square wave, high for half a beat, low for the other half, forever, at a perfectly even tempo. I promised we'd build the real thing later. Later is now. First, remind yourself what the wave looks like. This even, tireless drumbeat is the thing every register on the machine listens to.
ticking — half high, half low, forever
We just take this square wave as given — a steady, evenly-timed drumbeat for the whole machine. What actually generates it (the oscillator) is the next figure.
Fig. 17. The whole machine marches to one drumbeat: a clock — a steady square wave that sits high for half the beat and low for the other half, over and over, at a perfectly even tempo. Hit running and watch it scroll past the now line; each rising edge is a tick, and the counter climbs one per full cycle. Drag speed to change the tempo — the shape never does. We take this beat as a given here; the oscillator that actually makes it is next.
So where does a wave like that come from? Nothing we've built oscillates. Every circuit so far settles to an answer and sits there. The trick is to build something that can't settle. Take an odd number of inverters and wire them in a ring, output back to input. Now the loop is a liar. Feed a 1 in and it must come back a 0, which comes back a 1, forever chasing its own tail. It never finds a stable state. That failure to settle, happening as fast as the gates can flip, is the oscillation.
NEVER SETTLES · the clock runs
period = 2 × n × gate-delay = 2 × 5 = 10 gate-delays laps: 0 · cycles: 0
One lap of the chase flips the tap once — half a cycle. Two laps make one full square wave, and every inverter adds one gate-delay to the lap. The delay that made mid-settle latching dangerous is the very thing that sets the tempo.
Fig. 18. Press Run ▶ and watch the strip on the right: the square wave that times every computer is being manufactured, one column per gate-delay, from the tap at the ring's centre. Each gold tick is the lit front completing a lap past the tap — and the bracket shows one full cycle taking exactly two laps: at 5 inverters the readout prints 2 × 5 = 10 gate-delays. Drag the slider to 9 and the printed period stretches to 18 while the drawn wave visibly widens — more gates, longer lap, slower beat. Set an even length and the trace flatlines dead across the strip: no walls, no cycle, no clock. The turn worth keeping: the same propagation delay that made latching mid-settle so dangerous is the very thing that sets the machine's tempo.
That's a ring oscillator — the honest, from-the-metal answer to "where does the clock come from." A real computer usually swaps the raw ring for a quartz crystal. Nudge that sliver electrically and it mechanically vibrates, ringing like a struck tuning fork at one exquisitely precise frequency (the piezoelectric effect). Same idea — a physical thing that will not hold still — just far more stable in its tempo. Either way, out comes the square wave. And that wave does its work at its edges, the near-vertical instant it snaps from low to high, or high to low. One full low-high-low is one clock cycle.
misses 0
both lit — green climbs, coral drops
Watch first, then press the green button: the wave freezes, the colours vanish, and you must click three rising walls yourself — then three falling. Click a flat stretch and see what it really is.
Fig. 19. First watch: every change of level is a wall — the rising edge is the 0→1 climb, the falling edge the 1→0 drop. Then press the green button and prove you can point at one: the wave freezes, the colours vanish, and you must click 3 rising walls, then 3 falling. Click the comfortable flat stretch instead and it flashes amber — held value, wide and lazy — because an edge is not the high shelf or the low shelf; it is the instant in the wall itself, sub-nanosecond thin. Land all 6/6 and you have done, with your own cursor, exactly what an edge-triggered register does: ignore the lazy stretches and fire on the wall. Your miss count is the lesson — the shelf is where everyone points first.
Now the subtle bit that makes the micro-steps actually safe. A source can be told to drive the bus whenever. The instant its out-enable goes high, its value starts crawling onto the wire. But a destination must not latch the moment its load-enable goes high, because the bus value isn't valid yet. Gates take real time to settle (that propagation delay we kept flagging), so for a few nanoseconds the wire holds garbage while the new value works its way through. So answer this one before I do. When exactly is it safe for the listener to grab? "When the bus is valid" is not an answer — the listener has no way to know that. It's a register, not a referee. What you need is an instant the whole machine agrees on in advance, the same instant for every block on the wire. There is exactly one, and it has been in front of you since the wave came on screen: drive anytime, but latch only on the clock edge. You AND every register's load-enable with the clock, so the catch happens at one sharp instant, after the bus has had the whole half-cycle to settle.
Don't take that on my word — go and get it wrong on purpose. The widget lets you drag the latch line anywhere across the beat. Drag it back into the smear, into the moment while the lines are still arriving at their own separate speeds, and watch what the listener bites down on: a value that was never on the bus at all, half old and half new, stitched together from a wire caught mid-thought. Then slide the latch onto the rising edge and watch the nonsense vanish. Being wrong on purpose is the cheapest anaesthetic there is. Once you've watched garbage get latched, the edge stops being a rule you were handed and becomes the only place the latch could possibly go.
latched mid-settle — 2/4 lines had flipped. Grabbed 0xA, not 0x9 — garbage
The driver shoved the bus at the window's start — it can drive whenever it likes. The listener may not: it must wait until the slowest line settles, then grab on the clock edge.
Fig. 20.The driver runs ahead; the listener waits. The bus carries four lines, and a new value doesn't arrive all at once — each line flips at its own moment, so the bus is a smear of half-old, half-new until the slowest line settles (that lag is the propagation delay). A driver can push its value the instant the window opens. A listener can't be so eager: it ANDs its load-enable with the clock and grabs only on the rising edge. Drag the latch line — catch the edge mid-settle and you bite down on garbage; wait for the bus to go valid and you get the clean 1001. Switch load-enable off and every edge slides past untouched.
That's the discipline under every transaction. The driver puts its value up early and holds it. The listener ignores the wobble and grabs the value exactly on the rising edge, when it's guaranteed clean. Reads wait for the edge. That single rule is why a machine full of gates that all take slightly different times to settle can still march in perfect, reliable lockstep.
05The same bytes, two lives
Step back and notice what we quietly assumed. The instruction 00010010 was sitting in the same RAM that holds the numbers the program works on. There is no separate "code memory." A cell holding a command and a cell holding a value are physically identical — the same eight flip-flops, the same address. A byte is an instruction only because, at that moment, the machine chose to fetch it into the IR and read it as one. That is the stored-program idea, and it is the reason a computer is universal rather than a fixed calculator.
Click a row's CODE / DATA tag. Watch: the eight bits never move — only the reader's reading of them flips. The tag isn't in the silicon; it's a decision.
Fig. 21. One strip of RAM. Every row is the same kind of thing — eight stored bits — and the bit colours here depend only on whether each bit is a 1 or a 0, never on what the row is "for." Tag a row CODE and the reader decodes those bits through the instruction format (the top nibble picks the opcode, the low nibble is its operand — the RAM cell it names); tag it DATA and the very same bits are just a number. Addresses 0x00 and 0x01 literally hold the identical byte 00010010 — tag them differently and one becomes an LDA 2 while the other is the number 18. That is the stored-program idea: a cell is a command only because the machine chose to fetch it as one. Nothing in the silicon marks the difference — the roles live in how the bytes are read, not in the bytes.
Both lives, one memory. Some rows we'll feed to the IR as opcode-plus-operand commands. Some rows we'll pull through the ALU as plain numbers. The RAM cannot tell them apart, because there's nothing to tell. Meaning lives in how a byte is read, not in the byte. We'll lean on that hard in a few chapters, when a program computes over its own instructions. For now, one honest admission about where we are. We ran a single instruction, but look back at what running it took.
a+b = ·−c+d = ·=·
next: load a → R0
seven clean beats — one talker, one edge, per beat.
The single register that raced tried to be talker and listener at once. Here every beat has a different one of each — so it just works.
Fig. 22.Running (a+b)−(c+d) by hand. This is the exact sum that made a lone register thrash when it tried to feed itself. On the bus it comes apart into seven calm beats: load a, load b, add and store, load c, load d, add, subtract and store. Watch each beat — one talker drives the wire, the ALU reads two registers, and exactly one register latches on the clock edge. No box is ever talker and listener at once, so nothing races — the answer just falls out. Set your own a, b, c, d and run it again.
A hand-timed ritual: enable this, pulse that, latch here, around again. It's the exact seven-beat dance you did by hand back in Chapter 10, now dressed up as LDA. It's a machine, but it's a machine with a human as its clock-and-controller. Every one of those choices, though, was a fixed function of the situation. For this opcode, on this step, assert these lines. And you already know what a fixed function with an answer for every case is: a lookup table. A ROM. The hand punching the control lines is about to be replaced by the same decode-and-OR furniture you built last chapter, pointed at the machine's own controls.
That's Chapter 12. A byte became a command the instant we split it into an opcode and an operand and fed the halves to different parts of the machine — opcode to the control logic, operand out to the bus. We added the two registers that make it possible. The MAR names a cell for RAM, and the IR holds the instruction and drives just its operand. We ran LDA as a fixed sequence of bus moves. And we finally built the clock — a ring oscillator that can't hold still — and saw why a read waits for its edge. But one instruction is not a program. A program is many instructions. To run them, the machine has to remember where it is and march forward on its own, advancing through RAM without a human reading the lines. That self-driven march is the fetch–execute loop, and it's next.