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
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