Instruction Register and the Decode Stage
How a teaching CPU captures an instruction, extracts opcode, register, and immediate fields, and turns them into validated control signals—with RISC-V and x86 context.
TL;DR: In a simple CPU, an instruction register (IR) captures a fetched instruction so decode sees stable bits. Decode identifies the instruction format, extracts register and immediate fields, checks whether the encoding is legal, and generates control information for later stages. A modern processor may distribute that role across fetch buffers and pipeline registers rather than contain one literal architectural “IR.”
The program counter answers where to fetch. The decode stage answers what the fetched bits mean. Between them, a teaching CPU usually places an instruction register: a bank of flip-flops that preserves the current instruction while control logic examines it.
That model is useful, but it needs a boundary. The instruction register is not a programmer-visible register in most ISAs, and a high-performance implementation may hold many instructions at once in fetch blocks, queues, pipeline registers, or decoded-operation caches. “IR” names a role in the teaching datapath, not a universal physical component.
The Teaching Datapath
A small multicycle CPU can be drawn as:
PC → instruction memory → instruction register → field extraction → control
On an instruction-fetch event:
- the PC supplies an instruction address;
- instruction memory returns one instruction word;
- the IR captures that word on the active clock edge; and
- combinational decode logic interprets the stored bits.
The IR’s write enable is asserted only when a new instruction should be accepted. During a stall, the IR holds its old value. During a reset or pipeline flush, the controller either marks the stored instruction invalid or replaces it with a harmless operation.
Some multicycle datapaths place a memory data register between memory and the IR. Others capture the memory output directly. Neither sequence is universal; the timing and handshake of the chosen memory interface determine the registers required.
A Small Example Encoding
Suppose an eight-bit teaching ISA defines this format:
7 5 4 2 1 0
┌──────────────┬───────────────┬───────────────┐
│ opcode [2:0] │ register [2:0]│ mode / small │
│ │ │ immediate │
└──────────────┴───────────────┴───────────────┘
The exact fields are an ISA design choice. Eight bits cannot encode a large opcode space, two independent register operands, and a useful immediate simultaneously, so a real teaching ISA often uses several formats. For example:
- a register instruction may devote bits to source and destination addresses;
- a load-immediate instruction may use most low bits as a constant; and
- a branch instruction may interpret those same bits as an offset.
Decode must first establish the format, then interpret the remaining bits accordingly. Giving every bit one permanent label produces the wrong circuit.
Fixed-Position Fields: RISC-V Example
The base RISC-V ISA uses 32-bit instruction formats. For an R-type instruction:
31 25 24 20 19 15 14 12 11 7 6 0
┌────────────┬────────┬────────┬───────┬─────────┬──────────┐
│ funct7 │ rs2 │ rs1 │ funct3│ rd │ opcode │
└────────────┴────────┴────────┴───────┴─────────┴──────────┘
The register fields occupy consistent positions across the base formats:
opcode = IR[6:0]
rd = IR[11:7]
funct3 = IR[14:12]
rs1 = IR[19:15]
rs2 = IR[24:20]
funct7 = IR[31:25]
Those slices are wiring, not arithmetic. rs1 and rs2 feed the register file’s read addresses; rd identifies a possible destination; and the opcode plus function bits identify the operation class and variant.
Immediates require more care. In several RISC-V formats the immediate bits are deliberately split across the instruction. Hardware must concatenate them in the specified order and sign-extend from the architecturally defined sign bit. That remains simple combinational wiring, but it is not always one contiguous slice.
Decode Is More Than an Opcode Decoder
For a toy ISA with eight complete operations, a three-to-eight decoder can create one-hot signals:
| Opcode | Teaching operation | One-hot result |
|---|---|---|
000 | NOP | is_nop |
001 | LOAD | is_load |
010 | STORE | is_store |
011 | ADD | is_add |
100 | SUB | is_sub |
101 | JUMP | is_jump |
110 | BRANCH-Z | is_branch_z |
111 | HALT | is_halt |
Control equations can then be derived from those signals:
That is a useful introduction to decoders and sum-of-products logic, but it is not the general structure of a real decoder.
In a larger ISA:
- the primary opcode often selects a format or instruction family rather than one operation;
- secondary function fields distinguish members of the family;
- mode or prefix state can change operand size and interpretation;
- some bit patterns are reserved or illegal;
- privilege and extension availability can affect legality; and
- control outputs are usually encoded rather than one dedicated wire per instruction.
A correct decoder must reject unsupported encodings instead of accidentally treating them as a nearby legal instruction.
What Decode Produces
The output is better thought of as a control bundle than dozens of unrelated wires. A teaching bundle might contain:
| Field | Meaning |
|---|---|
alu_op | Select addition, subtraction, logical operation, comparison, or pass-through |
src_a / src_b | Choose register, PC, immediate, or constant operands |
reg_write | Permit a register-file write at the appropriate later stage |
mem_read / mem_write | Request a data-memory operation |
result_source | Choose ALU, memory, PC-relative value, or another write-back source |
branch_kind | Select no branch, conditional branch, direct jump, or indirect jump |
immediate | Reassembled and extended constant |
legal | Indicate whether the encoding is supported in the current machine state |
These signals must be qualified by pipeline validity and stage timing. A combinational reg_write = 1 at decode is not permission to update the register file immediately; the write occurs only when the instruction reaches the designated stage without being flushed or faulted.
Fixed and Variable Instruction Length
Instruction length changes the front of the decode problem.
Fixed-length example: Arm A64
Arm A64 instructions are 32 bits wide. Once fetch has supplied an aligned word, field positions can be examined directly. Fixed length simplifies instruction-boundary discovery, but it does not make every operation or immediate encoding trivial.
RISC-V with compressed instructions
Base RISC-V instructions are 32 bits. The optional compressed extension adds 16-bit instructions, and the architecture reserves a length-encoding scheme for longer encodings. Fetch must determine whether the next instruction occupies two, four, or another supported number of bytes before advancing the PC and aligning the next instruction.
Variable-length example: x86
x86 instructions range from one to 15 bytes and can contain legacy or modern prefix encodings, opcode bytes, ModR/M and SIB addressing bytes, displacement, and immediate data. Which parts are present depends on the preceding bytes.
A modern x86 front end therefore needs instruction-boundary and length decoding before or alongside semantic decoding. Implementations differ: it is unsafe to claim that every processor fetches one fixed block size, uses one queue layout, or translates every instruction through the same path. Intel’s architecture manuals define the software-visible encoding; the exact pipeline is microarchitecture-specific.
Fixed-length and variable-length are not synonyms for RISC and CISC. They describe one encoding property.
Hardwired and Sequenced Control
A small CPU can generate control directly from Boolean logic. A multicycle controller can instead use a state machine or a control store whose entries describe several internal steps. Real processors may combine fast decode paths with sequenced handling for more complex operations.
The useful distinction is:
- Combinational decode maps current fields to an initial control representation.
- Sequenced control emits multiple internal actions over time.
Neither method is automatically “RISC” or “CISC,” and a microcoded implementation is not inherently slow. Performance depends on the complete implementation and workload.
Pipeline Control: Stall, Flush, and Validity
Once several instructions overlap, the instruction bits are only part of the state. Each pipeline register also needs control metadata.
Stall
If the next stage cannot accept an instruction, the current fetch/decode register must hold its data or participate in a ready/valid handshake. Allowing the bits to advance while the validity state stalls loses alignment between instruction and control.
Flush
A mispredicted branch, exception, or reset can invalidate younger instructions. Clearing only the instruction bits is less robust than clearing a valid bit, because an all-zero encoding may itself be legal in some ISAs.
Dependency handling
Decode may identify source and destination registers for hazard checks. The response can be a stall, forwarding selection, register renaming, or another implementation-specific action. Field extraction provides the identifiers; later control decides what to do with them.
Common Design Errors
- Assuming memory always needs an MDR. Add registers from the actual memory timing and interface, not from a universal diagram.
- Changing the IR while its instruction is still active. Use a write enable or handshake so decode sees stable bits.
- Decoding only the primary opcode. Function fields, modes, extensions, and legality checks may be required.
- Concatenating immediate bits in numerical drawing order. Follow the ISA’s bit mapping exactly, then extend from the specified sign bit.
- Driving side effects directly from unqualified decode. Gate writes with pipeline validity, stage timing, and exception/flush state.
- Resetting to an arbitrary instruction pattern. Prefer a valid bit or controller reset state; do not assume all-zero bits mean NOP.
- Treating an educational waveform as physical timing proof. The model can show logical sequencing, not silicon setup/hold closure.
Build and Verify a Teaching Decoder
Open the Sequential Instruction Executor and identify:
- the instruction-storage element;
- the wires that form each field;
- the control outputs influenced by each field; and
- the point at which those outputs are allowed to change architectural state.
Then build a compact test table:
| Test class | What to vary | Expected result |
|---|---|---|
| Each legal opcode | Primary opcode bits | Correct operation family and side-effect enables |
| Function variants | Secondary fields | Correct ALU or addressing variant |
| Register addresses | rs / rd fields | Correct register ports, unchanged operation |
| Immediate extremes | Zero, maximum positive, most negative | Correct concatenation and extension |
| Reserved encoding | Unsupported bit pattern | Illegal-instruction path, no unintended write |
| Stall | Hold decode for several clocks | Instruction and control remain aligned |
| Flush | Invalidate an in-flight instruction | No register or memory side effect |
Manually toggling one example is an illustration, not sufficient verification. Cover every legal operation class and representative illegal encodings.
Where It Fits in the CPU
The program counter supplies the fetch address. Decode identifies operands and control intent. The CPU flags register is one possible source of branch conditions in flag-based ISAs; other ISAs compare registers directly. The control unit sequences the teaching datapath and qualifies side effects.
Together these elements explain the control flow of a small processor, but none of them alone is “the entire control plane.” Caches, prediction, exceptions, privilege, hazards, and pipeline state add further control in larger machines.
Primary References
- RISC-V unprivileged ISA specification library
- RISC-V base instruction formats
- Arm explanation of A64 fixed-width encoding
- Intel 64 and IA-32 Software Developer’s Manuals
Continue with the fetch–decode–execute deep dive, then modify one encoding in the teaching CPU and update the decoder, tests, and documentation together.



