Tutorials

Learn More

TLM analysis port

  1. The uvm_analysis_port is a TLM-based class that provides a write method for communication. TLM analysis port broadcasts transactions to one or multiple components.
  2. uvm_analysis_port can be open without any implementation of uvm_analysis_imp or uvm_analysis_export.
  3. Single uvm_analysis_port can have a connection with uvm_analysis_imp or uvm_analysis_export. No errors will be reported. 
  4. Multiple uvm_analysis_port can be connected to a single uvm_analysis_imp or uvm_analysis_export.
  5. uvm_subscriber already has analysis_export so that it can directly receive transactions from the connected analysis port. Generally, it is useful to write a coverage collector that attaches to the monitor.
  6. Valid Connections:
    a. port to port
    b. port to export
    c. port to imp
    d. export to export
    e. export to imp
analysis_port_symbol

Analysis Ports Declaration:

uvm_analysis_port #(<trans_item>) analysis_port;
uvm_analysis_imp #(<trans_item>, <receiver_component>) analysis_imp;
uvm_analysis_export #(<trans_item>) analysis_export;

tlm_analysis_port example

TLM analysis port

seq_item.sv

class seq_item extends uvm_sequence_item;
  rand bit [3:0] value;
  `uvm_object_utils(seq_item)
  
  function new(string name = "seq_item");
    super.new(name);
  endfunction
  
  constraint val_c {value > 0;}
endclass
`include "uvm_macros.svh"
import uvm_pkg::*;

`include "seq_item.sv"

class producer extends uvm_component;
  seq_item req;
  uvm_analysis_port #(seq_item) a_put;
  
  `uvm_component_utils(producer)
  
  function new(string name = "producer", uvm_component parent = null);
    super.new(name, parent);
    a_put = new("a_put", this);
  endfunction
  
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    
    req = seq_item::type_id::create("req");
    assert(req.randomize());
    `uvm_info(get_type_name(), $sformatf("Send value = %0h", req.value), UVM_NONE);
    a_put.write(req);
  endtask
endclass

class consumer_A extends uvm_component;
  seq_item req;
  uvm_analysis_imp #(seq_item, consumer_A) analysis_imp_A;
  
  `uvm_component_utils(consumer_A)
  
  function new(string name = "consumer_A", uvm_component parent = null);
    super.new(name, parent);
    analysis_imp_A = new("analysis_imp_A", this);
  endfunction
  
  virtual function void write(seq_item req);
    `uvm_info(get_type_name(), $sformatf("Received value = %0h", req.value), UVM_NONE);
  endfunction
endclass

class consumer_B extends uvm_component;
  seq_item req;
  uvm_analysis_imp #(seq_item, consumer_B) analysis_imp_B;
  
  `uvm_component_utils(consumer_B)
  
  function new(string name = "consumer_B", uvm_component parent = null);
    super.new(name, parent);
    analysis_imp_B = new("analysis_imp_B", this);
  endfunction
  
  virtual function void write(seq_item req);
    `uvm_info(get_type_name(), $sformatf("Received value = %0h", req.value), UVM_NONE);
  endfunction
endclass

class consumer_C extends uvm_subscriber #(seq_item);
  seq_item req;
  `uvm_component_utils(consumer_C)
  
  function new(string name = "consumer_C", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  virtual function void write (seq_item t);
    req = t;
    `uvm_info(get_type_name(), $sformatf("Received value = %0h", req.value), UVM_NONE);
  endfunction
endclass

class env extends uvm_env;
  producer pro;
  consumer_A con_A;
  consumer_B con_B;
  consumer_C con_C;
  `uvm_component_utils(env)
  
  function new(string name = "env", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    pro = producer::type_id::create("pro", this);
    con_A = consumer_A::type_id::create("con_A", this);
    con_B = consumer_B::type_id::create("con_B", this);
    con_C = consumer_C::type_id::create("con_C", this);
  endfunction
  
  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    pro.a_put.connect(con_A.analysis_imp_A);
    pro.a_put.connect(con_B.analysis_imp_B);
    pro.a_put.connect(con_C.analysis_export);
  endfunction
endclass
              
class test extends uvm_test;
  env env_o;
  `uvm_component_utils(test)
  
  function new(string name = "test", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    env_o = env::type_id::create("env_o", this);
  endfunction
 
  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    #50;
    phase.drop_objection(this);
  endtask
endclass

module tb_top;
  initial begin
    run_test("test");
  end
endmodule

Output:

UVM_INFO testbench.sv(22) @ 0: uvm_test_top.env_o.pro [producer] Send value = 6
UVM_INFO testbench.sv(39) @ 0: uvm_test_top.env_o.con_A [consumer_A] Received value = 6
UVM_INFO testbench.sv(55) @ 0: uvm_test_top.env_o.con_B [consumer_B] Received value = 6
UVM_INFO testbench.sv(69) @ 0: uvm_test_top.env_o.con_C [consumer_C] Received value = 6

TLM analysis Export

  1. Exports lower level uvm_analysis_imp to a higher component in hierarchy.
  2. Lower level component implementation details will be hidden which ultimately enhances the modularity of the verification environment.
  3. This enables the reuse and changing of particular child components.

TLM analysis Export Example

In the below example, the consumer component is considered a child component. Consumer wrapper is a component at a higher hierarchical level.

TLM analysis export
`include "uvm_macros.svh"
import uvm_pkg::*;

`include "seq_item.sv"

class producer extends uvm_component;
  seq_item req;
  uvm_analysis_port #(seq_item) a_put;
  
  `uvm_component_utils(producer)
  
  function new(string name = "producer", uvm_component parent = null);
    super.new(name, parent);
    a_put = new("a_put", this);
  endfunction
  
  task run_phase(uvm_phase phase);
    super.run_phase(phase);
    
    req = seq_item::type_id::create("req");
    assert(req.randomize());
    `uvm_info(get_type_name(), $sformatf("Send value = %0h", req.value), UVM_NONE);
    a_put.write(req);
  endtask
endclass

class consumer extends uvm_component;
  seq_item req;
  uvm_analysis_imp #(seq_item, consumer) a_imp;
  
  `uvm_component_utils(consumer)
  
  function new(string name = "consumer", uvm_component parent = null);
    super.new(name, parent);
    a_imp = new("a_imp", this);
  endfunction
  
  virtual function void write(seq_item req);
    `uvm_info(get_type_name(), $sformatf("Received value = %0h", req.value), UVM_NONE);
  endfunction
endclass

class consumer_wrapper extends uvm_component;
  seq_item req;
  consumer con;
  uvm_analysis_export #(seq_item) a_export;
  
  `uvm_component_utils(consumer_wrapper)
  
  function new(string name = "consumer_wrapper", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    a_export = new("a_export");
    con = consumer::type_id::create("con", this);
  endfunction
  
  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    a_export.connect(con.a_imp);
  endfunction
endclass

class env extends uvm_env;
  producer pro;
  consumer_wrapper con_wrap;
  `uvm_component_utils(env)
  
  
  function new(string name = "env", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    pro = producer::type_id::create("pro", this);
    con_wrap = consumer_wrapper::type_id::create("con_wrap", this);
  endfunction
  
  function void connect_phase(uvm_phase phase);
    super.connect_phase(phase);
    pro.a_put.connect(con_wrap.a_export);
  endfunction
endclass
              
class test extends uvm_test;
  env env_o;
  `uvm_component_utils(test)
  
  function new(string name = "test", uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    env_o = env::type_id::create("env_o", this);
  endfunction
 
  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    #50;
    phase.drop_objection(this);
  endtask
endclass

module tb_top;
  initial begin
    run_test("test");
  end
endmodule

Output:

UVM_INFO testbench.sv(22) @ 0: uvm_test_top.env_o.pro [producer] Send value = 5
UVM_INFO testbench.sv(39) @ 0: uvm_test_top.env_o.con_wrap.con [consumer] Received value = 5