RV32I_GV 5-stage pipelined CPU in SystemVerilog. Learning project for HDL + RISC-V ISA. This code is written unfortunately by flesh slop but documentation and guidence for the flesh is done with Claude.
See docs.md for architecture and design details.
nix develop # enter the dev shell (pulls all tools automatically)rtl/
core/
adder.sv dff.sv mux2.sv bus_if.sv
alu.sv regfile.sv
if_stage.sv id_stage.sv ex_stage.sv
mem_stage.sv wb_stage.sv hazard_unit.sv
minori5_top.sv
tb/
phase0/
tb_adder.cpp (unit test — combinational adder)
tb_dff.cpp (unit test — D flip-flop)
lint the full CPU hierarchy:
verilator --lint-only -sv --top-module minori5_top \
rtl/minori5_top.sv \
rtl/core/if_stage.sv rtl/core/id_stage.sv rtl/core/ex_stage.sv \
rtl/core/mem_stage.sv rtl/core/wb_stage.sv rtl/core/hazard_unit.sv \
rtl/core/alu.sv rtl/core/regfile.svlint standalone primitives:
verilator --lint-only -sv rtl/core/adder.sv
verilator --lint-only -sv rtl/core/dff.sv
verilator --lint-only -sv rtl/core/mux2.svall commands run from the project root.
# combinational adder
verilator --cc -sv rtl/core/adder.sv \
--exe tb/phase0/tb_adder.cpp \
--build -Mdir tb/phase0/obj_dir_adder --top adder
./tb/phase0/obj_dir_adder/Vadder
# D flip-flop
verilator --cc -sv rtl/core/dff.sv \
--exe tb/phase0/tb_dff.cpp \
--build -Mdir tb/phase0/obj_dir_dff --top dff
./tb/phase0/obj_dir_dff/VdffCPU-level testbench not yet written (tb/tb_core.cpp is a future milestone).
Once written, the build will look like:
verilator --cc -sv \
rtl/minori5_top.sv \
rtl/core/if_stage.sv rtl/core/id_stage.sv rtl/core/ex_stage.sv \
rtl/core/mem_stage.sv rtl/core/wb_stage.sv rtl/core/hazard_unit.sv \
rtl/core/alu.sv rtl/core/regfile.sv \
--exe tb/tb_core.cpp \
--build -Mdir obj_dir --top minori5_top
./obj_dir/Vminori5_topthe top reads program.hex at startup via $readmemh — one 32-bit instruction per line in hex:
00500093 # addi x1, x0, 5
00300113 # addi x2, x0, 3
002081b3 # add x3, x1, x2
riscv32-none-elf-objcopy -O verilog produces this format from an ELF binary.
the dev shell provides the riscv-arch-test source at $RISCV_ARCH_TEST and the riscv32-none-elf-* cross toolchain. compliance testing requires the CPU testbench to be in place first.
manual compile of a single test:
TEST=$RISCV_ARCH_TEST/riscv-test-suite/rv32i_m/I/src/add-01.S
riscv32-none-elf-gcc \
-march=rv32i -mabi=ilp32 -static -nostdlib \
-T $RISCV_ARCH_TEST/riscv-test-suite/env/link.ld \
-I $RISCV_ARCH_TEST/riscv-test-suite/env \
$TEST -o add-01.elf
riscv32-none-elf-objcopy -O verilog add-01.elf program.hex
spike --isa=rv32i add-01.elf # golden referenceyosys -p "
read_verilog -sv rtl/minori5_top.sv rtl/core/*.sv;
synth -top minori5_top;
stat;
"add +define+DUMP_VCD to the verilator build and open with gtkwave:
gtkwave dump.vcd