Funvizeo logo
  • Contents
      • Back
      • Verilog
      • SystemVerilog
      • UVM
      • Digital Basics
      • Verification
Most Popular
Verification
  Testbench Evolution
  Constraint Random Verification
  Verification Techniques
  Verification Plan
  Code Coverage

Verilog
  Data Types
  Basic Constructs
  Behavioral Modeling
  Gate Modeling
  Simulation Basics
  Design Examples
  Interview Questions

SystemVerilog
  Data Types
  Class
  Interface
  Constraints and more!
  Testbench Examples
  Interview Questions

UVM
  Sequences
  Testbench Components
  TLM Tutorial
  Register Model Tutorial
  Testbench Examples
  Interview Questions

Digital Fundamentals
  Binary Arithmetic
  Boolean Logic
  Karnaugh Maps
  Combinational Logic
  Sequential Logic

UVM TLM Analysis Port

The put/get communication we have seen earlier typically require a corresponding export to supply the implementation. The idea behind having an analysis port is that a component like monitor should be able to generate a stream of transactions regardless of whether there is a target actually connected to it.

The uvm_analysis_port is a specialized TLM based class whose interface consists of a single function write () and can be embedded within any component as shown in the snippet below. This port contains a list of analysis exports that are connected to it. When the component (my_monitor) calls analysis_port.write(), it basically cycles through the list and calls the write() method of each connected export. If nothing is connected to it, then it simply does not do anything.


class my_monitor extends uvm_component;
	...
	uvm_analysis_port #(my_data) analysis_port;
	...
endclass

The advantage lies in the fact that an analysis port may be connected to zero, one or many analysis exports and allows a component to call write() method without depending on the number of connected exports. Also it's worth to note that write() is a void function and hence will always complete within the same simulation delta cycle.

Example

Let's take component B from the TLM Put example and connect three Subscribers to it. In order for component B to broadcast transactions to it's subscribers, there needs to be a special channel for communication. This is implemented by analysis ports. Analysis ports are declared using uvm_analysis_port so that component B can send transactions into the channel. We'll see how we can connect subscribers to this channel in a short while.

Read more: UVM TLM Analysis Port

UVM TLM Example

This UVM TLM example uses put ports, TLM FIFOs and get ports discussed in previous articles to build a testbench that has TLM ports at different levels.

tlm-hier

TLM FIFO can be extended to have another component called componentB to accept packets using another internal FIFO and sub-component.

A class called Packet is defined below to act as the data item that will be transferred from one component to another. This class object will have two random variables that can be randomized before sending.


class Packet extends uvm_object;
  rand bit[7:0] addr;
  rand bit[7:0] data;
 
  `uvm_object_utils_begin(Packet)
    `uvm_field_int(addr, UVM_ALL_ON)
    `uvm_field_int(data, UVM_ALL_ON)
  `uvm_object_utils_end
 
  function new(string name = "Packet");
    super.new(name);
  endfunction
endclass	

subComp1

This component is exactly the same as in UVM TLM FIFO example and starts sending packets using its uvm_blocking_put_port.


class subComp1 extends uvm_component;
   `uvm_component_utils (subComp1)
 
  // Create a blocking TLM put port which can send an object
  // of type 'Packet'
  uvm_blocking_put_port #(Packet) m_put_port;
  int m_num_tx;
 
   function new (string name = "subComp1", uvm_component parent= null);
      super.new (name, parent);
   endfunction
 
   // Remember that TLM put_port is a class object and it will have to be 
   // created with new ()
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
     m_put_port = new ("m_put_port", this);
   endfunction
 
  // Create a packet, randomize it and send it through the port
  // Note that put() is a method defined by the receiving component
  // Repeat these steps N times to send N packets
   virtual task run_phase (uvm_phase phase);
     repeat (m_num_tx) begin
         Packet pkt = Packet::type_id::create ("pkt");
         assert(pkt.randomize ()); 
 		#50;
          // Print the packet to be displayed in log
       `uvm_info ("SUBCOMP1", "Packet sent to compA:tlm_fifo", UVM_LOW)
         pkt.print (uvm_default_line_printer);
 
         // Call the TLM put() method of put_port class and pass packet as argument
         m_put_port.put (pkt);
      end
   endtask   
endclass

subComp2

This sub-component is slightly slower in receiving packets compared to the one seen above, and accepts data through uvm_blocking_get_port.

Note that this also has another put port of type uvm_blocking_put_port to forward data out of componentA.


class subComp2 extends uvm_component;
   `uvm_component_utils (subComp2)
 
   // Create a get_port to request for data from subComp1
   uvm_blocking_get_port #(Packet) m_get_port;
  uvm_blocking_put_port #(Packet) m_put_port;
 
  function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      m_get_port = new ("m_get_port", this);
     m_put_port = new ("m_put_port", this);
   endfunction
 
   virtual task run_phase (uvm_phase phase);
      Packet pkt;
      forever begin
       #100;
         m_get_port.get (pkt);
        `uvm_info ("SUBCOMP2", "Packet received from compA:tlm_fifo, forward it", UVM_LOW)
        pkt.print (uvm_default_line_printer);
        m_put_port.put(pkt);
      end
   endtask
endclass   

ComponentA

This layer contains both sub-components connected together by a TLM FIFO since their transfer rates are different.

Note that it also has another put port of type uvm_blocking_put_port to forward the packet it receives from subComp2 which is at a lower layer.


class componentA extends uvm_component;
   `uvm_component_utils (componentA)
  function new(string name="componentA", uvm_component parent=null);
    super.new(name, parent);
  endfunction
  
   subComp1 m_subcomp_1;
   subComp2 m_subcomp_2;
 
   uvm_tlm_fifo #(Packet)    		m_tlm_fifo;
   uvm_blocking_put_port #(Packet)  m_put_port;
   int 								m_num_tx;
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      // Create an object of both components
      m_subcomp_1 = subComp1::type_id::create ("m_subcomp_1", this);
      m_subcomp_2 = subComp2::type_id::create ("m_subcomp_2", this);
 
      // Create a FIFO with depth 2
      m_tlm_fifo = new ("uvm_tlm_fifo", this, 2);
      m_put_port = new ("m_put_port", this);
      m_subcomp_1.m_num_tx = m_num_tx;
   endfunction
 
   // Make componentA connections
   virtual function void connect_phase (uvm_phase phase);
     // Connect put port from subComp1 to TLM FIFO and then 
     // connect get_export of TLM FIFO with subComp2
     m_subcomp_1.m_put_port.connect(m_tlm_fifo.put_export);
     m_subcomp_2.m_get_port.connect(m_tlm_fifo.get_export);
     
     // Now connect subComp2 to componentA for forwarding pkt
     m_subcomp_2.m_put_port.connect(this.m_put_port);
   endfunction
 
   // Display a message when the FIFO is full
   virtual task run_phase (uvm_phase phase);
      forever begin
        #10 if (m_tlm_fifo.is_full ()) 
          `uvm_info ("COMPA", "componentA:TLM_Fifo is now FULL !", UVM_MEDIUM)
      end
   endtask
endclass

subComp3

Assume the destination component is even slower than the other components seen above and accepts packet using a uvm_blocking_get_port.


// subComp3 accepts packet even slower than what componentA is sending out          
// which is the reason we need a TLM FIFO in componentB
class subComp3 extends uvm_component;
  `uvm_component_utils (subComp3)
  
   // Create a get_port to request for data from subComp1
   uvm_blocking_get_port #(Packet) m_get_port;
   int m_num_tx;
 
  function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      m_get_port = new ("m_get_port", this);
   endfunction
 
   virtual task run_phase (uvm_phase phase);
      Packet pkt;
     repeat(m_num_tx) begin
        #200;
        m_get_port.get (pkt);
        `uvm_info ("SUBCOMP3", "Packet received from componentA", UVM_LOW)
        pkt.print (uvm_default_line_printer);
      end
   endtask
endclass

ComponentB

Another UVM TLM FIFO is required to be connected to subComp3 to buffer packets it receives because of the slower rate of destination. Note that this has a top level put_export port of type uvm_blocking_put_export.


class componentB extends uvm_component;
   `uvm_component_utils (componentB)
 
   subComp3                    			m_subcomp_3;
  uvm_tlm_fifo #(Packet)    			m_tlm_fifo;
   uvm_blocking_put_export #(Packet) 	m_put_export;
   int 									m_num_tx;
 
   function new (string name = "componentB", uvm_component parent = null);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      // Create an object of both components
     m_subcomp_3 = subComp3::type_id::create ("m_subcomp_3", this);
 
      // Create a FIFO with depth 2
      m_tlm_fifo = new ("tlm_fifo", this, 2);
 
      // Create the export to connect with componentA
     m_put_export = new ("m_put_export", this);
     
     m_subcomp_3.m_num_tx = m_num_tx;
   endfunction
 
   virtual function void connect_phase (uvm_phase phase);
      // Connect from componentB export to FIFO export
     m_put_export.connect (m_tlm_fifo.put_export);
 
      // Connect from FIFO export to subComponent3 port 
     m_subcomp_3.m_get_port.connect (m_tlm_fifo.get_export);
   endfunction
  
     // Display a message when the FIFO is full
   virtual task run_phase (uvm_phase phase);
      forever begin
        #10 if (m_tlm_fifo.is_full ()) 
          `uvm_info ("COMPB", "componentB:TLM_Fifo is now FULL !", UVM_MEDIUM)
      end
   endtask
endclass

Top Env/Test

The connection between a port and its implementation has to be done at a higher hierarchical level. Since both components are instantiated directly within the test class in this example, the connection between them can be done during the connect_phase of the test. If these two components were instantiated in another component or environment, they have to be connected during the connect_phase of that component or environment.


class my_test extends uvm_env;
  `uvm_component_utils (my_test)
 
  componentA compA;
  componentB compB;
  int 		 m_num_tx;
  
  function new (string name = "my_test", uvm_component parent = null);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
     compA = componentA::type_id::create("componentA", this);
     compB = componentB::type_id::create("componentB", this);
     
     std::randomize(m_num_tx) with { m_num_tx inside {[4:10]}; };
     `uvm_info("TEST", $sformatf("Create %0d packets in total", m_num_tx), UVM_LOW)
     compA.m_num_tx = m_num_tx;
     compB.m_num_tx = m_num_tx;
   endfunction
 
   // Connect the ports to the export of FIFO.
   virtual function void connect_phase (uvm_phase phase);
     compA.m_put_port.connect(compB.m_put_export);
   endfunction
  
  virtual task run_phase(uvm_phase phase);
    super.run_phase(phase);
    // Let all components finish for purpose of illustration
    phase.raise_objection(this);
    #1000;
    phase.drop_objection(this);
  endtask
endclass
 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO testbench.sv(220) @ 0: uvm_test_top [TEST] Create 4 packets in total
UVM_INFO testbench.sv(48) @ 50: uvm_test_top.componentA.m_subcomp_1 [SUBCOMP1] Packet sent to compA:tlm_fifo
pkt: (Packet@2663) { addr: 'h1f  data: 'h31  } 
UVM_INFO testbench.sv(79) @ 100: uvm_test_top.componentA.m_subcomp_2 [SUBCOMP2] Packet received from compA:tlm_fifo, forward it
pkt: (Packet@2663) { addr: 'h1f  data: 'h31  } 
UVM_INFO testbench.sv(48) @ 100: uvm_test_top.componentA.m_subcomp_1 [SUBCOMP1] Packet sent to compA:tlm_fifo
pkt: (Packet@2685) { addr: 'hf4  data: 'h91  } 
UVM_INFO testbench.sv(48) @ 150: uvm_test_top.componentA.m_subcomp_1 [SUBCOMP1] Packet sent to compA:tlm_fifo
pkt: (Packet@2699) { addr: 'hab  data: 'ha8  } 
UVM_INFO testbench.sv(126) @ 150: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 160: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 170: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 180: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 190: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(154) @ 200: uvm_test_top.componentB.m_subcomp_3 [SUBCOMP3] Packet received from componentA
pkt: (Packet@2663) { addr: 'h1f  data: 'h31  } 
UVM_INFO testbench.sv(79) @ 200: uvm_test_top.componentA.m_subcomp_2 [SUBCOMP2] Packet received from compA:tlm_fifo, forward it
pkt: (Packet@2685) { addr: 'hf4  data: 'h91  } 
UVM_INFO testbench.sv(48) @ 200: uvm_test_top.componentA.m_subcomp_1 [SUBCOMP1] Packet sent to compA:tlm_fifo
pkt: (Packet@2681) { addr: 'h77  data: 'he7  } 
UVM_INFO testbench.sv(126) @ 200: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 210: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 220: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 230: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 240: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 250: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 260: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 270: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 280: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(126) @ 290: uvm_test_top.componentA [COMPA] componentA:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(79) @ 300: uvm_test_top.componentA.m_subcomp_2 [SUBCOMP2] Packet received from compA:tlm_fifo, forward it
pkt: (Packet@2699) { addr: 'hab  data: 'ha8  } 
UVM_INFO testbench.sv(198) @ 300: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 310: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 320: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 330: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 340: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 350: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 360: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 370: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 380: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 390: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(154) @ 400: uvm_test_top.componentB.m_subcomp_3 [SUBCOMP3] Packet received from componentA
pkt: (Packet@2685) { addr: 'hf4  data: 'h91  } 
UVM_INFO testbench.sv(79) @ 400: uvm_test_top.componentA.m_subcomp_2 [SUBCOMP2] Packet received from compA:tlm_fifo, forward it
pkt: (Packet@2681) { addr: 'h77  data: 'he7  } 
UVM_INFO testbench.sv(198) @ 400: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 410: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 420: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 430: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 440: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 450: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 460: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 470: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 480: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 490: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 500: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 510: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 520: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 530: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 540: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 550: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 560: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 570: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 580: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(198) @ 590: uvm_test_top.componentB [COMPB] componentB:TLM_Fifo is now FULL !
UVM_INFO testbench.sv(154) @ 600: uvm_test_top.componentB.m_subcomp_3 [SUBCOMP3] Packet received from componentA
pkt: (Packet@2699) { addr: 'hab  data: 'ha8  } 
UVM_INFO testbench.sv(154) @ 800: uvm_test_top.componentB.m_subcomp_3 [SUBCOMP3] Packet received from componentA
pkt: (Packet@2681) { addr: 'h77  data: 'he7  } 
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 1000: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 1000: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

UVM TLM Fifo [uvm_tlm_fifo]

Assume data rate of the sender is much faster than the rate at which the receiver can get packets. A FIFO element is required in between to store packets so that it allows both the sender and the receiver to independently operate. Depth of the FIFO is typically calculated based on the rate of data transfer. A TLM FIFO is placed in between testbench components that transfer data objects at different rates.

UVM TLM FIFO Example

A class called Packet is defined below to act as the data item that will be transferred from one component to another. This class object will have two random variables that can be randomized before sending.


class Packet extends uvm_object;
  rand bit[7:0] addr;
  rand bit[7:0] data;
 
  `uvm_object_utils_begin(Packet)
    `uvm_field_int(addr, UVM_ALL_ON)
    `uvm_field_int(data, UVM_ALL_ON)
  `uvm_object_utils_end
 
  function new(string name = "Packet");
    super.new(name);
  endfunction
endclass
1. Create sender class with a port of type uvm_blocking_put_port

A class called componentA is created which has a uvm_blocking_put_port parameterized to accept a data object of type Packet. The port has to be instantiated with the new() method preferably in the build_phase of the same component.

In this example, a class object of type Packet is created, randomized and sent via the put_port handle by calling the put() method. Many such packets can be sent using a simple loop controlled by a configurable variable.


class componentA extends uvm_component;
   `uvm_component_utils (componentA)
 
  // Create a blocking TLM put port which can send an object
  // of type 'Packet'
  uvm_blocking_put_port #(Packet) m_put_port;
  int m_num_tx = 2;
 
   function new (string name = "componentA", uvm_component parent= null);
      super.new (name, parent);
   endfunction
 
   // Remember that TLM put_port is a class object and it will have to be 
   // created with new ()
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
     m_put_port = new ("m_put_port", this);
   endfunction
 
  // Create a packet, randomize it and send it through the port
  // Note that put() is a method defined by the receiving component
  // Repeat these steps N times to send N packets
   virtual task run_phase (uvm_phase phase);
     phase.raise_objection(this);
     repeat (m_num_tx) begin
         Packet pkt = Packet::type_id::create ("pkt");
         assert(pkt.randomize ()); 
 		#50;
          // Print the packet to be displayed in log
         `uvm_info ("COMPA", "Packet sent to CompB", UVM_LOW)
         pkt.print (uvm_default_line_printer);
 
         // Call the TLM put() method of put_port class and pass packet as argument
         m_put_port.put (pkt);
      end
      phase.drop_objection(this);
   endtask
endclass
2. Create receiver class that receives using the get method

The receiver class tries to get an item using uvm_blocking_get_port.


class componentB extends uvm_component;
   `uvm_component_utils (componentB)
 
   // Create a get_port to request for data from componentA
   uvm_blocking_get_port #(Packet) m_get_port;
   int m_num_tx = 2;
 
  function new (string name, uvm_component parent);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      m_get_port = new ("m_get_port", this);
   endfunction
 
   virtual task run_phase (uvm_phase phase);
      Packet pkt;
     phase.raise_objection(this);
     repeat (m_num_tx) begin
       #100;
         m_get_port.get (pkt);
         `uvm_info ("COMPB", "ComponentA just gave me the packet", UVM_LOW)
        pkt.print (uvm_default_line_printer);
      end
     phase.drop_objection(this);
   endtask
endclass
3. Connect the two components via a TLM FIFO at a higher level

The connection between the two components via a TLM FIFO has to be done at a higher hierarchical level. Since both components are instantiated directly within the test class in this example, the connection between them can be done during the connect_phase of the test. If these two components were instantiated in another component or environment, they have to be connected during the connect_phase of that component or environment.

UVM TLM FIFO in this example is defined to have a depth of 2. The put_export is connected to the first component's put port and the get_export is connected to the receiver's get port.


class my_test extends uvm_env;
  `uvm_component_utils (my_test)
 
   componentA compA;
   componentB compB;
  
   int m_num_tx;
 
   // Create the UVM TLM Fifo that can accept simple_packet
   uvm_tlm_fifo #(Packet)    m_tlm_fifo;
 
  function new (string name = "my_test", uvm_component parent = null);
      super.new (name, parent);
   endfunction
 
   virtual function void build_phase (uvm_phase phase);
      super.build_phase (phase);
      // Create an object of both components
      compA = componentA::type_id::create ("compA", this);
      compB = componentB::type_id::create ("compB", this);
     std::randomize(m_num_tx) with { m_num_tx inside {[4:10]}; };
     compA.m_num_tx = m_num_tx;
     compB.m_num_tx = m_num_tx;
 
      // Create a FIFO with depth 2
      m_tlm_fifo = new ("uvm_tlm_fifo", this, 2);
   endfunction
 
   // Connect the ports to the export of FIFO.
   virtual function void connect_phase (uvm_phase phase);
     compA.m_put_port.connect(m_tlm_fifo.put_export);
     compB.m_get_port.connect(m_tlm_fifo.get_export);
   endfunction
 
   // Display a message when the FIFO is full
   virtual task run_phase (uvm_phase phase);
      forever begin
        #10;
        if (m_tlm_fifo.is_full ())
          `uvm_info ("UVM_TLM_FIFO", "Fifo is now FULL !", UVM_MEDIUM)          
      end
   endtask
endclass
uvm-tlm-fifo

You can see that we connected both the ports in componentA/B to the exports in TLM Fifo.

 Simulation Log
UVM_INFO @ 0: reporter [RNTST] Running test my_test...
UVM_INFO testbench.sv(49) @ 50: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@2234) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(91) @ 100: uvm_test_top.compB [COMPB] ComponentA just gave me the packet
pkt: (Packet@2234) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(49) @ 100: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@2256) { addr: 'hc1  data: 'hb9  } 
UVM_INFO testbench.sv(49) @ 150: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@2270) { addr: 'hf0  data: 'hae  } 
UVM_INFO testbench.sv(137) @ 150: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 160: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 170: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 180: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 190: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(91) @ 200: uvm_test_top.compB [COMPB] ComponentA just gave me the packet
pkt: (Packet@2256) { addr: 'hc1  data: 'hb9  } 
UVM_INFO testbench.sv(49) @ 200: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: (Packet@1879) { addr: 'h68  data: 'h7d  } 
UVM_INFO testbench.sv(137) @ 200: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 210: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 220: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 230: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 240: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 250: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 260: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 270: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 280: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(137) @ 290: uvm_test_top [UVM_TLM_FIFO] Fifo is now FULL !
UVM_INFO testbench.sv(91) @ 300: uvm_test_top.compB [COMPB] ComponentA just gave me the packet
pkt: (Packet@2270) { addr: 'hf0  data: 'hae  } 
UVM_INFO testbench.sv(91) @ 400: uvm_test_top.compB [COMPB] ComponentA just gave me the packet
pkt: (Packet@1879) { addr: 'h68  data: 'h7d  } 
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_objection.svh(1271) @ 400: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /playground_lib/uvm-1.2/src/base/uvm_report_server.svh(847) @ 400: reporter [UVM/REPORT/SERVER] 
--- UVM Report Summary ---

UVM TLM Blocking Get Port

Any component can request to receive a transaction from another component through a TLM get port. The sending component should define an implementation of the get port. The implementation gives sender the chance to define what needs to be sent to the requestor. This is just the opposite of a put port seen in a previous article.

The port can be either blocking or nonblocking in nature, which will decide whether the get method will block execution in the receiver until the sender sends the object. The example shown below is a TLM blocking get port in one component connected to its implementation port in another component.

Read more: UVM TLM Blocking Get Port

UVM TLM Blocking Put Port

Any component can send a transaction to another component through a TLM put port. The receiving component should define an implementation of the put port. The implementation gives receiver the chance to define what has to be done with the incoming packet.

The port can be either blocking or nonblocking in nature, which will decide whether the put method will block execution in the sender until the receiver accepts the object. The example shown below is a TLM blocking put port in one component connected to its implementation port in another component.

Read more: UVM TLM Blocking Put Port

  1. UVM TLM
  2. SystemVerilog forever loop
  3. Gate Level Modeling
  4. Agent and Scoreboard
  5. Reporting Functions

Page 55 of 68

  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
Interview Questions
  Verilog Interview Set 1
  Verilog Interview Set 2
  Verilog Interview Set 3
  Verilog Interview Set 4
  Verilog Interview Set 5

  SystemVerilog Interview Set 1
  SystemVerilog Interview Set 2
  SystemVerilog Interview Set 3
  SystemVerilog Interview Set 4
  SystemVerilog Interview Set 5

  UVM Interview Set 1
  UVM Interview Set 2
  UVM Interview Set 3
  UVM Interview Set 4
Related Topics
  Digital Fundamentals
  Verilog Tutorial

  Verification
  SystemVerilog Tutorial
  UVM Tutorial
Latest in Verilog
  • Verilog $random
  • Verilog VCD Dump
  • Verilog VCD
  • Verilog Namespace
  • Verilog $stop $finish
Latest in SystemVerilog
  • SystemVerilog `define Macro
  • SystemVerilog Callback
  • SystemVerilog Interview Questions Set 10
  • SystemVerilog Interview Questions Set 9
  • SystemVerilog Interview Questions Set 8
Latest in UVM
  • UVM Callback
  • UVM Singleton Object
  • UVM Component [uvm_component]
  • UVM Object [uvm_object]
  • UVM Root [uvm_root]
© 2025 Funvizeo
Terms and Conditions