In this phase, we will write a receiver and use the receiver in environment class to collect the packets coming from the switch output_interface.
Receiver
Receiver collects the data bytes from the interface signal. And then unpacks the bytes in to packet using unpack_bytes method and pushes it into Rcvr2Sb_port for score boarding.
Receiver class is written in Reveicer.sv file.
Receiver class is defined by extending uvm_component class. It will drive the received transaction to scoreboard using uvm_analysis_port.
1) Define Receiver class by extending uvm_component.
`ifndef GUARD_RECEIVER
`define GUARD_RECEIVER
class Receiver extends uvm_component;
endclass : Receiver
`endif
2) Declare configuration class object.
Configuration cfg;
3) Declare an integer to hold the receiver number.
integer id;
4) Declare a virtual interface of dut out put side.
virtual output_interface.OP output_intf;
5) Declare analysis port which is used by receiver to send the received transaction to scoreboard.
uvm_analysis_port #(Packet) Rcvr2Sb_port;
6) Declare the utility macro. This utility macro provides the implementation of creat() and get_type_name() methods.
`uvm_component_utils(Receiver)
7) Define the constructor.
function new (string name, uvm_component parent); super.new(name, parent); endfunction : new
8) Define the build method and construct the Rcvr2Sb_port.
10) Define the run() method. This method collects the packets from the DUT output interface and unpacks it into high level transaction using transactions unpack_bytes() method.
virtualtask run();
Packet pkt; fork forever begin
// declare the queue and dynamic array here
// so they are automatically allocated for every packet bit [7:0] bq[$],bytes[];
repeat(2) @(posedge output_intf.clock); while (output_intf.cb.ready) begin
bq.push_back(output_intf.cb.data_out);
@(posedge output_intf.clock); end
bytes = new[bq.size()] (bq); // Copy queue into dyn array
virtualtask run();
Packet pkt; fork forever begin
// declare the queue and dynamic array here
// so they are automatically allocated for every packet bit [7:0] bq[$],bytes[];
repeat(2) @(posedge output_intf.clock); while (output_intf.cb.ready) begin
bq.push_back(output_intf.cb.data_out);
@(posedge output_intf.clock); end
bytes = new[bq.size()] (bq); // Copy queue into dyn array
We will update the Environment class and take instance of receiver and run the testcase.
1) Declare 4 receivers.
Receiver Rcvr[4];
2) In the build() method construct the Receivers using create() methods. Also update the id variable of the receiver object.
foreach(Rcvr[i]) begin
Rcvr[i] = Receiver::type_id::create($psprintf("Rcvr%0d",i),this);
Rcvr[i].id = i; end
Environment class source code
`ifndef GUARD_ENV
`define GUARD_ENV
class Environment extends uvm_env;
`uvm_component_utils(Environment)
Sequencer Seqncr;
Driver Drvr;
Receiver Rcvr[4];
function new(string name , uvm_component parent = null);
super.new(name, parent);
endfunction: new
virtual function void build();
super.build();
uvm_report_info(get_full_name(),"START of build ",UVM_LOW);
Drvr = Driver::type_id::create("Drvr",this);
Seqncr = Sequencer::type_id::create("Seqncr",this);
foreach(Rcvr[i]) begin
Rcvr[i] = Receiver::type_id::create($psprintf("Rcvr%0d",i),this);
Rcvr[i].id = i; end
uvm_report_info(get_full_name(),"END of build ",UVM_LOW);
endfunction
virtual function void connect();
super.connect();
uvm_report_info(get_full_name(),"START of connect ",UVM_LOW);
Drvr.seq_item_port.connect(Seqncr.seq_item_export);
uvm_report_info(get_full_name(),"END of connect ",UVM_LOW);
endfunction