Visual walkthrough — Pipeline registers and control signals
We start from the single-cycle picture (see Single-cycle datapath) and slowly discover why boxes must appear between the stages, and what must go inside each box.
Step 1 — First, what is a "register"? A box that remembers on a tick
WHAT we did: we named the only building block we need. It has three things: input wires (left), output wires (right), and a clock tick (bottom).
WHY we need it: combinational logic (adders, ALUs, muxes) has no memory — its output changes the instant its input changes. If two instructions' values arrive at the same adder at overlapping times, they blur together. A register freezes a value so the next stage can read a stable snapshot. See Clocking and edge-triggered flip-flops for the tick itself.
PICTURE: the box below. The red wire is the value being captured; notice the output only steps to the new value at the black tick marks — it is flat in between.

Step 2 — Why a wall must sit between every pair of stages
WHAT we did: we drop a register (from Step 1) onto each gap between neighbouring stages.
WHY: without a wall, when EX finishes instruction A and starts instruction B, the half-cooked value of B immediately floods forward and overwrites A's value before MEM has read it. The wall latches A's output at the tick, so MEM reads A next cycle while EX freely chews on B.
WHY only 4 walls, not 5: there are 5 stages but only 4 gaps between them. There is no gap after WB — WB's output flows straight into the register file, which is itself a memory. Adding a 5th wall would just delay every write by one tick and make hazards worse (see Pipeline hazards).
PICTURE: five boxes (stages) in a row with four red walls in the gaps. Count them: the red walls are IF/ID, ID/EX, EX/MEM, MEM/WB.

Step 3 — What DATA must the EX/MEM wall carry? Follow the arrows out of EX
We now zoom into one wall — EX/MEM, the wall between Execute and Memory — and derive its contents from scratch. The rule is brutally simple:
Look at everything Execute computes and ask, for each: does anyone to the right still want this?
- The ALU result (32 bits): needed as the memory address for loads/stores, and as data to write back. → must cross.
- The store data (32 bits): for
sw, the value to be written to memory is read in ID and just rides through EX untouched, consumed in MEM. → must cross. - The branch target (32 bits): , computed by an adder in EX, used by MEM if the branch is taken. → must cross.
- The Zero flag (1 bit): the ALU's "was the result zero?" line, used in MEM to decide a branch. → must cross.
WHAT we did: listed the data fields that survive out of EX.
WHY each: every one is produced upstream of, and consumed downstream of, this wall. Drop any and the later stage silently reads garbage.
PICTURE: the four data arrows leaving EX, each labelled with its bit-width; the red arrow is the 32-bit ALU result, the star of the show.

Each symbol above is a wire count: "32" means a 32-bit-wide value physically occupies 32 flip-flops in the wall.
Step 4 — The sneaky one: the destination register number must ride too
WHAT we did: we add a 5-bit field — the destination register number — to the wall.
WHY 5 bits: MIPS has registers, so a register name is a 5-bit number.
WHY it must travel: if WB instead read "whichever register field happens to be on the current instruction's wires," it would write to the wrong register. This is the classic "used the current instruction's field instead of the pipelined one" datapath bug. The number is latched ID/EX → EX/MEM → MEM/WB, arriving in WB tagged to the correct, older instruction.
PICTURE: the 5-bit dest-# (red) threading through all three walls like a luggage tag, while the instruction word (grey) is discarded after ID.

Step 5 — Control signals: the paperwork that also crosses the wall
Every control signal is generated once, in ID, by the control unit reading the opcode (see Control unit design). But they are used at different times. The parent grouped them into three bundles by which stage consumes them:
| Bundle | Signals | Bits | Consumed in |
|---|---|---|---|
| EX | ALUSrc, ALUOp, RegDst |
3 | Execute |
| MEM | MemRead, MemWrite, Branch |
3 | Memory |
| WB | RegWrite, MemtoReg |
2 | Write-back |
WHAT we did: we found which bundles still need to cross the EX/MEM wall.
WHY only MEM + WB cross: by the time we reach the EX/MEM wall, EX has already consumed its own bundle — it's used up, so we drop it. Only the MEM bundle (used next) and the WB bundle (used two stages later) survive.
PICTURE: the three bundles entering ID/EX; the EX bundle (grey) falls off at EX, and the red MEM+WB bundles continue into EX/MEM.

Here means "number of wires in the MEM bundle" , and . That is the parent's 107. We built it wire by wire.
Step 6 — Every wall, every case: what each register carries and drops
WHAT we did: we generalise Step 5 to all four walls.
WHY it matters: this covers every case — no wall is left mysterious.
- IF/ID: carries the raw instruction word + PC+4. No control yet — the opcode hasn't been decoded.
- ID/EX: carries reg values, sign-extended immediate, PC+4, dest-#, and all three bundles (EX+MEM+WB).
- EX/MEM: carries ALU result, store data, branch target, Zero, dest-#, MEM+WB (EX dropped).
- MEM/WB: carries memory data, ALU result, dest-#, WB only (MEM dropped).
Degenerate/edge cases the survival rule handles automatically:
add(no memory access):MemRead=MemWrite=0still ride across EX/MEM — they're present but inactive. The wall doesn't know the instruction type; it just carries the bits.sw(no write-back):RegWrite=0rides all the way to WB and simply disables the write. The dest-# is still carried but ignored.beq(branch): the branch target and Zero flag are the whole point at MEM; for non-branch instructions those same wires carry harmless unused values.
PICTURE: the staircase — four walls, each shorter in its control column, bundles peeling off at their consuming stage.

The one-picture summary
Below: the full pipeline with all four red walls, the RegWrite signal traced as one bright red thread from ID (born) → ID/EX → EX/MEM → MEM/WB → WB (used), and each wall annotated with its bit width. The whole derivation, compressed.

Recall Feynman: the whole walkthrough in plain words
A register is a box that snaps a photo of its input at each clock tick and holds it steady. We put four such boxes between the five workers on our assembly line — four, because there are only four gaps (nothing after the last worker, since he hands the sandwich to the fridge, which already remembers). To decide what goes in one box, I ask a single question about every wire: does someone further down the line still need this? If yes, it crosses; if no, it's dropped. For the Execute→Memory box I found four data wires still needed (ALU answer, store data, branch target, the zero flag), plus a 5-bit luggage tag telling write-back which register to write, plus the two paperwork bundles still unread (MEM's and WB's). The Execute bundle got used up and thrown away. Add the widths: 32+32+32+1+5+3+2 = 107 bits. Every stage after does the same — eat your bundle, drop it, pass the rest — so each box is a little narrower than the last.
Connections
- Parent: Pipeline registers and control signals
- Single-cycle datapath — the register-free starting picture of Step 2
- Clocking and edge-triggered flip-flops — the "tick" that makes Step 1's box work
- Control unit design — where the Step 5 signals are born
- Forwarding and stalling — why carrying the dest-# (Step 4) also enables hazard fixes
- Pipeline hazards — the collisions these walls and staggered signals create