|HOME |ABOUT |ARTICLES |ACK |FEEDBACK |TOC |LINKS |BLOG |JOBS |


Tutorials



PHASE 8 SCOREBOARD




In this phase we will see the scoreboard implementation. Vmm has scoreboard classes with lot of features. For this example, we will write a simple scoreboard which is implemented using the vmm_xactor.

Scoreboard has 2 channels. One is used to for getting the packets from the driver and other from the receiver. Then the packets are compared and if they don't match, then error is asserted. For comparison, compare () method of the Packet class is used.

Scoreboard in implemented in file Scoreboard.sv.



1) Declare 2 channels drvr2sb_chan and rcvr2sb_chan.


Packet_channel drvr2sb_chan;
Packet_channel rcvr2sb_chan;


2) Declare a constructor method with drvr2sb_chan , rcvr2sb_chan , a string for instance name and stream_id as arguments.


function new(string inst = "class",
int unsigned stream_id = -1,
Packet_channel drvr2sb_chan = null,
Packet_channel rcvr2sb_chan = null);



3) Call the super.new() method and Connect the channels of the constructor to the channels of the scoreboard.


super.new("sb",inst,stream_id);

if(drvr2sb_chan == null)
`vmm_fatal(this.log,"drvr2sb_channel is not constructed");
else
this.drvr2sb_chan = drvr2sb_chan;

if(rcvr2sb_chan == null)
`vmm_fatal(this.log,"rcvr2sb_channel is not constructed");
else
this.rcvr2sb_chan = rcvr2sb_chan;

`vmm_note(log,"Scoreboard created ");




4) Define vmm_xactor main() method. First call the super.main() method and then do the following steps forever.
Wait until there is a packet is in "rcvr2sb_chan". Then pop the packet from channel.


rcvr2sb_chan.get(pkt_rcv);
$display(" %0d : Scorebooard : Scoreboard received a packet from receiver ",$time);



Then pop the packet from drvr2sb_chan.


drvr2sb_chan.get(pkt_exp);


Compare both packets and assert an error if the comparison fails using `vmm_error.


if(pkt_rcv.compare(pkt_exp,msg))
$display(" %0d : Scoreboard :Packet Matched ",$time);
else
`vmm_error(this.log,$psprintf(" Packet MissMatched \n %s ",msg));

Scoreboard Class Source Code:

`ifndef GUARD_SCOREBOARD
`define GUARD_SCOREBOARD

class Scoreboard extends vmm_xactor;

Packet_channel drvr2sb_chan;
Packet_channel rcvr2sb_chan;


function new(string inst = "class",
int unsigned stream_id = -1,
Packet_channel drvr2sb_chan = null,
Packet_channel rcvr2sb_chan = null);

super.new("sb",inst,stream_id);

if(drvr2sb_chan == null)
`vmm_fatal(this.log,"drvr2sb_channel is not constructed");
else
this.drvr2sb_chan = drvr2sb_chan;

if(rcvr2sb_chan == null)
`vmm_fatal(this.log,"rcvr2sb_channel is not constructed");
else
this.rcvr2sb_chan = rcvr2sb_chan;

`vmm_note(log,"Scoreboard created ");

endfunction:new


task main();
Packet pkt_rcv,pkt_exp;
string msg;
super.main();
forever
begin
rcvr2sb_chan.get(pkt_rcv);
$display(" %0d : Scoreboard : Scoreboard received a packet from receiver ",$time);
drvr2sb_chan.get(pkt_exp);
if(pkt_rcv.compare(pkt_exp,msg))
$display(" %0d : Scoreboard :Packet Matched ",$time);
else
`vmm_error(this.log,$psprintf(" Packet MissMatched \n %s ",msg));
end
endtask : main

endclass

`endif





Now we will see how to connect the scoreboard in the Environment class.


1) Declare a scoreboard handle.


Scoreboard sb;


2) Construct the scoreboard in the build() method. Pass the drvr2sb_chan and rcvr2sb_chan channels to the score board constructor.


sb = new("Sb",0,drvr2sb_chan,rcvr2sb_chan);


3) Start the scoreboard activities in the start() method.


sb.start_xactor();


4) Stop the scoreoard activities in stop() method.


sb.stop_xactor();


Source Code Of The Environment Class:


`ifndef GUARD_ENV
`define GUARD_ENV

class Environment extends vmm_env;

virtual mem_interface.MEM mem_intf ;
virtual input_interface.IP input_intf ;
virtual output_interface.OP output_intf[4] ;

Packet_atomic_gen atomic_gen;
Driver drvr;
Receiver rcvr[4];

Scoreboard sb;

Packet_channel gen2drvr_chan;
Packet_channel drvr2sb_chan;
Packet_channel rcvr2sb_chan;

function new(virtual mem_interface.MEM mem_intf_new ,
virtual input_interface.IP input_intf_new ,
virtual output_interface.OP output_intf_new[4] );
super.new("Environment ");
this.mem_intf = mem_intf_new ;
this.input_intf = input_intf_new ;
this.output_intf = output_intf_new ;

`vmm_note(this.log, "Created env object");
endfunction : new


virtual function void gen_cfg();
super.gen_cfg();
`vmm_note(this.log,"Start of gen_cfg() method ");
`vmm_note(this.log,"End of gen_cfg() method ");
endfunction

virtual function void build();
super.build();
`vmm_note(this.log,"Start of build() method ");
gen2drvr_chan = new("gen2drvr","chan");
drvr2sb_chan = new("drvr2sb","chan");
rcvr2sb_chan = new("rcvr2sb","chan");
atomic_gen = new("atomic_gen",0,gen2drvr_chan);
atomic_gen.stop_after_n_insts = 10;
drvr = new("Drvr",0,input_intf,gen2drvr_chan,drvr2sb_chan);
foreach(rcvr[i])
rcvr[i] = new($psprintf("Rcvr-%0d",i),i,output_intf[i],rcvr2sb_chan);

sb = new("Sb",0,drvr2sb_chan,rcvr2sb_chan);

`vmm_note(this.log,"End of build() method ");
endfunction

virtual task reset_dut();
super.reset_dut();
`vmm_note(this.log,"Start of reset_dut() method ");
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;

`vmm_note(this.log,"End of reset_dut() method ");
endtask

virtual task cfg_dut();
super.cfg_dut();
`vmm_note(this.log,"Start of cfg_dut() method ");
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;
`vmm_note(this.log ,$psprintf(" Port 0 Address %h ",`P0));

@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h1;
mem_intf.cb.mem_data <= `P1;
`vmm_note(this.log ,$psprintf(" Port 1 Address %h ",`P1));

@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h2;
mem_intf.cb.mem_data <= `P2;
`vmm_note(this.log ,$psprintf(" Port 2 Address %h ",`P2));

@(posedge mem_intf.clock);
mem_intf.cb.mem_add <= 8'h3;
mem_intf.cb.mem_data <= `P3;
`vmm_note(this.log ,$psprintf(" Port 3 Address %h ",`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;

`vmm_note(this.log,"End of cfg_dut() method ");
endtask

virtual task start();
super.start();
`vmm_note(this.log,"Start of start() method ");
atomic_gen.start_xactor();
drvr.start_xactor();
rcvr[0].start_xactor();
rcvr[1].start_xactor();
rcvr[2].start_xactor();
rcvr[3].start_xactor();

sb.start_xactor();

`vmm_note(this.log,"End of start() method ");
endtask

virtual task wait_for_end();
super.wait_for_end();
`vmm_note(this.log,"Start of wait_for_end() method ");
repeat(1000) @(input_intf.clock);
`vmm_note(this.log,"End of wait_for_end() method ");
endtask

virtual task stop();
super.stop();
`vmm_note(this.log,"Start of stop() method ");
atomic_gen.stop_xactor();
drvr.stop_xactor();
rcvr[0].stop_xactor();
rcvr[1].stop_xactor();
rcvr[2].stop_xactor();
rcvr[3].stop_xactor();

sb.stop_xactor();

`vmm_note(this.log,"End of stop() method ");
endtask

virtual task cleanup();
super.cleanup();
`vmm_note(this.log,"Start of cleanup() method ");
`vmm_note(this.log,"End of cleanup() method ");
endtask

virtual task report();
`vmm_note(this.log,"Start of report() method \n\n\n");
$display("---------------------------------------------------------------------");
super.report();
$display("---------------------------------------------------------------------");
$display("\n\n");
`vmm_note(this.log,"End of report() method");
endtask

endclass
`endif


(S)Download the phase 8 score code:


vmm_switch_8.tar
Browse the code in vmm_switch_8.tar


(S)Run the simulation:
vcs -sverilog -f filelist -R -ntb_opts rvm

(S)Log File Report:

******************* Start of testcase ****************
Normal[NOTE] on Environemnt() at 0:
Created env object
Normal[NOTE] on Environemnt() at 0:
Start of gen_cfg() method
Normal[NOTE] on Environemnt() at 0:
End of gen_cfg() method
Normal[NOTE] on Environemnt() at 0:
Start of build() method
Normal[NOTE] on driver(Drvr) at 0:
Driver created
Normal[NOTE] on Receiver(Rcvr-0) at 0:
Receiver created
Normal[NOTE] on Receiver(Rcvr-1) at 0:
Receiver created
Normal[NOTE] on Receiver(Rcvr-2) at 0:
Receiver created
Normal[NOTE] on Receiver(Rcvr-3) at 0:
Receiver created
Normal[NOTE] on sb(Sb) at 0:
Scoreboard created
Normal[NOTE] on Environemnt() at 0:
End of build() method
Normal[NOTE] on Environemnt() at 0:
Start of reset_dut() method
Normal[NOTE] on Environemnt() at 60:
End of reset_dut() method
Normal[NOTE] on Environemnt() at 60:
Start of cfg_dut() method
Normal[NOTE] on Environemnt() at 90:
Port 0 Address 00
Normal[NOTE] on Environemnt() at 110:
Port 1 Address 11
Normal[NOTE] on Environemnt() at 130:
Port 2 Address 22
Normal[NOTE] on Environemnt() at 150:
Port 3 Address 33
Normal[NOTE] on Environemnt() at 170:
End of cfg_dut() method
Normal[NOTE] on Environemnt() at 170:
Start of start() method
Normal[NOTE] on Environemnt() at 170:
End of start() method
Normal[NOTE] on Environemnt() at 170:
Start of wait_for_end() method
Normal[NOTE] on driver(Drvr) at 170:
started main task
Normal[NOTE] on Receiver(Rcvr-0) at 170:
started main task
Normal[NOTE] on Receiver(Rcvr-1) at 170:
started main task
Normal[NOTE] on Receiver(Rcvr-2) at 170:
started main task
Normal[NOTE] on Receiver(Rcvr-3) at 170:
started main task
size 8 ****
Normal[NOTE] on Receiver(Rcvr-0) at 470:
Received a packet
rcvr packet #0.0.0
rcvr da:0x00
rcvr sa:0xac
rcvr length:0x05 (data.size=4)
rcvr data[0]:0xcb data[1]:0x7e data[2]:0x52 data[3]:0xa4
rcvr fcs:0x29

470 : Scorebooard : Scoreboard received a packet from receiver
size 9 ****
Normal[NOTE] on Receiver(Rcvr-1) at 710:
Received a packet
rcvr packet #0.0.0
rcvr da:0x11
rcvr sa:0xf3
rcvr length:0x06 (data.size=5)
rcvr data[0]:0xc4 data[1]:0xd5 .... data[3]:0xf3 data[4]:0x88
rcvr fcs:0x5b

size 6 ****
Normal[NOTE] on Receiver(Rcvr-3) at 890:
Received a packet
rcvr packet #0.0.0
rcvr da:0x33
rcvr sa:0x6b
rcvr length:0x03 (data.size=2)
rcvr data[0]:0x32 data[1]:0x27
rcvr fcs:0x1c

Normal[NOTE] on Environemnt() at 10170:
End of wait_for_end() method
Normal[NOTE] on Environemnt() at 10170:
Start of stop() method
Normal[NOTE] on Environemnt() at 10170:
End of stop() method
Normal[NOTE] on Environemnt() at 10170:
Start of cleanup() method
Normal[NOTE] on Environemnt() at 10170:
End of cleanup() method
Normal[NOTE] on Environemnt() at 10170:
Start of report() method



---------------------------------------------------------------------
Simulation PASSED on /./ (/./) at 10170 (0 warnings, 0 demoted errors & 0 demoted warnings)
---------------------------------------------------------------------



Normal[NOTE] on Environemnt() at 10170:
End of report() method
******************** End of testcase *****************


Index
Introduction
Specification
Verification Plan
Phase 1 Top
Phase 2 Environment
Phase 3 Reset
Phase 4 Packet
Phase 5 Generator
Phase 6 Driver
Phase 7 Receiver
Phase 8 Scoreboard
Phase 9 Coverage

Report a Bug or Comment on This section - Your input is what keeps Testbench.in improving with time!





<< PREVIOUS PAGE

TOP

NEXT PAGE >>

copyright 2007-2017 :: all rights reserved www.testbench.in::Disclaimer