Introduction: Why Connect SVA to Software?

Seeing an error message in a terminal is fine for a human, but a self-checking testbench needs to know programmatically when an assertion fails. By using the Direct Programming Interface (DPI), we can call a C++ function directly from an SVA “Action Block.”

The Action Block: The Trigger

Every assertion has two hidden slots called Action Blocks: the “pass” block and the “fail” block.

a_protocol_check: assert property (p_my_rule)
  // Success Action Block
  begin
      $display(Success!);
  end
// Failure Action Block
else begin
    $error(Failed!);
end

The DPI Bridge (Linking to C++/Python)

Instead of just printing a message, we can call a C function. This function can then update a scoreboard in C++ or raise an exception in Cocotb.

Step A: Declare the C function in SystemVerilog Inside your checker or a separate package, define the function you want to call.

// Import the C function into SystemVerilog
import DPI-C function void notify_assertion_failure(string name, int cycle);

Step B: Call it from the SVA Action Block

a_handshake: assert property (@(posedge clk) req |=> ack)
  else begin
      // Call the C function when the assertion fails
      notify_assertion_failure(REQ_ACK_FAIL, $time);
  end

Handling the Event in C++ (Verilator)

When Verilator compiles your code, it expects you to provide the implementation of notify_assertion_failure.

// In your C++ Testbench (sim_main.cpp)
extern C void notify_assertion_failure(const char* name, int cycle) {
  printf(C++ Alert: Assertion %s failed at time %d!\n, name, cycle);
  // You can also increment an error counter here
  my_testbench->error_count++;
}

Integration with Cocotb (Python)

Cocotb works by wrapping the simulator. When using Cocotb, you usually have two choices for SVA:

Passive Monitoring
Let SVA print to the console; Cocotb’s log-scrubber will see the “Error” message and fail the test automatically.
Active Signaling
Use a DPI function (as shown above) to toggle a “failure signal” in a helper module. Cocotb can “watch” this signal using await Edge(dut.assertion_fail_sig).

Conclusion: Your Verification Superpowers

You’ve now moved from writing simple code to building a cross-language verification framework.

SVA handles the complex timing logic.

DPI handles the communication.

C++/Python handles the test coordination and results.

This concludes the Foundations Series! You can find the example code here.