Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Small single-cycle RV32I-subset processor

This educational 32-bit RISC-V processor implements seven instructions from RV32I. It is not a complete or compliant RV32I CPU. The goal is a small, explainable datapath with reproducible functional verification.

Instruction Type Tested
ADD R Yes, unit and integration
SUB R Yes, unit and integration
ADDI I Yes, including negative immediate and x0
LW I Yes, store/reload and invalid alignment
SW S Yes, signed offset and store/reload
BEQ B Yes, taken and not taken
JAL J Yes, target, link, and x0 destination

Architecture

The 32-bit byte-addressed PC starts at 0. A behavioral instruction memory in the integration testbench reads build/integrated.hex asynchronously using PC[5:2]. The decoder accepts only the seven listed instruction forms and emits register write, memory write, ALU operand, ALU subtraction, writeback, branch, jump, and immediate-type controls. The immediate generator reconstructs and sign-extends I, S, B, and J formats. Two asynchronous register-file ports feed the ALU and branch equality comparison. The ALU adds for address calculation and all supported operations except SUB. A 64-word data memory has asynchronous reads and rising-edge writes. The writeback mux selects the ALU result, loaded word, or PC+4. The next-PC mux chooses PC+4, a taken BEQ target, a JAL target, or the current PC for an illegal instruction. See DATAPATH.md.

The PC, registers, and data memory update at the rising edge. Decode, register reads, arithmetic, data-memory reads, writeback, and next-PC selection are combinational. Synchronous active-high reset sets PC and all 32 registers to zero and clears all data words. Clearing the general registers and memory is a deterministic simulation choice, not an ISA requirement.

Memory and unsupported behavior

Addresses are byte addresses; both memories contain 32-bit words. The testbench instruction memory holds 16 words (64 bytes), loaded from a generated hex file. It is a simulation model, and its asynchronous read does not establish FPGA block-RAM compatibility. Data memory holds 64 words (256 bytes). LW/SW require 4-byte alignment and an address from 0 through 252; other word addresses assert illegal_instr, suppress state writes, and freeze PC. No byte or halfword access is implemented. Instructions outside the testbench's instruction-memory range yield an unsupported word. No fake HALT instruction exists: jal x0,0 is the completion loop.

Unsupported encodings assert illegal_instr, suppress register and memory writes, and freeze PC. There are no traps or exception handlers. Most RV32I instructions, interrupts, CSRs, multiplication/division, pipelining, caches, OS support, FPGA board integration, synthesis assessment, and timing closure are outside this project. Misaligned instruction targets are not given RISC-V exception behavior.

Run

Requires Python 3 and Icarus Verilog (iverilog, vvp). The Makefile includes Homebrew's /opt/homebrew/bin in PATH. Run from the repository root:

make test          # independent encoder/state check, unit test, integration test
make clean         # remove generated simulator products and waveform

make test-stage1, make unit, and make integration run the suites separately. make integration writes a per-instruction trace to stdout and waves/integration.trace.log, plus waves/integration.vcd. tools/encode_check.py contains independent encoders for R/I/S/B/J formats, an assembly-level expected-state calculation, and generates build/integrated.hex. The source assembly and generated words are listed in PROGRAM.md. The Python calculation supports verification; it is not an RTL simulator.

Observed evidence

On September 20, 2026, make test passed with Icarus Verilog: Stage 1 arithmetic tests passed., PASS unit: arithmetic x0 memory branches jump illegal alignment and PASS integration ... cycles=26. Expected and observed completion: PC=60 self-loop; x0=0, x1=5, x2=0xfffffffe, x3=3, x4=7, x5=7, x6=5, x7=52, x8=0, x10=16, and data memory byte address 12 contains 7. The trace confirms both BEQ outcomes and JAL target/link. Icarus emits informational warnings about always_comb constant-select sensitivity and unspecified RTL time units; simulation passes. These tests establish behavior for the exercised cases, not exhaustive instruction verification, synthesis, FPGA operation, or timing.

About

Educational single-cycle 32-bit RISC-V processor implementing a verified 7-instruction RV32I subset with datapath/control RTL and unit/integration tests.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages