RISC-V Processor Verification

Learn how to verify the open-standard RISC-V architecture. From checking simple ADD instructions to verifying complex pipelines and hazards.

Why RISC-V Verification?

RISC-V is an open-source Instruction Set Architecture (ISA) that is revolutionizing hardware design. However, the freedom to implement custom cores brings a massive verification challenge: How do we ensure our custom core actually obeys the RISC-V spec?

The Verification Challenge

Verifying a processor is different from verifying a peripheral (like SPI or I2C). You are not just checking signals;

  • Instruction Decoding: Does the core understand every legal opcode?
  • Execution: Does `ADD x1, x2, x3` actually put `x2 + x3` into `x1`?
  • Hazards: What happens if I use a register immediately after writing to it?
  • Privilege Modes: Do exceptions and interrupts work correctly?

Our Learning Path

Snippet: Validating an ALU Operation

A simple check in a Scoreboard might look like this:

// Simple check inside UVM Scoreboard
virtual function void check_alu(transaction tr);
    bit [31:0] expected;
    // Golden Reference Logic
    case (tr.opcode)
        ADD: expected = tr.rs1 + tr.rs2;
        SUB: expected = tr.rs1 - tr.rs2;
        AND: expected = tr.rs1 & tr.rs2;
        OR:  expected = tr.rs1 | tr.rs2;
    endcase
    // Comparison
    if (tr.rd_val !== expected) begin
        `uvm_error("ALU_FAIL", $sformatf("Op: %s, RS1: %0h, RS2: %0h | Exp: %0h, Act: %0h", 
            tr.opcode.name(), tr.rs1, tr.rs2, expected, tr.rd_val))
    end
endfunction