# The control unit

*The sequencer that pulls the levers*

The control unit is the sequencer that steps through the micro-operations of each instruction, raising the control lines that gate values onto the bus and trigger register loads. A ring counter supplies the steps, and the current opcode selects which lines fire on each one.

Group: Processor
URL: https://digiwleea.wleeaf.dev/learn/control/

All the blocks are built, but something has to **orchestrate** them: decide, each clock, which register drives the [bus](https://digiwleea.wleeaf.dev/learn/tristate/), which register loads, and what the [ALU](https://digiwleea.wleeaf.dev/learn/alu/) computes. That is the **control unit**. It is the part that makes the others cooperate, and it works in two layers: a **stepper** that counts through the sub-steps of an instruction, and **decode logic** that turns the current step plus the opcode into a set of control-line levels.

## Why an instruction needs several steps

A single instruction cannot happen in one clock, because the shared bus can carry only one value at a time. Consider 'add the number at address 9 to the accumulator'. The CPU must, in order: put 9 on the address bus and read memory, send that byte to the [ALU](https://digiwleea.wleeaf.dev/learn/alu/)'s `B` input, and finally load the ALU result into the accumulator. Each of those is a separate **micro-step**, and each uses the bus differently. So the control unit walks through a short fixed sequence of steps for every instruction.

## A ring counter makes the steps

The stepper is a **ring counter**: a loop of [flip-flops](https://digiwleea.wleeaf.dev/learn/dff/) in which exactly one is high at a time, and the high bit rotates one position each clock. Its outputs `T0, T1, T2, ...` are the micro-step lines, lit one after another, then wrapping around. It is one-hot, just like a [decoder](https://digiwleea.wleeaf.dev/learn/decoder/)'s output, but it advances by itself on the clock instead of being chosen by an address. `T0` marks the first step of an instruction, `T1` the second, and so on.

_Circuit diagram: A 4-step ring counter (RING4), the heart of the control sequencer: after reset, exactly one of T0-T3 is high, and the hot step advances each clock, T0 to T1 to T2 to T3 and back. Before the first clock the outputs read Z; open it in the lab, pulse reset, then run the clock and watch the single high step march around._

## The clock: one heartbeat, two jobs

Every storage element in the machine, the ring counter, the [program counter](https://digiwleea.wleeaf.dev/learn/counter/), the accumulator, the [instruction register](https://digiwleea.wleeaf.dev/learn/instruction-register/), shares **one clock line**. That single signal does two jobs each tick, and the order matters. During the time the clock is steady, the control lines (decoded from the current step and opcode) settle, and exactly one [tri-state](https://digiwleea.wleeaf.dev/learn/tristate/) drives the bus while the destination's `D` input watches it. Then the clock **edge** fires: every enabled register captures whatever was on the bus at that instant, and the ring counter advances to the next step. So one clock period equals one micro-step: levers set up while the clock is level, transfer committed on the edge.

> **KEY:** This is why a synchronous CPU is predictable. Nothing moves *between* edges; values just settle. Everything moves *at* the edge, all at once, on the same clock. Slow the clock down and the machine runs in slow motion but computes the identical result; the clock sets the pace, not the logic. A real CPU's "3 GHz" is just this edge firing three billion times a second.

## From steps to control lines

The first two steps are the **fetch**, and they are the same for every instruction: step `T0` puts the [program counter](https://digiwleea.wleeaf.dev/learn/counter/) on the bus and reads memory into the [instruction register](https://digiwleea.wleeaf.dev/learn/instruction-register/); a step then increments the PC. After that the steps **branch on the opcode**. The decode logic is a wall of [AND](https://digiwleea.wleeaf.dev/learn/and/)/[OR](https://digiwleea.wleeaf.dev/learn/or/) gates: a control line is raised when the right step is active and the opcode matches. For example, the accumulator's load line is `(T2 AND opcode==ADD) OR (T1 AND opcode==LOAD) OR ...`. Each control line is just an OR of the step-and-opcode conditions that should turn it on.

```
control_line = OR over (step, opcode) pairs that should assert it
```

It helps to see the lines laid out as a **control matrix**: one row per micro-step, one column per control line, a `1` where that line is asserted. Here is the `ADD addr` instruction, with `PC.out` (drive the PC onto the bus), `MEM.read` (RAM drives the addressed byte out), `IR.load`, `PC.inc`, `B.load` (load the ALU's `B` operand), and `ACC.load`:

| step | PC.out | MEM.read | IR.load | PC.inc | B.load | ACC.load |
| --- | --- | --- | --- | --- | --- | --- |
| T0 (fetch) | 1 | 1 | 1 | 0 | 0 | 0 |
| T1 (incr) | 0 | 0 | 0 | 1 | 0 | 0 |
| T2 (operand) | 0 | 1 | 0 | 0 | 1 | 0 |
| T3 (compute) | 0 | 0 | 0 | 0 | 0 | 1 |

_The micro-steps of ADD addr. Each row is one clock: T0 fetches (PC drives the bus, RAM reads, IR loads); T1 increments the PC; T2 reads the operand byte into the ALU's B; T3 loads the ALU sum into the accumulator. Reading down a column tells you the logic for that one control line._

Read **down** the `ACC.load` column: it is `1` only on `T3` of an ADD, so its logic is `T3 AND opcode==ADD` (ORed with the steps of any other instruction that also loads the accumulator, like `T2` of LOAD). Read **across** a row and you get the full set of levers for one micro-step. The whole control unit is just this matrix turned into [AND](https://digiwleea.wleeaf.dev/learn/and/)/[OR](https://digiwleea.wleeaf.dev/learn/or/) gates, one gate cluster per column.

> **WARN:** The cardinal rule of the matrix: in any single row, **at most one `*.out` line may be `1`**. Two sources driving the bus at once is the [tri-state](https://digiwleea.wleeaf.dev/learn/tristate/) short (`X`) that fights itself. Loads are safe to overlap (many registers can sample the bus on one edge), but drivers are not. A bug in the control logic that raises two `*.out` lines on the same step is the classic way a hand-built CPU corrupts its bus. (The one place the table above bends this for brevity is fetch: on a strict single bus, `T0` is really **two** bus phases, first the PC drives the bus so a memory-address latch captures the address, then memory drives the byte back to the `IR`. We fold both into one `T0` row here; on each real phase only one driver is live, so the rule still holds.)

**Q (Check yourself):** On step `T2` of `ADD`, the control unit raises `MEM.read` and `B.load`. Why is it safe to assert both at once, but it would *not* be safe to also raise `ACC.out` on that same step?

**A:** `MEM.read` is the one driver putting the operand byte on the bus; `B.load` is a destination sampling the bus. One driver, one (or more) readers is fine. But `ACC.out` would be a **second driver** on the same wire, so the bus would have RAM and the accumulator fighting over it: contention (`X`). At most one `*.out` per step; any number of loads.

> **TIP:** This style is a **hard-wired** control unit: the instruction set is literally a pattern of gates. Bigger CPUs often store the control-line patterns in a small memory (a **microcode** ROM) indexed by step and opcode, so the instruction set can be changed without rewiring. Both compute the same thing: which levers to pull on each micro-step.

> **KEY:** That is the last piece. The ring counter gives the rhythm, the opcode picks the pattern, and the control lines drive every other block. Hang the [ALU](https://digiwleea.wleeaf.dev/learn/alu/), registers, [program counter](https://digiwleea.wleeaf.dev/learn/counter/), [RAM](https://digiwleea.wleeaf.dev/learn/ram/), and [instruction register](https://digiwleea.wleeaf.dev/learn/instruction-register/) on the shared bus, wire the control lines to their enables, and you have a [datapath](https://digiwleea.wleeaf.dev/learn/datapath/) a control unit can run, which is a working [CPU](https://digiwleea.wleeaf.dev/learn/cpu/).

### FAQ

**Q:** What does a control unit do?

**A:** The control unit sequences **fetch-decode-execute**: each clock it raises the control lines that gate one value onto the shared bus and trigger the right register loads. A ring counter supplies the micro-steps `T0, T1, T2, ...`, and the current opcode selects which lines fire on each step.

**Q:** Why does one instruction take several clock cycles?

**A:** Because the shared bus can carry only **one value at a time**. Adding a memory value to the accumulator must, in order: drive the address and read [RAM](https://digiwleea.wleeaf.dev/learn/ram/), send that byte to the [ALU](https://digiwleea.wleeaf.dev/learn/alu/)'s `B` input, then load the result into the accumulator. Each is a separate micro-step using the bus differently, so the control unit walks a short fixed sequence.

**Q:** How does a control unit decode an opcode into control lines?

**A:** Decoding is **combinational**: a control line is raised when the right step is active **and** the opcode matches, so each line is just an [OR](https://digiwleea.wleeaf.dev/learn/or/) of [AND](https://digiwleea.wleeaf.dev/learn/and/)ed (step, opcode) conditions. For example `ACC.load = (T3 AND opcode==ADD) OR (T2 AND opcode==LOAD) OR ...`. The whole control unit is the control matrix turned into gate clusters, one per column.

**Q:** What is the cardinal rule of the control matrix?

**A:** In any single step, **at most one** `*.out` driver line may be `1`. Two drivers on the bus at once is a [tri-state](https://digiwleea.wleeaf.dev/learn/tristate/) short (`X`) that fights itself. Loads can safely overlap (many registers may sample the bus on one edge), but drivers cannot, so raising two `*.out` lines on the same step is the classic way a hand-built CPU corrupts its bus.
