two-way communication

I. Overview

Similar to one-way communication, the two ends of two-way communication are also divided into initiator and target, but the data flow is bidirectional between end-to-end. Both ends of the two-way communication play the role of producer and consumer at the same time, and the initiator, as the request initiator, waits for the response to return after initiating the request.

UVM bidirectional ports are divided into the following types:

  • uvm_blocking_transport_PORT
  • uvm_nonblocking_transport_PORT
  • uvm_transport_PORT
  • uvm_blocking_master_PORT
  • uvm_nonblocking_master_PORT
  • uvm_master_PORT
  • uvm_blocking_slave_PORT
  • uvm_nonblocking_slave_PORT
  • uvm_slave_PORT
     

PORT represents port, export

2. Classification

 According to the communication handshake mode, bidirectional ports can be divided into:

  • transaction two-way communication
  • Two-way communication between master and slave

The transport port can complete the sending and returning of REQ and RSP in the same method call process through the transport() method.

The communication mode of master and slave must be called by put, get and peek respectively, and a handshake communication can be completed only by using two methods. The difference between the master port and the slave port is that when the initiator acts as the master, it will send a REQ to the target, and then obtain the RSP from the target. When the initiator uses the slave port, it will first obtain the REQ from the target, and then send the RSP to the target. Send it to the target side.
 

Three, transport

insert image description here

transport two-way communication

class comp1 extends uvm_component;
	uvm_blocking_transport_port #(itrans, otrans) bt_port;
	`uvm_component_utils(comp1)
	...
	task run_phase(uvm_phase phase);
		itrans itr;
		otrans otr;
		int trans_num = 2;
		for(int i = 0; i < trans_num; i++) begin
			itr = new("itr", this);
			itr.id = i;
			itr.data = 'h10 + i;
			this.bt_port.transport(itr, otr);
			`uvm_info("TRSPT", $sformatf("put itrans id: 'h%0x, data: 'h%0x | get otrans id: 'h%0x, data: 'h%0x", itr.id, itr.data, otr.id, otr.data), UVM_LOW)
		end
	endtask
endclass
		
class comp2 extends uvm_component;
	uvm_blocking_transport_imp #(itrans, otrans, comp2) bt_imp;
	`uvm_component_utils(comp2)
	...
	task transport(itrans req, output otrans rsp);
		rsp = new("rsp", this);
		rsp.id = req.id;
		rsp.data = req.data << 8;
	endtask
endclass

class env1 extends uvm_env;
	comp1 c1;
	comp2 c2;
	`uvm_component_utils(env1)
	...
	function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		c1 = comp1::type_id::create("c1", this);
		c2 = comp2::type_id::create("c2", this);
	endfunction
	function void connect_phase(uvm_phase phase);
		super.connect_phase(phase);
		c1.bt_port.connect(c2.bt_imp);
	endfunction
endclass

 Bidirectional port processing is similar to unidirectional port instantiation and connection, the difference is that the corresponding bidirectional transmission tasks are required to be implementedtask transport(itrans req, output otrans rsp)

Guess you like

Origin blog.csdn.net/Arvin_ing/article/details/127709485