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: ([email protected]) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(91) @ 100: uvm_test_top.compB [COMPB] ComponentA just gave me the packet
pkt: ([email protected]) { addr: 'ha1  data: 'h64  } 
UVM_INFO testbench.sv(49) @ 100: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: ([email protected]) { addr: 'hc1  data: 'hb9  } 
UVM_INFO testbench.sv(49) @ 150: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: ([email protected]) { 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: ([email protected]) { addr: 'hc1  data: 'hb9  } 
UVM_INFO testbench.sv(49) @ 200: uvm_test_top.compA [COMPA] Packet sent to CompB
pkt: ([email protected]) { 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: ([email protected]) { addr: 'hf0  data: 'hae  } 
UVM_INFO testbench.sv(91) @ 400: uvm_test_top.compB [COMPB] ComponentA just gave me the packet
pkt: ([email protected]) { 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 ---

Watch the example !