← Back to Course
# Processor Components ### CS 631 Systems Foundations — Apr 9, 2026 --- ## Today's Agenda 1. From counter to processor: state + combinational logic 2. Processor state and component block diagram 3. Single-cycle, multi-cycle, pipelined 4. Program counter & instruction memory 5. Register file interface and internals --- ## Recap: The 4-Bit Counter
flowchart LR REG["4-bit Register"] -->|"Q"| ADD["4-bit Adder"] ONE["1"] --> ADD ADD -->|"sum"| REG CLK["CLK"] --> REG CLR["CLR"] --> REG REG -->|"count"| OUT["count"]
- Register holds current count, adder computes next - Rising edge promotes next → current --- ## The Generalization Replace "register + adder" with **state + combinational logic** and you get the shape of every synchronous digital system:
flowchart LR CLK[CLK] --> STATE["STATE"] STATE --> CL["Combinational
Logic"] CL --> STATE
A processor is just a more elaborate instance of this picture. --- ## Processor State | State Element | Purpose | Size | |---------------|---------|------| | Registers `x0`–`x31` | GP registers | 32 × 64 bits | | PC | Instruction address | 64 bits | | Data memory | Stack/heap | Variable (RAM) | Everything else is combinational logic reading and feeding this state. --- ## One Instruction: `add t0, t1, t2` Two things happen in this cycle: 1. Read `t1`, `t2` → ALU → write sum to `t0` 2. `PC = PC + 4` to fetch the next instruction Both land on the **same rising edge**. Branches/jumps: `PC = BTA` instead of `PC + 4`. --- ## Processor Components
flowchart LR PC["PC
(S)"] -->|addr| IM["Inst Mem
(C, ROM)"] IM -->|IW| DEC["Decoder
(C)"] DEC --> RF["Reg File
(S)"] RF -->|"RD0,RD1"| ALU["ALU
(C)"] ALU --> DM["Data Mem
(S, RAM)"] DM --> RF
**S** = sequential (holds state). **C** = combinational (pure function). --- ## Component Roles | Component | Type | Function | |-----------|------|----------| | PC | S | Address of current instruction | | Inst Memory | C (ROM) | PC → 32-bit IW | | Decoder | C | Extracts fields + control | | Reg File | S | 32 GP registers | | ALU | C | Arithmetic / logic / shift | | Data Memory | S (RAM) | Load/store target | --- ## One Instruction per Cycle ``` init add sub beq ↓ ↓ ↓ ↓ CLK ────┐ ┌─────┐ ┌─────┐ ┌─────┐ ──── └────┘ └────┘ └────┘ └────┘ ``` - Between edges: values flow through combinational logic - On the edge: PC, register file, data memory all update --- ## Design Evolution | Design | Description | |--------|-------------| | **Single-cycle** | One instruction per clock cycle | | Multi-cycle | Variable cycles per instruction (1970s) | | Pipelined | Instructions overlap, one stage each | Modern CPUs add out-of-order, superscalar, speculative execution.
Single-cycle clock period =
longest combinational path
(typically load-word).
--- ## Program Counter 64-bit register holding the address of the current instruction. | Signal | Width | Description | |--------|-------|-------------| | D | 64 | Next PC value | | Q | 64 | Current PC value | | CLK | 1 | Clock | | EN | 1 | Enable (normally 1) | | CLR | 1 | Synchronous clear | Update rule: `PC_next = PC + 4`, or `PC_next = BTA` for branches/jumps. --- ## PC with Sync CLR MUX Digital's register has no CLR — add one with a MUX:
flowchart LR D[D] --> CM["CLR MUX"] --> FF["64-bit reg"] --> Q[Q] ZERO["0"] --> CM CLR[CLR] --> CM CLK[CLK] --> FF EN[EN] --> FF
`CLR = 1` → next rising edge loads 0 instead of D. --- ## Instruction Memory ROM with 32-bit data words, 8-bit address = 256 instructions. | Parameter | Value | |-----------|-------| | Data width | 32 bits (one RISC-V insn) | | Address width | 8 (typical) | | Type | ROM, loaded from `.hex` | Generated from assembly with `makerom3.py`. --- ## Byte Addr → Word Addr PC is byte-addressed; ROM is word-addressed. Each instruction is 4 bytes, so: ``` word_addr = byte_addr >> 2 ```
flowchart LR PC["PC (64)"] -->|"bits [9:2]"| SPL["splitter"] SPL -->|"8-bit"| ROM["ROM"] ROM -->|"32-bit IW"| OUT["instruction word"]
Bits 0–1 are always 0 for aligned instructions. `PC[9:2]` gives an 8-bit word address. --- ## Register File Interface
**Inputs** | Signal | Width | |--------|-------| | RR0 | 5 | | RR1 | 5 | | WR | 5 | | WD | 64 | | WE | 1 | | CLK | 1 | | CLR | 1 |
**Outputs** | Signal | Width | |--------|-------| | RD0 | 64 | | RD1 | 64 | | `x0`–`x31` | 64 each (debug) |
--- ## Two Reads + One Write per Cycle On every clock cycle, the register file supports: 1. **Up to two reads** — `RD0` (selected by `RR0`) and `RD1` (selected by `RR1`) 2. **At most one write** — register `WR` captures `WD` on the rising edge, only if `WE = 1`
Reads are
combinational
; the write is
synchronous
.
--- ## Register File Internals
flowchart LR X0["x0 = 0"] --> M0["32:1 MUX
RD0"] X1["x1"] --> M0 XN["... x31"] --> M0 X0 --> M1["32:1 MUX
RD1"] X1 --> M1 XN --> M1 RR0[RR0] --> M0 RR1[RR1] --> M1 WR[WR] --> DEC["5-to-32
decoder"] WE[WE] --> DEC DEC --> X1 DEC --> XN
--- ## x0 and the Write Decoder - **`x0` is hard-wired to 0** — no flip-flop, no storage - Writes with `WR = 0` go nowhere (no register to update) - The **5-to-32 decoder** + AND with `WE` enables exactly one register - On the next rising edge, that register captures `WD`
add x0, x5, x6
is a NOP — result is computed but never stored.
--- ## Coming Up (Tuesday) - **ALU**: add, sub, mul, sll, srl — combinational - **Instruction decoder**: extract opcode, `funct3`/`funct7`, register numbers, immediates; drive control lines - Connect everything: run a small program end-to-end --- ## Key Takeaways - Every digital system = **state + combinational logic + clock** - Processor state: **PC, register file, data memory** - **Single-cycle** design: one instruction per clock edge - PC uses a **sync-CLR MUX**; ROM is addressed by `PC[9:2]` - Register file: **2 combinational reads + 1 synchronous write**; `x0` hard-wired to 0