Menu Close

PicoRV32 Tutorial : Practical + Beginner-Friendly

Posted in Risc-V

— here’s a clear, no-BS PicoRV32 tutorial to get you from “what is this” → “I can run it on FPGA / simulate it”.


🧠 PicoRV32 Tutorial (Practical + Beginner-Friendly)

🔗 0. Get the code

👉 Official repo:
https://github.com/YosysHQ/picorv32

Clone it:

git clone https://github.com/YosysHQ/picorv32.git
cd picorv32

🧩 1. What PicoRV32 actually is

👉 A tiny RISC-V CPU core in Verilog

  • File to focus on:
    picorv32.v
    

👉 It is:

  • multi-cycle CPU
  • FSM-controlled
  • not pipelined
  • not “textbook style”

🏗️ 2. Minimal System Architecture

PicoRV32 alone is just a CPU — you need to wrap it:

        +-------------+
        |  PicoRV32   |
        +-------------+
             | memory interface
             v
        +-------------+
        |   Memory    |
        +-------------+
             |
        +-------------+
        |   Program   |
        +-------------+

👉 Key idea:
CPU talks to memory via a simple interface (no AXI by default)


🔌 3. Understanding the Memory Interface (CRITICAL)

This is THE most important part.

Signals:

output        mem_valid
output        mem_instr
input         mem_ready

output [31:0] mem_addr
output [31:0] mem_wdata
output [3:0]  mem_wstrb

input  [31:0] mem_rdata

🧠 What it means:

Signal Meaning
mem_valid CPU requests memory access
mem_ready Memory responds
mem_addr Address
mem_wdata Data to write
mem_rdata Data read
mem_wstrb Write enable (byte mask)

🔁 Handshake logic:

👉 CPU says:

“I want data” → mem_valid = 1

👉 Memory replies:

“Here you go” → mem_ready = 1


⚙️ 4. Minimal Working Example (Simulation)

Here’s a super simple memory module:

reg [31:0] memory [0:1023];

always @(posedge clk) begin
    mem_ready <= 0;

    if (mem_valid && !mem_ready) begin
        mem_ready <= 1;

        if (mem_wstrb != 0) begin
            memory[mem_addr >> 2] <= mem_wdata;
        end else begin
            mem_rdata <= memory[mem_addr >> 2];
        end
    end
end

👉 This is enough to run PicoRV32.


🧪 5. Run the built-in test

Inside repo:

make test

👉 This runs:

  • simulation
  • test programs
  • verifies CPU works

🧠 6. How PicoRV32 Executes Instructions

Unlike your diagram (single-cycle):

👉 PicoRV32 does:

FETCH → DECODE → EXECUTE → MEMORY → WRITEBACK

But:

  • one stage at a time
  • controlled by FSM

⚡ 7. Key Parameters (very useful)

Inside picorv32.v:

parameter ENABLE_MUL = 1;
parameter ENABLE_DIV = 1;
parameter ENABLE_IRQ = 1;

👉 You can:

  • disable features → save area
  • enable features → more capability

🔧 8. Optional Interfaces

PCPI (co-processor interface)

👉 For custom instructions (AI / crypto etc.)

IRQ

👉 Interrupt support


🚀 9. Run on FPGA (high level)

Steps:

  1. Add:
    • PicoRV32
    • RAM
    • clock/reset
  2. Load program:
    • compiled .hex or .bin
  3. Connect:
    • memory interface

🧠 10. Mental Model (SUPER IMPORTANT)

👉 Think of PicoRV32 as:

A state machine that walks through instructions step by step

NOT:

  • ❌ parallel datapath
  • ❌ one-cycle execution

🔥 Common Beginner Mistakes

❌ Treating it like textbook CPU
❌ Ignoring mem_valid / mem_ready
❌ Expecting pipeline behavior
❌ Not aligning memory (addr >> 2)

Leave a Reply