Phase 6 Receiver
Phase 6 Receiver
Phase 6 Receiver
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 collects the data bytes from the interface signal. And then unpacks the bytes in to packet and
pushes it into mailbox.
Receiver class is written in reveicer.sv file.
1) Declare a virtual output_interface. We will connect this to the Physical interface of the top module,
same as what we did in environment class.
virtual output_interface.OP output_intf;
2) Declare a mailbox "rcvr2sb" which is used to send the packets to the score board
mailbox rcvr2sb;
3) Define new constructor with arguments, virtual input interface and a mail box which is used to send
packets from the receiver to scoreboard.
function new(virtual output_interface.OP output_intf_new,mailbox rcvr2sb);
this.output_intf = output_intf_new ;
if(rcvr2sb == null)
begin
$display(" **ERROR**: rcvr2sb is null");
$finish;
end
else
this.rcvr2sb = rcvr2sb;
endfunction : new
4) Define the start method.
In start method, do the following
Wait for the ready signal to be asserted by the DUT.
wait(output_intf.cb.ready)
If the ready signal is asserted, then request the DUT to send the data out from the data_out signal by
asserting the read signal. When the data to be sent is finished by the DUT, it will deassert the ready
signal. Once the ready signal is deasserted, stop collecting the data bytes and deasseart the read signal.
output_intf.cb.read <= 1;
repeat(2) @(posedge output_intf.clock);
while (output_intf.cb.ready)
begin
bytes = new[bytes.size + 1](bytes);
bytes[bytes.size - 1] = output_intf.cb.data_out;
@(posedge output_intf.clock);
end
output_intf.cb.read <= 0;
@(posedge output_intf.clock);
$display(" %0d : Receiver : Received a packet of length %0d",$time,bytes.size);
Create a new packet object of packet.
pkt = new();
Then call the unpack method of the packet to unpacked the bytes and then display the packet content.
pkt.byte_unpack(bytes);
pkt.display();
Then send the packet to scoreboard.
rcvr2sb.put(pkt);
Delete the dynamic array bytes.
bytes.delete();
Receiver Class Source Code:
`ifndef GUARD_RECEIVER
`define GUARD_RECEIVER
class Receiver;
virtual output_interface.OP output_intf;
mailbox rcvr2sb;
//// constructor method ////
function new(virtual output_interface.OP output_intf_new,mailbox rcvr2sb);
this.output_intf = output_intf_new ;
if(rcvr2sb == null)
begin
$display(" **ERROR**: rcvr2sb is null");
$finish;
end
else
this.rcvr2sb = rcvr2sb;
endfunction : new
task start();
logic [7:0] bytes[];
packet pkt;
forever
begin
repeat(2) @(posedge output_intf.clock);
wait(output_intf.cb.ready)
output_intf.cb.read <= 1;
repeat(2) @(posedge output_intf.clock);
while (output_intf.cb.ready)
begin
bytes = new[bytes.size + 1](bytes);
bytes[bytes.size - 1] = output_intf.cb.data_out;
@(posedge output_intf.clock);
end
output_intf.cb.read <= 0;
@(posedge output_intf.clock);
$display(" %0d : Receiver : Received a packet of length %0d",$time,bytes.size);
pkt = new();
pkt.byte_unpack(bytes);
pkt.display();
rcvr2sb.put(pkt);
bytes.delete();
end
endtask : start
endclass
`endif
Now we will take the instance of the receiver in the environment class.
1) Declare a mailbox "rcvr2sb" which will be used to connect the scoreboard and receiver.
mailbox rcvr2sb;
2) Declare 4 receiver object "rcvr".
Receiver rcvr[4];
3) In build method, construct the mail box.
rcvr2sb = new();
4) In build method, construct the receiver object. Pass the output_intf and "rcvr2sb" mail box. There are
4 output interfaces and receiver objects. We will connect one receiver for one output interface.
foreach(rcvr[i])
rcvr[i]= new(output_intf[i],rcvr2sb);
5) To start collecting the packets from the DUT, call the "start" method of "rcvr" in the "start" method of
Environment class.
task start();
$display(" %0d : Environment : start of start() method",$time);
fork
drvr.start();
rcvr[0].start();
rcvr[1].start();
rcvr[2].start();
rcvr[3].start();
join_any
$display(" %0d : Environment : end of start() method",$time);
endtask : start
Environment Class Source Code:
`ifndef GUARD_ENV
`define GUARD_ENV
class Environment ;
virtual mem_interface.MEM mem_intf ;
virtual input_interface.IP input_intf ;
virtual output_interface.OP output_intf[4] ;
Driver drvr;
Receiver rcvr[4];
mailbox drvr2sb;
mailbox rcvr2sb;
function new(virtual mem_interface.MEM mem_intf_new ,
virtual input_interface.IP input_intf_new ,
virtual output_interface.OP output_intf_new[4] );
this.mem_intf = mem_intf_new ;
this.input_intf = input_intf_new ;
this.output_intf = output_intf_new ;
$display(" %0d : Environment : created env object",$time);
endfunction : new
function void build();
$display(" %0d : Environment : start of build() method",$time);
drvr2sb = new();
rcvr2sb = new();
drvr= new(input_intf,drvr2sb);
foreach(rcvr[i])
rcvr[i]= new(output_intf[i],rcvr2sb);
$display(" %0d : Environment : end of build() method",$time);
endfunction : build
task reset();
$display(" %0d : Environment : start of reset() method",$time);
// Drive all DUT inputs to a known state
mem_intf.cb.mem_data <= 0;
mem_intf.cb.mem_add <= 0;
mem_intf.cb.mem_en <= 0;
mem_intf.cb.mem_rd_wr <= 0;
input_intf.cb.data_in <= 0;
input_intf.cb.data_status <= 0;
output_intf[0].cb.read <= 0;
output_intf[1].cb.read <= 0;
output_intf[2].cb.read <= 0;
output_intf[3].cb.read <= 0;
// Reset the DUT
input_intf.reset <= 1;
repeat (4) @ input_intf.clock;
input_intf.reset <= 0;
$display(" %0d : Environment : end of reset() method",$time);
endtask : reset
task cfg_dut();
$display(" %0d : Environment : start of cfg_dut() method",$time);
mem_intf.cb.mem_en <= 1;
@(posedge mem_intf.clock);
mem_intf.cb.mem_rd_wr <= 1;
@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h0;
mem_intf.cb.mem_data <= `P0;
$display(" %0d : Environment : Port 0 Address %h ",$time,`P0);
@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h1;
mem_intf.cb.mem_data <= `P1;
$display(" %0d : Environment : Port 1 Address %h ",$time,`P1);
@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h2;
mem_intf.cb.mem_data <= `P2;
$display(" %0d : Environment : Port 2 Address %h ",$time,`P2);
@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h3;
mem_intf.cb.mem_data <= `P3;
$display(" %0d : Environment : Port 3 Address %h ",$time,`P3);
@(posedge mem_intf.clock);
mem_intf.cb.mem_en <=0;
mem_intf.cb.mem_rd_wr <= 0;
mem_intf.cb.mem_add <= 0;
mem_intf.cb.mem_data <= 0;
$display(" %0d : Environment : end of cfg_dut() method",$time);
endtask :cfg_dut
task start();
$display(" %0d : Environment : start of start() method",$time);
fork
drvr.start();
rcvr[0].start();
rcvr[1].start();
rcvr[2].start();
rcvr[3].start();
join_any
$display(" %0d : Environment : end of start() method",$time);
endtask : start
task wait_for_end();
$display(" %0d : Environment : start of wait_for_end() method",$time);
repeat(10000) @(input_intf.clock);
$display(" %0d : Environment : end of wait_for_end() method",$time);
endtask : wait_for_end
task run();
$display(" %0d : Environment : start of run() method",$time);
build();
reset();
cfg_dut();
start();
wait_for_end();
report();
$display(" %0d : Environment : end of run() method",$time);
endtask : run
task report();
endtask: report
endclass
`endif
Download the phase 6 source code:
switch_6.tar
Browse the code in switch_6.tar
Run the command:
vcs -sverilog -f filelist -R -ntb_opts dtm