Back to projects

RISC-V processor in RTL

A 32-bit RV32I processor in Verilog, built one stage at a time. Fetch, decode, the register file, and the ALU with branch logic are implemented and checked against golden traces in Verilator. It doesn't run programs end to end yet: write-back and PC updates on branches and jumps are next.

RV32I datapath progressBuilt: a 32-bit program counter that resets to 0x01000000 and adds 4 each cycle, byte-addressable little-endian instruction memory, a combinational decoder with immediate generation, a 32 by 32-bit register file with two read ports and one write port, and a combinational ALU that also resolves branches, instrumented with 21 probes. Next: data memory and write-back.BUILT · FETCH TO ALUNEXT · WRITE-BACK+4PC32-bitreset0x01000000imemorybyte-addrlittle-endian1 MiBpcinsndecodeR I S B U Jimm gen5 layouts9 probesrs1rs2rdimmreg file32 x 32-bit2R · 1WALU+ branch6 conditionsdata memload/storewrite-backto rdbuilt: fetch · decode · reg file · ALUnext: write-back21 probes
Built so farFetch to ALU
Instruction setRV32I · 37
Register file32 × 32-bit
Fetch trace match400 / 400
Built so far

Fetch to ALU, in RTL.

Instruction memory

Byte-addressable, little-endian storage built from 8-bit elements. A 32-bit read assembles four bytes, and writes land on the rising clock edge. $readmemh loads the program as hex words and splits each word into four bytes. Capacity is configurable, 1 MiB by default in simulation.

Fetch

A 32-bit program counter resets synchronously to 0x01000000 and advances 4 bytes on every clock edge, streaming instruction words out of memory in order.

Decode

A combinational decoder extracts opcode, register, and function fields for all six RV32I formats (R, I, S, B, U, and J), covering the 37-instruction subset the core targets.

Immediate generation

Five immediate layouts, selected by opcode, reassembled from their scattered instruction bits, sign-extended, and padded to 32 bits.

Register file

32 registers of 32 bits with two combinational read ports and one write port on the rising clock edge. x0 ignores writes and always reads zero, and x2, the stack pointer, starts at the top of memory. Initialized in an initial block so it can map onto FPGA block RAM later.

ALU and branches

A fully combinational execute stage: arithmetic, logic, shifts, and signed and unsigned compares for register and immediate operands, load and store addresses, LUI and AUIPC, jump targets, and all six branch conditions with the branch target.

Immediate generation

Five layouts, one 32-bit value.

RISC-V scatters immediate bits across the instruction so the register fields stay in fixed positions. The decoder reverses that: the opcode picks the layout, the bit slices are copied into place, bit 31 is sign-extended, and the low bits are zero-filled where the format requires it.

RV32I immediate layoutsHow the decoder builds each 32-bit immediate from instruction bits. I and S copy instruction bit 31 into the upper 21 bits as the sign. B does the same for the upper 20 bits and forces bit 0 to zero. U copies instruction bits 31 to 12 and zero-fills the low 12 bits. J sign-extends the upper 12 bits and forces bit 0 to zero.FORMATimm[31]imm[0]Iaddi · lw · jalr31 · sign30:2524:2120Ssw · sh · sb31 · sign30:2511:87Bbeq · bne · blt31 · sign730:2511:80Ului · auipc31:120Jjal31 · sign19:122030:2524:210sign: copies of inst[31]zero fillinstruction bits copied

Each cell names the instruction bits it copies · all five share the sign at inst[31]

Verification

Checked against golden traces.

01

The register file passes the course's register file test.

02

Register reads, ALU results, and branch decisions match the golden traces in Verilator, alongside fetch and decode.

03

Instruction memory passed its tests, and the fetch trace matched a 400-line golden reference exactly.

04

Signal-level debugging in GTKWave waveforms, from the first memory tests onward.

05

21 probes across fetch, decode, the register file, and execute expose internal signals to the testbench.

06

The current build is reproducible from a single Git commit.

Roadmap

From fetch to FPGA.

01

Memory & fetch

Byte-addressable instruction memory and a 32-bit PC stepping through the program.

Done
02

Decode & immediates

Field extraction for six formats and five immediate layouts, integrated with fetch.

Done
03

Register file & ALU

Two-read, one-write register file and a combinational ALU that also resolves branches.

Done
04

Write-back & control flow

Data memory, write-back to rd, and PC updates on taken branches and jumps, so the core runs all 37 instructions.

Next
05

Five-stage pipeline

Pipeline registers, data forwarding, and hazard stalls to keep instructions moving correctly.

Planned
06

FPGA bring-up

Synthesize the pipelined core and bring it up on a PYNQ-Z1 board.

Planned
Next

Write-back comes next.

With write-back and PC updates in place, the core runs real programs and this page gets its first full execution traces.