5-stage pipelined RISC-V processor in SystemVerilog. Implements the full RV32I base integer ISA with data forwarding, hazard detection, a branch predictor, and hardware performance counters.
Built this as a computer architecture project. Verified on ModelSim and EDA Playground.
Standard 5-stage pipeline: IF → ID → EX → MEM → WB
+-------------------------------------------------------------+
| RISC-V Core |
| |
+----+ | +----+ +----+ +----+ +----+ +----+ |
| PC |---+ IF |---+---->| ID |---+---->| EX |---+---->|MEM |---+>| WB |-+--> RegWrite
+----+ | +----+ | +----+ | +----+ | +----+ | +----+ |
^ | | | ^ | ^ | |
| | | | | +-------+-----+ |
| | | | | Forwarding |
+----+ | | | +-------------+ |
|BTB/| | | | |
|BHT |-+ v v |
+----+ | +----------------------+ |
| | Hazard Detection Unit| |
| +----------------------+ |
+-------------------------------------------------------------+
- IF: fetches instruction, queries BTB for branch target prediction
- ID: decodes opcode, reads register file, generates immediates
- EX: ALU ops, branch condition evaluation, forwarding mux selection
- MEM: load/store with byte/half/word access and sign extension
- WB: selects result (ALU / mem read / PC+4) and writes back to rd
16-entry BTB (direct-mapped) + 2-bit saturating counter BHT. Predicts taken/not-taken and caches branch targets. On misprediction, flushes IF/ID and ID/EX (2-cycle penalty).
EX-to-EX and MEM-to-EX forwarding paths. Eliminates most RAW hazard stalls — only load-use hazards need a 1-cycle bubble.
Catches load-use dependencies. Stalls PC and IF/ID for 1 cycle, inserts NOP bubble into ID/EX.
64-bit counters tracking: clock cycles, instructions retired, stall cycles, branch count, misprediction count.
| Type | Instructions |
|---|---|
| R-Type | ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND |
| I-Type | ADDI, SLTI, SLTIU, XORI, ORI, ANDI, SLLI, SRLI, SRAI, LB, LH, LW, LBU, LHU, JALR |
| S-Type | SB, SH, SW |
| B-Type | BEQ, BNE, BLT, BGE, BLTU, BGEU |
| U-Type | LUI, AUIPC |
| J-Type | JAL |
| System | EBREAK |
Tested on ModelSim and cross-verified on EDA Playground (Cadence Xcelium):
| Benchmark | Branches | Mispredictions | Accuracy | IPC | Cycles |
|---|---|---|---|---|---|
| Bubble Sort (32 elem) | 1,582 | 194 | 87.74% | 0.840 | 5,536 |
| Fibonacci (10x50 iter) | 1,031 | 13 | 98.74% | 0.990 | 3,116 |
| Nested Loop (16x16x8) | 4,913 | 276 | 94.38% | 0.945 | 10,116 |
| Linear Search (32x32) | 2,621 | 35 | 98.66% | 0.869 | 7,039 |
| Insertion Sort (32 elem) | 854 | 37 | 95.67% | 0.875 | 2,791 |
| Geometric Mean | — | — | 94.95% | — | — |
All sorting outputs verified against expected sorted arrays in memory. Branch prediction hits ~95% accuracy across 11k+ branches. IPC ranges from 0.84 to 0.99.
Quartus Prime, targeting Cyclone V (5CSEMA5F31C6):
- Fmax: 314.47 MHz
- Logic: 341 ALMs (<1.5% utilization)
- ALUTs: 159
- Registers: 191
- DSP blocks: 0
rtl/
defines.sv - opcodes, ALU ops, pipeline structs
if_stage.sv - instruction fetch + PC logic
id_stage.sv - decode, register file, immediate gen
ex_stage.sv - ALU + branch eval + forwarding muxes
mem_stage.sv - load/store + sign/zero extension
wb_stage.sv - writeback mux
pipeline_regs.sv - IF/ID, ID/EX, EX/MEM, MEM/WB registers
hazard_unit.sv - load-use detection, stall/flush control
forwarding_unit.sv - EX and MEM forwarding logic
branch_predictor.sv - 2-bit BHT + 16-entry BTB
perf_counters.sv - hardware performance counters
riscv_core.sv - top level module
mem/
instr_mem.sv - instruction memory (reads program.hex)
data_mem.sv - data memory (reads data.hex)
tb/
riscv_tb.sv - testbench
asm.py - simple python assembler
run_benchmarks.py - automated benchmark suite
program.hex - assembled program
data.hex - initial data memory
Automated benchmarks:
python run_benchmarks.py
Manual (ModelSim):
vlog -sv -suppress 2892 rtl/defines.sv rtl/*.sv mem/*.sv tb/riscv_tb.sv
vsim -c -do "run -all; quit" work.riscv_tb
- Patterson & Hennessy, Computer Organization and Design (RISC-V Edition), Morgan Kaufmann, 2017
- RISC-V ISA Manual, Volume I: Unprivileged ISA, v20191213