Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

32-Bit Custom CPU — COE608 Lab 6

A fully structural 32-bit CPU implemented in VHDL and synthesized for an Intel Cyclone IV E FPGA. The design uses a classic three-stage fetch–decode–execute datapath controlled by a finite-state machine, with a ripple-carry adder hierarchy built from first principles.

Architecture Overview

The CPU is composed of three top-level components instantiated inside cpu1:

  • Control_New — a 3-state Mealy FSM (T1/T2/T3) that decodes the instruction register and drives all register load/clear signals, MUX selects, ALU operation codes, and memory enables.
  • data_path — the full datapath: program counter, instruction register, two general-purpose registers (A and B), an ALU, an internal data memory, and a network of MUXes connecting them via a shared data bus.
  • reset_circuit — a power-on reset sequencer that holds the CPU in reset for one clock cycle and then asserts Enable_PD to start the control FSM.

Datapath Signal Flow

External System Memory
        │ dataIn[31:0]
        ▼
  ┌─────────────┐      data bus (32-bit)
  │  DATA_MUX   │◄──────────────────────────────────────┐
  │  (4-to-1)   │  sel: dataIn / data_mem / ALU / zero  │
  └──────┬──────┘                                       │
         │ data_bus_s                                   │
         ├──► IR (register32) ──► Control_New (INST)    │
         ├──► A_Mux ──► Reg_A ──► IM_MUX1 ──► ALU ─────┘
         └──► B_Mux ──► Reg_B ──► IM_MUX2 ──► ALU

PC ──► addrOut ──► External System Memory (address)

Example Simulation

The following waveforms were captured in ModelSim during functional verification:

Reset circuit — full state sequence: Reset waveform CPU FSM cycling through fetch → decode → execute → writeback states after reset

Reset circuit — zoomed timing: Reset waveform zoomed Detailed timing showing register writes and PC increment per instruction

Module Hierarchy

cpu1
├── reset_circuit
├── Control_New          (3-state FSM, no sub-modules)
└── data_path
    ├── IR               [register32]
    ├── PC0              [pc]
    │   ├── addd         [add]          — increments PC by 1
    │   ├── mux0         [mux2to1]      — selects branch target or PC+1
    │   └── reg32        [register32]
    ├── LZE_PC / LZE_A_Mux / LZE_B_Mux / LZE_IM_MUX2   [LZE]  — lower-16 zero-extend
    ├── UZE_IM_MUX1      [UZE]          — upper-16 zero-extend (for LUI)
    ├── RED_Data_Mem     [RED]          — extracts lower 8 bits as memory address
    ├── A_Mux0           [mux2to1]      — data bus vs. immediate operand for Reg A
    ├── B_Mux0           [mux2to1]      — data bus vs. immediate operand for Reg B
    ├── Reg_A            [register32]   — 32-bit accumulator A
    ├── Reg_B            [register32]   — 32-bit accumulator B
    ├── Reg_Mux0         [mux2to1]      — selects A or B for memory write
    ├── Data_Mem0        [data_mem]     — 256 × 32-bit synchronous RAM
    ├── IM_MUX1a         [mux2to1]      — ALU A-operand: Reg_A vs. immediate
    ├── IM_MUX2a         [mux4to1]      — ALU B-operand: Reg_B / immediate / 1 / 0
    ├── ALU0             [alu]          — 8-operation 32-bit ALU
    │   ├── add0         [adder32]      — addition path
    │   │   ├── stage0   [adder16]
    │   │   │   └── 4×  [adder4]       — 4-bit ripple-carry adder (leaf cell)
    │   │   └── stage1   [adder16]
    │   └── sub0         [adder32]      — subtraction path (NOT b + carry)
    └── DATA_MUX0        [mux4to1]      — selects result back onto data bus

Instruction Set

The CPU supports 26 instructions encoded in a 32-bit word. The top 4 bits form the primary opcode; a subset use an 8-bit extended opcode in bits [31:24].

Opcode Mnemonic Operation
0000 LDAI Load immediate into A (lower 16 bits of IR, zero-extended)
0001 LDBI Load immediate into B
0010 STA Store A to data memory at address in IR[7:0]
0011 STB Store B to data memory
0100 LUI Load upper immediate into A (IR[15:0] shifted to upper half)
0101 JUMP Unconditional branch (load PC from IR lower bits)
0110 BEQ Branch if zero flag set
1000 BNE Branch if zero flag clear
1001 LDA Load A from data memory
1010 LDB Load B from data memory
0111 0000 ADD A ← A + B
0111 0001 ADDI A ← A + immediate
0111 0010 SUB A ← A − B
0111 0011 INCA A ← A + 1
0111 0100 ROL A ← rotate A left by 1
0111 0101 CLRA Clear A
0111 0110 CLRB Clear B
0111 0111 CLRC Clear carry flag
0111 1000 CLRZ Clear zero flag
0111 1001 ANDI A ← A AND immediate
0111 1010 TSTZ Skip next instruction if Z=1
0111 1011 AND A ← A AND B
0111 1100 TSTC Skip next instruction if C=1
0111 1101 ORI A ← A OR immediate
0111 1110 DECA A ← A − 1
0111 1111 ROR A ← rotate A right by 1

ALU Operations

ALU_op Operation
000 AND
001 OR
010 ADD (via adder32)
100 Rotate Left (ROL)
101 Rotate Right (ROR)
110 Subtract (via adder32 with NOT b)

Key Ports

Port Dir Width Description
clk in 1 CPU clock
mem_clk in 1 Memory clock (falling-edge triggered data_mem)
rst in 1 Asynchronous reset
dataIn in 32 Instruction/data from external system memory
addrOut out 32 Program counter → memory address bus
dataOut out 32 Internal data bus output
dOutA / dOutB out 32 Register A / B debug outputs
dOutIR out 32 Instruction register debug output
dOutPC out 32 Program counter debug output
dOutC / dOutZ out 1 Carry / zero flag debug outputs
outT out 3 FSM state (one-hot: 001=T1, 010=T2, 100=T3)
wen_mem / en_mem out 1 Write-enable / enable for internal data memory

Files

File Description
cpu1.vhd Top-level entity — instantiates data_path, Control_New, reset_circuit
data_path.vhd Full datapath structural implementation
Control_New.vhd 3-state instruction decoder FSM
control.vhd Earlier version of the control unit (reference)
alu.vhd 8-operation ALU using adder32
adder32.vhd 32-bit ripple-carry adder (2× adder16)
adder16.vhd 16-bit adder (4× adder4)
adder4.vhd 4-bit ripple-carry adder (4× fulladd)
fulladd.vhd 1-bit full adder (leaf cell)
pc.vhd Program counter (register32 + add + mux2to1)
register32.vhd 32-bit D flip-flop register with synchronous load and clear
mux2to1.vhd 32-bit 2-to-1 MUX
mux4to1.vhd 32-bit 4-to-1 MUX
LZE.vhd Lower zero-extend: zeros & IR[15:0]
UZE.vhd Upper zero-extend: IR[15:0] & zeros
RED.vhd Reduce to 8 bits: IR[7:0]
data_mem.vhd 256 × 32-bit synchronous RAM
system_memory.vhd 64 × 32-bit Altera altsyncram (instruction memory)
add.vhd PC increment adder (+1)
cpu_test_sim.vhd Simulation testbench

How to Run

Prerequisites: Intel Quartus Prime Lite (≥ 21.1) + ModelSim-Intel FPGA Edition

1. Open `src/Lab6.qpf` in Quartus Prime
2. Compile: Processing → Start Compilation
3. Simulate: Launch ModelSim via Tools → Run Simulation Tool → RTL Simulation
4. Program board: Programmer → Add .sof file → Start
   (DE2-115 or compatible Cyclone IV E board)
Pin assignments are in the .qsf file.

Design Decisions & Tradeoffs

  • Multi-cycle FSM control (not pipelined) — a 3-state Mealy FSM (T1/T2/T3) drives all control signals; simpler hazard handling at the cost of throughput (one instruction per 3 cycles minimum).
  • Accumulator-style architecture with 32-bit registers A and B — limits instruction-level parallelism but maps cleanly to a small register file and straightforward ISA encoding.
  • Ripple-carry adder hierarchy — cascades 8 × 4-bit adders through 2 × 16-bit stages to reach 32 bits; convenient structural hierarchy but creates a long carry chain on the critical path, limiting Fmax.
  • Harvard-style separate instruction/data memorysystem_memory holds instructions (Altera altsyncram), data_mem holds data (256 × 32-bit synchronous RAM); eliminates structural hazards between fetch and memory-access stages.
  • Single-clock FSM simplifies hazard handling at the cost of throughput — no forwarding logic or stall detection is needed since each state completes one micro-operation before advancing.

Future Improvements

  • Replace the ripple-carry adder with a carry-lookahead adder to cut the critical path and raise Fmax.
  • Add a 5-stage pipeline (IF/ID/EX/MEM/WB) with operand forwarding and hazard detection to increase instruction throughput.
  • Implement a branch predictor (start with static predict-not-taken) to reduce branch penalty in the pipelined version.
  • Extend the ISA with multiply and divide instructions (currently absent from the 26-instruction set).
  • Add a cache hierarchy (L1 I-cache + D-cache) in front of main memory to reduce average memory access latency.

Skills Demonstrated

VHDL · ISA design · multi-cycle control FSM · datapath design · ripple-carry adder · Quartus Prime · ModelSim · structural hierarchy · Cyclone IV E FPGA

License

MIT License — see LICENSE for details.

About

32-bit multi-cycle CPU in VHDL with a custom 28-instruction ISA, full datapath, and FSM control unit. Intel Cyclone IV E (DE2-115).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages