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 ovm_component class. It will drive the received transaction to scoreboard using ovm_analysis_port.
1) Define Receiver class by extending ovm_component.
`ifndef GUARD_RECEIVER
`define GUARD_RECEIVER
class Receiver extends ovm_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.
ovm_analysis_port #(Packet) Rcvr2Sb_port;
6) Declare the utility macro. This utility macro provides the implementation of creat() and get_type_name() methods.
`ovm_component_utils(Receiver)
7) Define the constructor.
function new (string name, ovm_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();
bit [7:0] bytes[];
Packet pkt;
fork forever begin repeat(2) @(posedge output_intf.clock);
wait(output_intf.ready)
output_intf.read <= 1;
repeat(2) @(posedge output_intf.clock);
while (output_intf.ready)
begin bytes = new[bytes.size + 1](bytes);
bytes[bytes.size - 1] = output_intf.data_out;
@(posedge output_intf.clock);
end
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
(S) Environment class source code
`ifndef GUARD_ENV `define GUARD_ENV
class Environment extends ovm_env;
`ovm_component_utils(Environment)
Sequencer Seqncr; Driver Drvr;
Receiver Rcvr[4];
function new(string name , ovm_component parent = null); super.new(name, parent); endfunction: new
function void build(); super.build(); ovm_report_info(get_full_name(),"START of build ",OVM_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
ovm_report_info(get_full_name(),"END of build ",OVM_LOW); endfunction function void connect(); super.connect(); ovm_report_info(get_full_name(),"START of connect ",OVM_LOW); Drvr.seq_item_port.connect(Seqncr.seq_item_export); ovm_report_info(get_full_name(),"END of connect ",OVM_LOW); endfunction