RISC-V FPGA SoC w/ RTOS
May 2026

Building a RISC-V core from scratch sounds like a textbook exercise until you actually try to make the pipeline run real code without stalling on every other instruction. Hazards, forwarding, privileged behavior, and FPGA timing closure all have to land together, and any one of them being sloppy tanks the whole design. This RV32IM processor is a full from-scratch SystemVerilog implementation, brought up as a small SoC on a Zynq UltraScale+ FPGA for EECS 151 at Berkeley. The pipeline handles branches, loads, stores, full data forwarding, hazard-aware stall logic (including the multi-cycle divider), and privileged behavior via CSRs and traps (ecall/mret) so firmware can install real exception handlers. Our design merges Decode/Execute and Memory/Writeback into two stages, with a synchronous IMEM doubling as the IF-to-DEX register and loads bypassing straight to DMEM in DEX. That swap trades a long IMEM-to-ALU-to-DMEM critical path for one fewer pipeline stall. A separate CSR regfile feeds a dedicated CSR ALU in MEW with its own forwarding path to resolve back-to-back CSR hazards. The only stalls left are in-flight divides and the store-after-load structural hazard; the pipeline flushes on branches, jumps, mret, ecall, and timer interrupts. Around the core sit instruction and data memories, a BIOS boot path, and MMIO peripherals (most notably a UART), all wired through a top-level FPGA harness. Final numbers: 100 MHz, 1.14 CPI on mmult, 228.6 CoreMarks, 4.43% LUT / 1.74% SLICE / 30.79% BRAM / 3.33% DSP utilization, and a figure of merit of 7.64. Roughly 1500 lines of hand-written SystemVerilog and 100+ hours later, the core boots Zephyr RTOS. We also built a simplified Logisim version of the datapath that runs real RISC-V programs. Partner: Aditya Anantaraman