5.2.4 · D5Processor Datapath & Pipelining

Question bank — Pipeline registers and control signals

1,939 words9 min readBack to topic

Before we start, three vocabulary anchors we lean on constantly.

Stage — one worker in the 5-worker assembly line: Fetch → Decode → Execute → Memory → Write-back (short: IF, ID, EX, MEM, WB).

Pipeline register — the tray (a bank of edge-triggered flip-flops — see Clocking and edge-triggered flip-flops) sitting between two workers, latching everything on the clock edge. "Latch" = "freeze the value now so the next worker reads it next cycle." There are exactly four, each named after the two stages it straddles:

Register Sits between Look at the picture
IF/ID Fetch → Decode the first tray
ID/EX Decode → Execute the second tray
EX/MEM Execute → Memory the third tray
MEM/WB Memory → Write-back the fourth tray

Control bundle — the control unit (in ID) produces many 1-bit "sticky notes" (RegWrite, MemRead, ALUSrc, …). We group them by which stage finally uses them, and call each group a bundle:

  • EX bundleALUSrc, ALUOp, RegDst (used in Execute)
  • MEM bundleMemRead, MemWrite, Branch (used in Memory)
  • WB bundleRegWrite, MemtoReg (used in Write-back)

The picture below shows all four trays, and how the three bundles are dropped off one by one as an instruction marches right. Refer back to it whenever a name below feels unfamiliar.

Figure — Pipeline registers and control signals

True or false — justify

Every pipeline register stores exactly the same set of fields.
False — each register carries only what later stages still need; e.g. MEM/WB no longer carries store data or the branch target because those were already consumed, so it is narrower than EX/MEM.
There is a pipeline register after the Write-back stage.
False — WB writes into the register file, which is already stateful storage, so an extra latch would only delay the write by a cycle and worsen hazards. Only four registers exist.
Control signals are generated independently in each stage from that stage's local logic.
False — only Decode sees the opcode, so all control signals are generated once in ID and then transported forward; later stages have no way to re-derive them.
The RegWrite signal is used in the same cycle it is generated.
False — it is generated in ID but only consumed in WB, three cycles later, so it must ride ID/EX → EX/MEM → MEM/WB before it does any work.
A pipeline register that carries a control signal drops that signal after the consuming stage.
True — the EX bundle is dropped after EX, the MEM bundle after MEM, so each successive register holds fewer control bits than the one before it.
The destination register number is only needed in the Decode stage where it is read from the instruction.
False — it is read in ID but used in WB to pick which register to write, so the 5-bit number must travel all the way through the registers or WB writes to the wrong place.
Widening a pipeline register with fields no later stage reads is harmless, just wasteful.
Roughly true on correctness but false on discipline — extra flip-flops burn area and power and signal a design misunderstanding; a register's width should equal the sum of fields a later stage physically needs, nothing more.
PC+4 can be discarded once the Fetch stage is done with it.
False — the branch target (defined just below) is computed in Execute, so PC+4 must survive through ID/EX to reach the EX adder.


Spot the error

"Stage 5 (WB) inspects the opcode to decide whether to write the register file."
The opcode is long gone by WB — the instruction word only lives in IF/ID. WB reads the latched RegWrite bit carried in MEM/WB instead.
"Since EX doesn't use RegWrite, we can safely drop it at EX/MEM."
Wrong — EX doesn't consume it, but WB (a later stage) still needs it, so EX must copy it forward unchanged into EX/MEM. Only signals whose consuming stage has passed may be dropped.
"The write-back writes to the register named in whatever instruction is currently in IF/ID."
In a pipeline five different instructions occupy the five stages; the IF/ID instruction was fetched four cycles after the one now in WB. WB must use the dest # that travelled with its own (older) instruction.
"We recompute the branch target in the Memory stage from the current instruction's immediate."
The immediate belongs to whichever instruction is in MEM now, not necessarily the branch. The target is computed in EX and latched into EX/MEM; MEM just reads the stored target.
"The EX/MEM register must carry the sign-extended immediate so MEM can use it."
MEM doesn't use the raw immediate — the immediate was already consumed by the ALU/branch adder in EX. What EX/MEM carries is the ALU result and branch target, the products of using that immediate.
"Because the pipeline has 5 stages, we need 5 pipeline registers for symmetry."
Registers sit between stages, so 5 stages have 4 gaps. The output of the last stage lands in the register file, not another tray.
"Control signals for the MEM stage should be generated in the MEM stage to keep them fresh."
MEM cannot see the opcode, so it has no way to generate them; they are decoded once in ID and carried in the MEM bundle through ID/EX → EX/MEM.

Why questions

Why can't we simply re-decode the opcode in every stage instead of carrying control signals?
Because after ID the opcode is no longer available — pipeline registers carry data and latched signals, not the full instruction word — so re-decoding is physically impossible past Decode.
Why are control signals split into EX, MEM, and WB bundles rather than kept as one lump?
Grouping by consuming stage lets each register drop a whole bundle the moment its stage finishes, minimizing width and making it obvious where each signal is used.
Why must every value a later stage needs be latched, even if the current stage ignores it?
The producing stage moves on to a new instruction next cycle and overwrites its combinational outputs; anything not latched is lost, so unused-but-needed values are copied through.
Why does forwarding (see Forwarding and stalling) read its operands from the pipeline registers rather than from the register file?
Because the correct newest value lives in EX/MEM or MEM/WB before it has been written back — the register file still holds the stale value, so forwarding taps the registers directly.
Why does the Zero flag from the ALU get latched into EX/MEM?
If the branch is resolved in the MEM stage, MEM needs the comparison outcome; the flag is produced in EX and would vanish when EX takes a new instruction, so it must be carried.
Why does putting control signals inside the pipeline registers automatically keep each instruction's paperwork with itself?
Each instruction occupies one slot in each register as it advances, so its signals march in lockstep with its data — no cross-talk between the five in-flight instructions.

Edge cases

For a nop (no-operation), what should the control bundles hold as they travel?
All state-changing signals — RegWrite, MemWrite — must be 0 so the nop writes nothing; the bits still ride the registers, they just carry a "do nothing" instruction.
When a hazard forces a stall, what is injected into the ID/EX control field?
A bubble — the control bundle is zeroed (RegWrite=0, MemWrite=0) so the stalled slot behaves like a nop and commits no state, while earlier stages hold their values (see Pipeline hazards).
When a branch is mispredicted, what must happen to the wrong-path instructions already in IF/ID and ID/EX?
They are flushed (squashed) — the pipeline registers holding them have their control bundles zeroed, turning those in-flight instructions into bubbles so their RegWrite/MemWrite never fire and no wrong-path state is committed (this is a control hazard, see Pipeline hazards).
Why does a flush zero the control fields but not bother clearing the data fields?
Because harmless data does nothing without an active write signal — if RegWrite=MemWrite=0, whatever garbage sits in the data fields is never written anywhere, so only the control bits must be squashed.
An R-type instruction has no memory access — does it still carry MEM-bundle signals?
Yes, it carries them but with MemRead=MemWrite=0; the fields exist for every instruction, and a non-memory op simply sets them inactive rather than omitting them.
A sw (store) writes no register — is its dest-reg # field still latched?
The 5-bit field still travels (the datapath is uniform), but its WB bundle sets RegWrite=0, so whatever number sits there is harmlessly ignored.
At the very first clock edges after reset, the pipeline registers hold undefined values — why is that safe only in a properly reset design?
It is safe only if the flip-flops holding the control bundles have a synchronous or asynchronous reset that forces RegWrite=MemWrite=0 at power-up; without such resettable flops the garbage control bits could trigger spurious writes, so real designs give the control registers an explicit reset even when the data fields have none.
If two instructions need the same physical pipeline register slot in the same cycle, what has gone wrong?
Nothing can — each register holds exactly one instruction's fields per cycle by construction; if a design ever demanded two, it means a stage was skipped or the clocking was mis-timed (see Clocking and edge-triggered flip-flops).

Connections