1. Background & Motivation

Modern RISC-V SoC development often demands parallel hardware and firmware progress. Waiting for RTL completion or silicon fabrication delays firmware bring-up and can mask integration bugs until late in the project. Traditional RTL-only simulations, while accurate, are painfully slow for running substantial firmware workloads.

This project was built to bridge that gap. By combining a high-speed software Instruction Set Simulator (ISS) with a cycle-accurate RTL testbench, we can validate early firmware against evolving hardware models.

The design is tuned for RISC-V 64-bit systems and validated in QuestaSim. It targets scenarios where software must interact with memory-mapped peripherals in a realistic way, without requiring a full hardware prototype.

In short, this stack accelerates early-stage SW/HW co-verification in the pre-silicon stage by giving:

  • Firmware engineers realistic hardware responses
  • Hardware engineers realistic software traffic

2. Project Overview

This repository implements a SW/HW co-simulation environment for RISC-V that couples:

  • Unicorn Engine (RISC-V 64-bit ISS) for executing ELF binaries at near-native speed
  • SystemVerilog testbench (QuestaSim) for peripheral and bus-cycle simulation
  • DPI-C bridge layer connecting the ISS process with the HDL simulation process

The test environment supports:

  • Loading arbitrary RISC-V ELF binaries into the ISS memory space
  • Forwarding memory-mapped I/O (MMIO) accesses from the ISS to RTL peripherals
  • Synchronizing ISS instruction execution with RTL simulation time
  • Capturing and analyzing CPU-to-peripheral transactions

Unlike a purely virtual platform, this approach gives RTL-accurate behavior for selected hardware blocks while still executing real firmware at usable speeds.

3. Architecture & Module Design

The stack is organized so each layer has a clear role and can be evolved independently:

cosim arch

As shown in the architecture flow, the SystemVerilog testbench orchestrates the run while the Unicorn ISS loads firmware into RAM and executes it (advancing the PC, decoding/executing instructions, and trapping MMIO accesses). When firmware touches GPIO via MMIO, the ISS forwards the access parameters (addr, data, len) through DPI-C to the AXI-Lite driver.

The driver lowers these transaction-level fields into standard AXI-Lite handshakes and drives the GPIO RTL. When the transaction completes, the GPIO returns read data or a write response back along the same path to the ISS. This produces hardware-accurate MMIO behavior while keeping software execution fast.

Component responsibilities

1. Firmware Application

The sample firmware demonstrates the end-to-end path by performing simple MMIO operations:

  • Write 0xA5A5A5A5 and 0xB6B6B6B6 to a memory-mapped GPIO address
  • Read data back from the same memory-mapped GPIO address
  • Exit using an ebreak instruction

2. RISC-V Unicorn ISS Layer

  • Loads and executes firmware binaries (RISC-V 64-bit ELF)
  • Provides hooks for instruction execution and MMIO access trapping
  • Maintains its own simulated memory space, with GPIO address ranges marked as MMIO

3. DPI-C Bridge

  • Implements the glue between C-based ISS code and the SystemVerilog testbench
  • Uses import "DPI-C" functions to pass transactions, memory reads/writes, and interrupt events
  • Encapsulates ISS-to-RTL exchanges so the ISS code is not tightly coupled to HDL code

4. SystemVerilog Testbench in QuestaSim

  • Contains BFMs and signal-driving logic to emulate the memory system and peripherals
  • Implements clock/reset generation, transaction routing, and signal assertions
  • Captures simulation waveforms for debugging in QuestaSim GUI

5. Target Peripheral (RTL)

  • A simple GPIO module connected through AXI-Lite
  • Provides realistic read/write latency and responses
  • Enables functional verification of firmware/hardware interaction through the ISS layer

This modular design means the ISS can be replaced with another RISC-V model, and the peripheral set can be extended, without overhauling the whole simulation infrastructure.

4. Simulation Workflow

The simulation uses a coordinated step-by-step exchange between the testbench, ISS, DPI-C bridge, and RTL peripheral:

cosim workflow

A typical run looks like this:

  1. The SystemVerilog testbench sets the pace (clock/reset and simulation timeline).
  2. The Unicorn ISS loads firmware into RAM and begins executing instructions.
  3. When firmware performs a GPIO MMIO access, the ISS pauses and packages the request (address, data, length).
  4. The DPI-C bridge forwards the request to the AXI-Lite driver in the testbench.
  5. The AXI-Lite driver performs the handshake with the GPIO RTL.
  6. The GPIO RTL returns read data or a write response.
  7. The response flows back through the same path to the ISS.
  8. The ISS resumes execution and continues until the next MMIO interaction or program exit.

This back-and-forth ensures memory-mapped I/O in the firmware is exercised against real hardware logic, making the simulation both realistic and precise.

The following screenshot shows the simulation result when running with QuestaSim:

cosim result

Feel free to explore the repository, build the design, and tailor it to your needs. Detailed build and run instructions can live alongside the project with ready-to-use scripts.

5. Key Takeaways & Next Steps

This RISC-V-specific SW/HW co-simulation stack demonstrates that we can combine fast CPU emulation with cycle-accurate RTL simulation in a single DPI-based test environment with several practical benefits:

  • Early firmware bring-up without waiting for FPGA or silicon
  • Cycle-accurate hardware behavior for selected components
  • Modular structure where ISS, DPI layer, and peripherals are independently replaceable

Potential next steps:

  • Extend the ISS model to support privileged-mode features (for example, custom CSRs)
  • Add more peripherals and DMA engines to broaden test coverage
  • Implement timing models for more accurate cycle estimation

Closing Thoughts

A good co-simulation stack is not just a demo. It is an engineering multiplier. It lets firmware and hardware move in parallel, surfaces integration issues earlier, and gives teams a reusable validation path before FPGA bring-up or silicon.

If you want, I can also help turn this post into a more tutorial-style version next (with a concrete repo layout, DPI function signatures, and a minimal AXI-Lite transaction example).