SystemVerilog Transactions, UVM and C: Correlation in a Functional Verification Environment
Transaction level modeling and transaction level debug have been in use for years in SystemVerilog and Verilog simulation and verification, but not as available in VHDL, perhaps not used in GLS simulation and C testbenches, and taking new forms in system level modeling. This paper re-introduces and refreshes transaction recording and debug and suggests how each abstraction level can be used productively with worked examples runnable by the reader.

-
Introduction
As designers build larger and larger chips, it becomes more and more important for verification engineers to think about verification at higher level abstractions. Transactions can be recorded from low level details like clock edges and bus transfers all the way up the abstraction tree to system level interactions and tracking behavioral models in C or other high-level languages. This is important because most of this kind of debug needs to correlate two things.
Perhaps two sets of transactions – one from the high level and one from the low level. Perhaps what needs correlated is the low-level signal changes with the top-level abstraction activity. Perhaps the entire abstraction tree must be correlated with itself – to understand who is causing what events and transactions.
The waveform window in a traditional functional design and verification debugger is ideal for this kind of correlation – time-based correlation. The signals and transactions occupy the same timeline and can be reasoned about in the wave window. New views can also be created. Often the actual timing of the transaction is not important, but rather whether a transaction completes before another – the relative position of starting and ending transactions.
This paper will review the various APIs and methods for transaction recording and demonstrate the concepts using an example. That example can be reused in reader code and is open source.
Transaction Recording Basics
A transaction recording interface is commonly available, including creating a transaction stream, beginning and ending a transaction, adding attributes, adding relationships and signal activity.
- $create_transaction_stream
- $begin_transaction
- $end_transaction
- $free_transaction
- $add_attribute
An example using such an interface is below. This example does nothing useful, except demonstrate using the API to model a channel with 4 out-of-order transactions in-flight at once.
module M(input clk); int stream; initial begin stream = $create_transaction_stream("stream", "kind"); end sub_channel s0(clk, 0, stream); sub_channel s1(clk, 1, stream); sub_channel s2(clk, 2, stream); sub_channel s3(clk, 3, stream); endmodule module sub_channel(input clk, input int inflight, int stream); always @(posedge clk) begin: LOOP ... begin req_rsp = REQ; tr = $begin_transaction(stream, $sformatf("tr%0d", tr_count)); $add_attribute(tr, req_rsp, "req_rsp"); $add_attribute(tr, addr, "addr"); payload = 0; $add_attribute(tr, payload, "payload"); $add_attribute(tr, id, "id"); $add_attribute(tr, l_serial_number, "serial_number"); #10; $end_transaction(tr); $free_transaction(tr); end ... begin req_rsp = RSP; tr = $begin_transaction(stream, $sformatf("tr%0d", tr_count)); $add_attribute(tr, req_rsp, "req_rsp"); $add_attribute(tr, addr, "addr"); payload = $random() % 1024; // Fetch the payload $add_attribute(tr, payload, "payload"); $add_attribute(tr, id, "id"); $add_attribute(tr, l_serial_number, "serial_number"); delay = 10; #delay; #10; $end_transaction(tr); $free_transaction(tr); end end endmodule
-
Download Paper
-
SystemVerilog Transactions, UVM and C: Correlation in a Functional Verification Environment
SystemVerilog Aug 20, 2025 pdf
-
-
Download Slides
-
SystemVerilog Transactions, UVM and C: Correlation in a Functional Verification Environment
SystemVerilog Aug 20, 2025 pdf
-