SystemVerilog DPI-C: Calling C from SystemVerilog
The Direct Programming Interface (DPI-C) lets SystemVerilog call C/C++ functions and vice-versa. It is how testbenches reuse a C reference model, a cryptographic library, or a scoreboard written in software — without the overhead of the older PLI/VPI.
Importing a C function into SystemVerilog
You declare the C function with import "DPI-C" and call it like any SV function. The canonical form below imports a C crc8 reference and compares it against the RTL (this snippet needs a C toolchain at compile time, so it is shown for reference rather than run in the browser lab):
// ---- C side (crc.c) ----
#include <stdint.h>
unsigned char crc8_ref(unsigned char data) {
unsigned char crc = data;
for (int i = 0; i < 8; i++)
crc = (crc & 0x80) ? (crc << 1) ^ 0x07 : (crc << 1);
return crc;
}
// ---- SystemVerilog side ----
import "DPI-C" function byte unsigned crc8_ref(byte unsigned data); // call C from SV
export "DPI-C" function sv_log; // let C call SV
function void sv_log(int code); $display("C called back: %0d", code); endfunction
initial begin
byte unsigned d = 8'hA5;
$display("C reference CRC of %0h = %0h", d, crc8_ref(d)); // direct C call
endKey direction rules: import "DPI-C" brings a C function into SV; export "DPI-C" exposes an SV function to C. SV and C types map by a defined table (byte unsigned↔unsigned char, int↔int, arrays via open arrays). Compile with the C source alongside the SV (vcs ... crc.c, xrun ... crc.c, or Verilator with the C file).
The idea, provable in pure SystemVerilog
The value of DPI is a trusted golden model checked against the DUT. Here is that pattern expressed entirely in SystemVerilog (a function standing in for the C reference) so you can run it in the browser and see the scoreboard concept:
module tb;
// golden reference (in real projects this is the imported C via DPI-C)
function automatic byte unsigned crc8_golden(byte unsigned data);
byte unsigned crc = data;
for (int i = 0; i < 8; i++)
crc = crc[7] ? (crc << 1) ^ 8'h07 : (crc << 1);
return crc;
endfunction
// "DUT" under test (same algorithm here; a bug would surface as a mismatch)
function automatic byte unsigned crc8_dut(byte unsigned data);
byte unsigned crc = data;
for (int i = 0; i < 8; i++)
crc = crc[7] ? (crc << 1) ^ 8'h07 : (crc << 1);
return crc;
endfunction
initial begin
int errors = 0;
for (int v = 0; v < 256; v++) begin
byte unsigned exp = crc8_golden(v[7:0]);
byte unsigned got = crc8_dut(v[7:0]);
if (exp !== got) begin errors++; $display("MISMATCH v=%0h exp=%0h got=%0h", v, exp, got); end
end
$display("checked 256 vectors against golden model, errors=%0d", errors);
end
endmodulechecked 256 vectors against golden model, errors=0
Swap the golden function for an import "DPI-C" of a C model and you have the real DPI scoreboard — the C code becomes the reference of record while the RTL is the thing under test.
▶ Try it in the ChipXpert Lab
Run the 256-vector golden-vs-DUT check above in the cocotb verification lab. In cocotb the “golden model” is simply Python — the same reference-model idea DPI gives you in C.
Check yourself
What is the difference between <code>import</code> and <code>export</code> in DPI-C?
import "DPI-C" declares a C function that SystemVerilog can call. export "DPI-C" exposes a SystemVerilog function so that C code can call back into the simulation. A testbench often uses both to pass control between the two languages.
Why reach for DPI-C instead of writing the reference model in SystemVerilog?
To reuse an existing, trusted C/C++ model — a codec, crypto core, instruction-set simulator or floating-point library — as the golden reference, and to run heavy computation faster than interpreted SV. The RTL is then checked against that independent implementation.
Share your question in comments or talk to our mentor team for batch guidance.
Learn Verilog with mentors, labs and placement support
This free series is maintained by the ChipXpert training team in Hyderabad & Bengaluru. Go deeper with instructor-led courses on real EDA tools.
Explore VLSI Courses