Classic Five-Stage Pipeline
The classic five-stage pipeline is the canonical reference design for a pipelined Reduced Instruction Set Computer (RISC) CPU. An instruction flows through five stages, Instruction Fetch (IF), Instruction Decode (ID), Execute (EX), Memory Access (MEM), and Write Back (WB), with a pipeline register latching the in-flight state between each pair of stages so that, at steady state, five instructions are in different stages at once and one instruction completes every cycle. The design originated with the Stanford MIPS work and the Berkeley RISC work in the early 1980s and crystallized in the first commercial Microprocessor without Interlocked Pipelined Stages (MIPS) R2000 in 1986 (Wikipedia, MIPS R2000). It is the structure that David Patterson and John Hennessy use to teach pipelining in Computer Organization and Design, the MIT 6.004 Beta CPU uses to teach pipelining (MIT 6.004 Spring 2017, Chapter 15), and the structure that the project definitely-not-esp32 builds in RTL for its RV32IMC core.
1. Why This Pipeline, In One Paragraph
A single-cycle CPU has a clock period set by the longest instruction’s critical path. For a load, that path is “fetch the instruction from memory, read two operands from the register file, add them in the ALU to form an address, read data memory at that address, write the data into a destination register,” all in one cycle (MIT 6.004 Ch. 15). The clock has to be long enough for the slowest of those paths, so every instruction pays that worst-case cost even if it does less work. Pipelining splits that path into smaller stages, each fast enough that the clock can run roughly five times faster, and overlaps the work across instructions so that, in the absence of hazards, one instruction completes per cycle. The MIT 6.004 notes put the trade-off bluntly: ideal pipelining gives “instruction throughput of 1 per clock cycle” while the latency of any one instruction goes up because of the added pipeline-register delays (MIT 6.004 Ch. 15). You buy throughput by paying latency.
The number 5 is not arbitrary. It falls out of the RISC philosophy. RISC instruction sets keep three things uniform: instructions are fixed length, only loads and stores touch memory, and arithmetic and logic only operate on registers (Wikipedia, RISC). Those three uniformities map almost mechanically onto the five stages: one stage to fetch the fixed-size instruction word, one to decode it and read registers, one to do arithmetic in the ALU, one for the optional memory access, one to write the result back. A pipeline with these specific five stages is the smallest natural decomposition of a load-store RISC instruction.
2. Mental Model and the Pipeline Diagram
The mental model that most clearly captures pipelining is the space-time diagram: instructions on the vertical axis, time on the horizontal axis, each cell showing which stage that instruction is in at that cycle. In the steady state, the diagonal stripes of one stage-per-cycle per-instruction are exactly the parallelism the pipeline buys.
gantt title Pipeline space-time diagram, six independent instructions, steady-state fill dateFormat X axisFormat %s section i1 IF :a1, 0, 1 ID :a2, 1, 2 EX :a3, 2, 3 MEM :a4, 3, 4 WB :a5, 4, 5 section i2 IF :b1, 1, 2 ID :b2, 2, 3 EX :b3, 3, 4 MEM :b4, 4, 5 WB :b5, 5, 6 section i3 IF :c1, 2, 3 ID :c2, 3, 4 EX :c3, 4, 5 MEM :c4, 5, 6 WB :c5, 6, 7 section i4 IF :d1, 3, 4 ID :d2, 4, 5 EX :d3, 5, 6 MEM :d4, 6, 7 WB :d5, 7, 8 section i5 IF :e1, 4, 5 ID :e2, 5, 6 EX :e3, 6, 7 MEM :e4, 7, 8 WB :e5, 8, 9 section i6 IF :f1, 5, 6 ID :f2, 6, 7 EX :f3, 7, 8 MEM :f4, 8, 9 WB :f5, 9, 10
Space-time diagram of the canonical 5-stage pipeline running six dependence-free instructions. What it shows: instructions move one stage per cycle. The first instruction takes 5 cycles to complete (its latency); the second instruction completes one cycle later, not five (the throughput is 1 per cycle in steady state). The insight to take: the win from pipelining is the diagonal, not any single row. Hazards (covered in Pipeline Hazards) introduce gaps in this diagonal, called bubbles, and CPI (covered in Cycles Per Instruction) goes up directly with the number of bubbles.
The complementary mental model is the datapath view: a horizontal flow chart of the hardware, with the pipeline registers as latches between stages.
flowchart LR PC["PC"] --> IF["IF<br/>Instruction Fetch<br/>read I-mem"] IF --> IFID[("IF/ID")] IFID --> ID["ID<br/>Decode +<br/>read register file"] ID --> IDEX[("ID/EX")] IDEX --> EX["EX<br/>ALU computes<br/>result or address"] EX --> EXMEM[("EX/MEM")] EXMEM --> MEM["MEM<br/>read or write D-mem<br/>(loads/stores only)"] MEM --> MEMWB[("MEM/WB")] MEMWB --> WB["WB<br/>write result back<br/>to register file"] WB -.->|"x_d value"| ID
The 5-stage datapath. What it shows: five combinational stages separated by four pipeline registers (IF/ID, ID/EX, EX/MEM, MEM/WB). The program counter (PC) feeds IF; the dashed line marks the architectural register file as logically shared between WB (write port) and ID (read ports). The insight to take: every signal an instruction needs in later stages must be carried forward through the pipeline registers; the pipeline registers are not optional storage, they are the mechanism that lets the hardware “remember” each in-flight instruction’s identity, operands, and control bits.
3. Mechanical Walk-through, Stage by Stage
3.1 Instruction Fetch (IF)
IF is responsible for fetching the binary-encoded instruction at the address held in the program counter (MIT 6.004 Ch. 15). The Berkeley CS61C course notes for the RISC-V 5-stage pipeline give the corresponding sentence: IF “retrieves instructions from memory and increments the program counter” (CS61C Notes, Five-Stage Pipeline). The stage holds three pieces of hardware: the PC register, an adder that computes PC + 4 (the address of the next sequential 32-bit word), and the read port of the instruction memory (in a small embedded core, a single-port SRAM; in a larger core, a level-1 instruction cache).
A subtle but important detail: PC and the I-memory read both have to complete in one clock period, which means the I-memory has to be a synchronous, single-cycle-access port. On an FPGA this is naturally satisfied by a block RAM clocked by the same domain. On a more aggressive design where the I-cache cannot return data in one cycle, IF is itself split into IF1/IF2 stages, deepening the pipeline.
The IF/ID pipeline register at the end of the stage latches the fetched 32-bit instruction word and the PC of that instruction (the latter is needed for branch-target computation, exception reporting, and link-register writes for JAL/JALR).
3.2 Instruction Decode (ID)
ID does three things in parallel: it decodes the instruction’s opcode and immediate fields, it reads up to two source registers from the register file, and (in many designs) it computes the sign-extended immediate. The MIT 6.004 notes summarize this as “the 32-bit instruction is passed to the register file stage (RF) where the required register operands are read from the register file” (MIT 6.004 Ch. 15). The CS61C notes list the per-stage control signals decoded here as ImmSel (which immediate to select), plus the control bits that will travel forward to the EX, MEM, and WB stages (CS61C Notes, Five-Stage Pipeline).
The register-file design matters. A canonical 5-stage RISC pipeline expects a register file with two read ports (for the two source registers an R-type or branch needs) and one write port (used by the WB stage of an older instruction). A well-known structural hazard arises because the WB stage of one instruction and the ID stage of a later instruction try to use the register file in the same cycle. Wikipedia’s Classic RISC Pipeline article calls this out as “a subtle structural hazard … many implementations of memory cells will not operate correctly when read and written at the same time” and notes that the standard fix is to clock the file so that writes happen on the falling edge and reads on the rising edge, so the read in the second half of the cycle sees the write from the first half (Wikipedia, Classic RISC pipeline). This internal-bypass in the register file is also called “first-half write, second-half read.”
The ID/EX pipeline register at the end of the stage carries: the two register read values, the sign-extended immediate, the destination register index, and a bundle of control bits encoding “what should EX, MEM, and WB do with this instruction.”
3.3 Execute (EX)
EX runs the Arithmetic Logic Unit (ALU). For an R-type instruction, the ALU computes the result on the two register operands. For a load or store, the ALU computes the effective memory address (rs1 + imm). For a branch, the ALU compares the two operands; for JAL/JALR, EX computes the target address (Wikipedia, Classic RISC pipeline).
The EX stage is also where operand forwarding physically lands (see Operand Forwarding). The two inputs to the ALU are fed from multiplexers whose select inputs come from a small hazard-detection unit that compares the destination register of the in-flight instruction in EX/MEM and MEM/WB against the source registers of the instruction currently in ID/EX. The multiplexers let a result computed last cycle (now sitting in EX/MEM) be routed back as an input to the current ALU operation, before it has been written back to the register file. This is the heart of pipelining for register-register sequences.
The EX/MEM pipeline register carries the ALU result, the second register value (for stores, which need the data to write), the destination register index, and the surviving control bits.
3.4 Memory Access (MEM)
MEM accesses the data memory for loads and stores; for every other instruction, the stage is just a one-cycle pass-through. The split between separate instruction memory (in IF) and separate data memory (in MEM) is the textbook Harvard structural assumption of the 5-stage pipeline. Without it, IF and MEM would contend for a single memory port every cycle a load or store was in flight; the pipeline would stall on every load or store. CS61C says explicitly that “the branch outcome becomes known during the MEM stage” in their RISC-V variant, which is one design choice (others resolve branches in EX); the resolution stage determines the branch-misprediction penalty (CS61C Notes, Five-Stage Pipeline).
A load’s read latency matters here. If the D-memory takes one cycle to respond (true of FPGA block RAM, of a hit in an L1 D-cache), the loaded value is available at the end of MEM, captured into the MEM/WB pipeline register. That timing is exactly what creates the Load-Use Hazard one cycle later.
3.5 Write Back (WB)
WB writes the result (either an ALU output for an R-type, or a loaded value for a load) back into the destination register in the register file. From WB’s perspective, the instruction is now retired (architecturally committed): subsequent reads from that register will see the new value through the normal register-file read port.
4. Pipeline Registers in Detail
The four pipeline registers, IF/ID, ID/EX, EX/MEM, MEM/WB, are not separate concepts from the stages; they are part of the stage boundary, and they exist because at the end of every cycle every stage must commit its in-progress state somewhere so the next cycle can begin work on a new instruction without losing the old one. CS61C explicitly lists what each carries (CS61C Notes, Five-Stage Pipeline):
- IF/ID: PC of the fetched instruction, the 32-bit instruction word.
- ID/EX: register values read from the register file, the sign-extended immediate, the instruction bits needed for downstream decode (e.g., the destination register index), and control signals for EX, MEM, and WB.
- EX/MEM: the ALU result, the second register value (write data for stores), the destination register index, and control signals for MEM and WB.
- MEM/WB: the memory output (for loads), the ALU result, the destination register index, and control signals for WB.
The control bits propagate down the pipeline so that each stage knows what to do for the instruction currently occupying it, without having to redecode. The CMU 18-447 lecture frames it as “dependence is a property of the program; hazards are specific to the microarchitecture” (CMU 18-447 Lecture 8); the pipeline-register bookkeeping is what makes the microarchitecture express, and resolve, those hazards.
5. The Structural Assumptions
The 5-stage pipeline rests on a small set of structural assumptions that, if violated, force a structural hazard (see Pipeline Hazards):
- Separate instruction and data memory ports (Harvard organization at the L1 boundary, even if the larger system is von Neumann). Without this, IF cannot fire on a cycle when MEM is busy. This is why the textbook pipeline draws “I-mem” and “D-mem” as two boxes. Real CPUs typically achieve this with separate L1 instruction and data caches that go to a unified lower-level cache.
- Single-cycle register-file read and write. Two read ports and one write port, dual-edge clocking or an explicit internal bypass so that a WB writing register
x5in the first half of cycle n is visible to a read ofx5in the second half of cycle n (Wikipedia, Classic RISC pipeline). - Single-cycle ALU. The integer ALU completes in one cycle. Multiply and divide do not fit, so the M extension is typically handled by a separate multi-cycle functional unit that stalls the EX stage or runs in parallel and is checked for completion at WB.
- Single-cycle memory access. D-memory hits respond in one cycle. A miss to a slower memory must stall the pipeline through a cache-fill machine, which is the dominant source of stalls in any real system.
- In-order issue and in-order completion. Instructions enter IF in program order and leave WB in program order; there is no reordering. This is what makes hazard analysis tractable for the textbook design and what limits it relative to out-of-order processors.
If any of these assumptions does not hold, the design either has to be modified (split memory into a longer access stage, replicate functional units, introduce structural-hazard stalls) or the pipeline depth has to change.
6. Comparison with Shallower and Deeper Pipelines
The classic five stages are a sweet spot for simple in-order RISC cores. They are not universal.
Shallower pipelines. The ARM Cortex-M0 implements a 3-stage pipeline (Wikipedia, ARM Cortex-M0). The Cortex-M0+ goes further and uses a 2-stage pipeline, which the article notes “lowers the power usage and increases performance (higher average IPC due to branches taking one fewer cycle)” (Wikipedia, ARM Cortex-M0). Shallow pipelines win on three axes: each stage does more work but there are fewer pipeline-register flip-flops to clock (lower dynamic power), branch mispredict penalties are tiny (often one cycle, often zero), and interrupt latency is shorter. They lose on clock frequency, because each stage has more combinational logic.
The ESP32-C3, the reference comparison hardware for definitely-not-esp32, uses a 4-stage, in-order, scalar pipeline (Espressif, ESP32-C3 Technical Reference Manual, Ch. 1). The TRM is unusually explicit: “The core has 4-stage, in-order, scalar pipeline optimized for area, power and performance,” running RV32IMC at up to 160 MHz. The fourth stage plausibly merges the ID and EX work or the MEM and WB work, again trading frequency for area and power.
The TRM does not name the four stages. The only hint it drops is incidental: the debug chapter says that on a trap or a debug entry, “mepc is set to current PC (in decode stage)” and “dpc is set to current PC (in decode stage)” (TRM v1.4 §1.7), which confirms a distinct decode stage exists and that the architectural PC is captured there. Any statement about which of the classic five stages got merged is inference, not documentation.
Resolved 2026-08-08
The SiFive E2 attribution is unsourced — treat it as folklore, not fact. A full-text search of the ESP32-C3 Technical Reference Manual v1.4 (dated 2026-03-26 in its Revision History) returns zero occurrences of the string “SiFive”, as does ESP32-C3 Datasheet v2.4. TRM §1.1 names the core only “ESP-RISC-V CPU”, and §1.4.2 Registers 1.1-1.3 hardwire
mvendorid = 0x00000612,marchid = 0x80000001,mimpid = 0x00000001. Those IDs matter, because the privileged specification definesmvendoridas “the JEDEC manufacturer ID of the provider of the core” and reserves themarchidMSB for commercial architecture IDs “allocated by each commercial vendor independently”, noting that “commercial fabrications of open-source designs should (and might be required by the license to) retain the original architecture ID” (riscv-isa-manual,src/priv/machine.adoc, main branch). SiFive’s own registered vendor ID is0x489(Linuxarch/riscv/include/asm/vendorid_list.h) — the C3 does not report it. Espressif is signing the core as its own first commercial microarchitecture.The forum thread the claim rests on turns out to be a reader’s post, not an announcement. User
dkhayes117opened it on 2020-11-21 under the headline “SiFive E2 Series Cores in ESP32-C3!” while quoting nothing but Espressif’s own C3 feature bullets (four-stage pipeline, RV32IMC, 16 PMP regions) — the SiFive claim lives entirely in the title. The thread’s one attempt at evidence is reply #4, “Given it has an FPU, it must be the E24 core”, which is simply wrong: the C3’smisahardwiresF = D = 0, and SiFive’s own Jim Wilson corrects it two posts later (“the Espressif chips (ESP32-C*) apparently don’t”) (SiFive forums thread). Absence of evidence is the finding here: neither company has ever claimed the lineage, so the defensible description is “provenance undisclosed, and Espressif signs it as its own design” — not “SiFive E2 derivative”.
Deeper pipelines. At the other extreme, Intel’s Pentium 4 NetBurst architecture famously stretched the pipeline to 20 stages in Willamette/Northwood and 31 stages in Prescott (Wikipedia, Pentium 4). The motivation was clock frequency: each stage’s work becomes a smaller share of the period, so the period can shrink. The Wikipedia summary names exactly the trade-off that killed the approach: Intel “had not anticipated a rapid upward scaling of transistor power leakage” at small nodes, and so “cooling and clock scaling problems” forced a return to shorter pipelines in the Core microarchitecture (Wikipedia, Pentium 4). Branch mispredictions on a 31-stage pipeline cost roughly 31 cycles each, multiplying the importance of Branch Prediction dramatically. The general modern reference figure is that “modern pipelines have 10-20 cycle misprediction penalties, making accurate prediction critical for performance” (Wikipedia, Branch predictor).
The lesson is that pipeline depth is not “more is better.” It is a single-variable optimization, with frequency on one side and IPC, power, and design complexity on the other. Five stages, the original MIPS choice, remains the textbook reference precisely because it sits at the inflection point where the next stage of depth no longer pays for itself in a simple in-order core.
7. The Critical Path
The clock period of a pipelined CPU is set by the slowest stage’s combinational delay plus the pipeline-register setup time and clock-to-output delay. In a balanced 5-stage RISC pipeline, the contenders for “slowest stage” are typically:
- IF: I-memory access time. On an FPGA, block RAM is one cycle but tight; on an ASIC with an L1 I-cache, the cache SRAM access often becomes the critical path.
- EX: ALU latency, especially the carry-propagate adder. A 32-bit ripple-carry adder is too slow at modern clocks; carry-look-ahead or carry-select adders are used to bring the EX delay down.
- MEM: D-memory access, same considerations as IF.
The CMU 18-447 lecture notes the general principle that “not uniform suboperations” force you to “group or sub-divide steps into stages to minimize variance,” and that what’s left over is “internal fragmentation (some too-fast stages)” where a fast stage is idle for part of the cycle waiting for the slowest one to settle (CMU 18-447 Lecture 8). Perfect balance is impossible; the goal is to keep the worst stage from being much worse than the others.
For a small FPGA RV32 core, the EX-stage ALU often dominates because the FPGA’s logic-cell carry chains have non-trivial per-bit delay. Designers often pipeline the multiplier across multiple cycles to keep it off the EX critical path, and they sometimes split the shifter into a barrel-shifter circuit rather than letting it sit on the same path as the adder.
8. FPGA versus ASIC Implementation Trade-offs
Although the same 5-stage pipeline RTL can target either an FPGA or an ASIC, the trade-offs differ.
On an FPGA (the definitely-not-esp32 target is a Tang Nano 20K), the basic building blocks are 4- or 6-input lookup tables (LUTs), dedicated carry chains, and block RAMs. Block RAM is naturally suited to be the I-memory and D-memory; using two separate block RAMs trivially satisfies the Harvard assumption. Multipliers and divider blocks may be free (dedicated DSP slices) or expensive (built from LUTs), pushing the design either toward an early M-extension implementation or away from it. Clock frequencies are modest (50 to 200 MHz typical for hand-written RV32 cores on small FPGAs); the EX-stage ALU is usually fine in one cycle. Power and area cost the FPGA developer almost nothing, since the silicon is already paid for.
On an ASIC, the same RTL targets a standard-cell library. Memories are SRAM macros; the choice of one-port versus two-port versus dual-port memories and the cache organization become first-order design decisions. Multipliers can be aggressive (fast Booth-encoded trees) at the cost of area. The 5-stage pipeline depth becomes a frequency lever: at the same standard-cell library, going from 5 to 6 or 7 stages can buy 30 to 50 percent more frequency at the cost of an extra pipeline register’s flip-flops per stage and slightly worse branch-mispredict cost. The ESP32-C3 sits at the conservative end of this spectrum, four in-order stages at 160 MHz, optimized for area and power rather than peak performance (Espressif TRM).
9. Worked Example: Three Instructions Through the Pipeline
Consider this RISC-V sequence with no hazards (the destination of each instruction is not the source of any later instruction):
addi x5, x0, 10 # x5 = 10
addi x6, x0, 20 # x6 = 20
add x7, x5, x6 # x7 = x5 + x6 = 30 (NOTE: this DOES read x5 and x6)The third instruction does read x5 and x6, so the sequence is not quite hazard-free; the dependences are exactly the textbook RAW situation that motivates forwarding. With forwarding (see Operand Forwarding), the timing looks like:
Cycle: 1 2 3 4 5 6 7
addi x5...: IF ID EX MEM WB
addi x6...: IF ID EX MEM WB
add x7...: IF ID EX MEM WBAt cycle 5, the add x7, x5, x6 is in EX. Its source x5 was produced by addi x5 whose ALU result has been sitting in EX/MEM since end of cycle 3 and in MEM/WB since end of cycle 4; the MEM/WB forwarding path feeds x5 = 10 into the ALU input. Its source x6 was produced by addi x6 whose result is in EX/MEM at end of cycle 4 (the start of cycle 5); the EX/MEM-to-EX forwarding path feeds x6 = 20 into the other ALU input. The pipeline runs at one-instruction-per-cycle steady state. The CPI for this sequence is exactly 1.
If add x7 were instead lw x7, 0(x5) followed by a use of x7 one cycle later, the pipeline would hit a load-use hazard and would need a one-cycle bubble; see Load-Use Hazard for the full timing diagram and Cycles Per Instruction for what that does to the CPI.
10. See Also
- Pipeline Hazards: the three classes of hazard the 5-stage pipeline must resolve.
- Operand Forwarding: the bypass paths that let the 5-stage pipeline avoid stalling on most RAW dependences.
- Load-Use Hazard: the one RAW hazard forwarding cannot fix.
- Cycles Per Instruction: how to measure what the pipeline buys.
- Branch Prediction and Two-Bit Saturating Counter: the standard countermeasures for control hazards.
- RV32IMC and RISC-V Instruction Set Architecture: the ISA the definitely-not-esp32 core implements.
- ESP32-C3 and Tang Nano 20K: the reference comparison and FPGA target.
- Computer Architecture MOC: the parent map.