In your System Verilog UVM environment, sometimes you want few components to communicate to each other in both ways. For example, a master component can request a memory component to pass over the memory content of specific address. So, how can you impelent such a communication channel between two components? Well, there are multiple ways. You can have two one-directional ports like uvm_get_ports and uvm_put_ports. Initator can send the address through output port and receives the data from another input port. Or it can be implemented through mailbox. The other way to implement is to use uvm_tlm_b_initiator_socket and uvm_tlm_b_target_socket ports. Using this port, you initiator can send a packet with specific address. Same packet can be updated with data by the memory element and later on can be read by initiator. Thus, by using single port and packet, two elements can communicate with each other in bidirectional way. Since this is a blocking port, request information and response information should come in a single shot. Here is an example to illustrate it. You can download the full examples by clicking uvm_bidirectional_port_example.tar.gz
//Memory cell definition
class mem_cell extend umv_sequence_item;
rand bit [1:0] addr;
rand bit [31:0] data;
endclass: mem_cell
//Memory component definition
class memory extends uvm_component;
//Define local memory
local bit [31:0] mem [3:0];
function new(string name = "memory", uvm_component parent = null);
super.new(name, parent);
socket = new("socket", this);
//Initialize the local memory
mem[0] = 32'h00000000;
mem[1] = 32'h11111111;
mem[2] = 32'h22222222;
mem[3] = 32'h33333333;
endfunction : new
//Declare blocking target socket port
uvm_tlm_b_target_socket #(memory, mem_cell) socket;
//Need to write implementation of b_transport() task
task b_transport(mem_cell req, uvm_tlm_time delay);
//Based on the req.addr, update the req.data which will be later read back by initiator
case (req.addr)
2'h0 : begin req.data = mem[0]; end
2'h1 : begin req.data = mem[0]; end
2'h2 : begin req.data = mem[0]; end
2'h3 : begin req.data = mem[0]; end
endcase
endtask : b_transport
endclasss : memory
class initiator extend uvm_component'
//Declare blocking transport socket port
uvm_tlm_b_transport_socket #(mem_cell) socket;
virtual task run_phase(uvm_phase phase);
//instantiate a mem_cell
mem_cell req;
uvm_tlm_time delay = new;
phase.raise_objection(this);
//Create mem_cell
req = mem_cell::type_id::create("req", , get_full_name());
//set address and sent it across to memory component
req.addr = 2'h0;
socket.b_transport(req, delay);
//memory element has now updated the req.data accordingly. it can be used now
`uvm_info("TEST", $sformat(f("For req.add='h%h, received req.data='h%h", req.addr, req.data), UVM_LOW);
//same object can be reused.
//set address and sent it across to memory component
req.addr = 2'h1;
socket.b_transport(req, delay);
//memory element has now updated the req.data accordingly. it can be used now
`uvm_info("TEST", $sformatf("For req.add='h%h, received req.data='h%h", req.addr, req.data), UVM_LOW);
phase.drop_objection(this);
endtask : run_phase
endclass : initator
class env extends uvm_component;
initiator init;
memory mem;
//Connect two ports
function void connect_phase(uvm_phase phase)
init.socket.connect(mem.socket);
endfunction
endclass : env
Log Output:
UVM_INFO initiator.sv(22) @ 10: env.init [TESTCASE] For req.add='h0 received req.data='h00000000
UVM_INFO initiator.sv(26) @ 20: env.init [TESTCASE] For req.add='h1 received req.data='h11111111
You can refer UVM User Guide 1.1 from http://www.accellera.org/community/uvm for more details about these ports.
UVM_INFO initiator.sv(26) @ 20: env.init [TESTCASE] For req.add='h1 received req.data='h11111111
You can refer UVM User Guide 1.1 from http://www.accellera.org/community/uvm for more details about these ports.
1 comment:
It looks to me that you are getting "bidirectional" behavior because you are passing the object reference around. That doesn't require a special TLM type. For a true bidirectional TLM connection try the uvm_blocking_transport:
https://verificationacademy.com/verification-methodology-reference/uvm/docs_1.1a/html/files/tlm1/uvm_ports-svh.html#uvm_*_port#(REQ,RSP)
Post a Comment