The idea: one instruction per clock cycle

The picture is the complete single-cycle MIPS processor from Harris and Harris, Digital Design and Computer Architecture (Figure 7.11). It runs every instruction in exactly one clock cycle. During the cycle, values flow from the PC through the memories, the register file, the ALU and the muxes, and settle. At the rising clock edge the results are stored: the new PC, one register and one memory word. Then the next instruction starts.

Simplified single-cycle datapath with the lw path highlighted: PC to instruction memory, rs to the register file, RD1 and the sign-extended immediate into the ALU, the address into data memory, ReadData through the MemtoReg mux back to the register file; PC + 4 back to PC; the Control Unit sets RegWrite 1, ALUSrc 1, MemtoReg 1, MemWrite 0, RegDst 0, Branch 0
In one clock cycle lw flows from the PC through both memories, the register file and the ALU; the Control Unit only sets the muxes and write enables.

See also Embedded I/O: the same Address, WriteData and MemWrite signals reach I/O device registers through an address decoder (memory-mapped I/O).

See also Memory Arrays: how the register file's two read ports and one write port, and the SRAM and DRAM behind the instruction and data memories, are built from bit cells, wordlines and bitlines.

Press Step Instruction. The cycle is shown in 6 steps so you can follow it, but steps 1 to 5 all happen in the same cycle and change nothing: they are combinational logic settling. Only step 6, the clock edge, writes state (green). Red wires carry a value the instruction uses; faded wires are not used. Blue lines are control signals from the Control Unit; they turn red when asserted (1).

State elements and combinational logic

PartKindWhat it does here
PCstate (register, has CLK)address of the current instruction; loads PC' at the clock edge
Instruction Memoryread only, combinational readRD = Mem[A]: Instr
Register Filestate (CLK, WE3)reads RD1 = reg[A1], RD2 = reg[A2] at any time; writes reg[A3] ← WD3 at the edge if WE3 (RegWrite) is 1
Data Memorystate (CLK, WE)reads ReadData = Mem[A]; writes Mem[A] ← WD at the edge if WE (MemWrite) is 1
ALU, two adders, Sign Extend, <<2, 4 muxes, Control Unit, AND gatecombinationalcompute SrcA op SrcB, PC + 4, the branch target, and steer values

The muxes, adders and the ALU are built from gates in Combinational Logic; the registers are edge-triggered flip-flops from Sequential Logic.

How the ALU's adder can be made fast (carry-lookahead and prefix adders), how it subtracts and compares, and how shifts and multiplies are built: Arithmetic Circuits.

The Control Unit: two small truth tables

The Control Unit reads only two fields of the instruction: Op (bits 31:26) and Funct (bits 5:0). The main decoder turns Op into the control lines; the ALU decoder turns ALUOp and Funct into the 3-bit ALUControl. Both tables are drawn on the canvas; the active row is highlighted.

InstructionOpRegWriteRegDstALUSrcBranchMemWriteMemtoRegALUOp
R-type00000011000010
lw10001110100100
sw1010110X101X00
beq0001000X010X01
addi00100010100000

Each line steers one part of the datapath:

  • RegWrite: write enable of the register file (WE3).
  • RegDst: which field names the destination register, rt (bits 20:16, I-type) or rd (bits 15:11, R-type). Its output is WriteReg.
  • ALUSrc: the second ALU input SrcB is RD2 (a register) or SignImm (the constant).
  • Branch and the ALU's Zero flag give PCSrc = Branch AND Zero: the next PC is PCPlus4 or PCBranch.
  • MemWrite: write enable of the data memory (WE).
  • MemtoReg: the value written back, Result, is ALUResult or ReadData from memory.
  • ALUOp: 00 add (addresses, addi), 01 subtract (beq compares), 10 "look at Funct" (R-type).

X means don't care: sw and beq write no register, so it does not matter what RegDst and MemtoReg select. A hardware designer picks whatever makes the logic smallest; the page fades those lines.

ALUOpFunctALUControl
00X010 (add)
X1X110 (subtract)
1X100000 (add)010 (add)
1X100010 (sub)110 (subtract)
1X100100 (and)000 (and)
1X100101 (or)001 (or)
1X101010 (slt)111 (set less than)

One instruction of each kind

InstructionPath through the datapathAt the clock edge
R-type add $t0, $s0, $s1RD1, RD2 → ALU (ALUSrc 0); ALUResult → Result (MemtoReg 0); WriteReg = rd (RegDst 1)$t0 ← Result, PC ← PC + 4
lw $t1, 0x100($0)RD1 + SignImm → ALU = address; ReadData → Result (MemtoReg 1); WriteReg = rt$t1 ← Mem[address]
sw $t0, 0x100($0)RD1 + SignImm = address; RD2 → WDMem[address] ← $t0 (MemWrite 1)
beq $t2, $0, skipRD1 − RD2 in the ALU, Zero; PCPlus4 + (SignImm << 2) in the branch adderPC ← PCBranch if Zero, else PC + 4
addi $s0, $0, 5RD1 + SignImm; ALUResult → Result; WriteReg = rt$s0 ← 5

Every instruction reads two registers and sign-extends the low 16 bits, whether it needs them or not: the hardware does it in parallel with decoding, so it costs no time. The branch offset counts instructions after the next one, so the target is PCPlus4 + (SignImm << 2): shifting left by 2 multiplies by 4 bytes per instruction. The Instr fields bar under the canvas splits each fetched word into its fields, for example lw $t1, 0x100($0) is 0x8C090100: op 35, rs 0, rt 9, imm 0x100.

The programs

  • One of each (Demo): addi, add, sw, lw, sub, a beq that is taken and skips an instruction, one that is not taken, and slt. 9 instructions in 9 cycles; mem[0x100] = 17, $s3 = 1.
  • Array sum: sums 5, 7 and 9. Figure 7.11 has no jump, so the loop goes back with beq $0, $0, loop, which is always taken. 23 instructions in 23 cycles; mem[0x10C] = 21.
  • Max of two: slt and beq choose the larger of 12 and 30; mem[0x108] = 30.
  • Or type an instruction (or pick a sample) and press Execute Instruction: it is written into instruction memory at the current PC and run. Try add $0, $s0, $s1: RegWrite is 1, but $0 stays 0.

Why one cycle is slow

CPI is exactly 1, but the clock period must be long enough for the slowest instruction to settle. That is lw: PC clock-to-Q, instruction memory read, register file read, sign extend and mux, ALU, data memory read, the MemtoReg mux, and the register file setup time:

Tc = tpcq_PC + tmem + max(tRFread, tsext + tmux) + tALU + tmem + tmux + tRFsetup

With the book's example delays (memory 250 ps, ALU 200 ps, register file read 150 ps, ...), Tc is about 925 ps, even though an add or a beq would be done much sooner. It also needs two memories, an extra adder for the branch target, and an ALU that is idle while memory is read.

Timeline of one lw cycle to scale: PC clock-to-Q 30 ps, instruction memory 250, register read 150, ALU 200, data memory 250, mux 25 and setup 20, 925 ps between clock edges; an add does not use the data memory but still waits for the same edge
The clock period is set by lw, the slowest instruction; faster instructions finish early and wait.
DesignCycles per instructionClock periodPage
Single-cycle1long: the slowest instruction (lw)this page
Multicycle3 to 5short: one step (one memory access or one ALU operation)How a Program Runs on the MIPS Datapath
Pipelinedabout 1 (plus stalls)short: one stageThe MIPS Pipeline: Hazards and Forwarding

What the page leaves out

  • j (jump): Figure 7.11 has no jump path. The book adds one with a third input to the PC mux and a Jump control line.
  • Other instructions (ori needs a zero-extender, shifts need shamt), exceptions, and overflow traps on add.
  • Only 8 of the 32 registers are shown and accepted, 11 words of instruction memory from address 0 and 8 words of data memory at 0x100–0x11C. Real MIPS starts code at 0x00400000.
  • Timing: wires settle instantly here. The steps 1 to 5 are one moment split up for explanation, not real time.