Panel For Example Panel For Example Panel For Example

Basic TLM Communication for Digital IC Verification

Author : Adrian September 11, 2025

UVM TLM

Overview

One key to improving verification productivity is thinking at the appropriate level of abstraction. UVM provides transaction-level communication interfaces for this purpose.

Transactions

In UVM, transactions model the information required for communication between two components (variables, constraints, etc.). Below is a simple bus-protocol transaction example:

class simple_trans extends uvm_transaction; rand data_t data; rand addr_t addr; rand enum {WRITE, READ} kind; constraint c1 { addr < 16'h2000; } ... endclass

After defining transactions, an interface that operates on those transactions must be provided.

TLM ports initiate transaction operations; TLM exports provide concrete implementations of those transaction methods.

Basic TLM Communication: put operation

The most basic transaction-level operation is one component putting a transaction to another component.

In the diagram, the square on the producer represents a port; the circle on the consumer represents an export.

class producer extends uvm_component; uvm_blocking_put_port #(simple_trans) put_port; // 1 parameter function new(string name, uvm_component parent); put_port = new("put_port", this); ... endfunction virtual task run(); simple_trans t; for (int i = 0; i < N; i++) begin // Generate t. put_port.put(t); end endtask endclass

The producer declares a uvm_blocking_put_port parameterized with simple_trans, then issues put operations inside its run() task.

class consumer extends uvm_component; uvm_blocking_put_imp #(simple_trans, consumer) put_export; // 2 parameters ... task put(simple_trans t); case (t.kind) READ: // Do read. WRITE: // Do write. endcase endtask endclass

The consumer declares a uvm_blocking_put_imp parameterized with simple_trans and specifying the implementing component. The put() method implementation resides in the consumer.

Basic TLM Communication: get operation

The get transaction-level operation is similar to put.

In the diagram, the square on the get_consumer represents a port; the circle on the get_producer represents an export.

class get_consumer extends uvm_component; uvm_blocking_get_port #(simple_trans) get_port; function new(string name, uvm_component parent); get_port = new("get_port", this); ... endfunction virtual task run(); simple_trans t; for (int i = 0; i < N; i++) begin // Generate t. get_port.get(t); end endtask endclass

The corresponding export implements the get operation:

class get_producer extends uvm_component; uvm_blocking_get_imp #(simple_trans, get_producer) get_export; ... task get(output simple_trans t); simple_trans tmp = new(); // Assign values to tmp. t = tmp; endtask endclass