SV Verification - 3Scoreboard

SV Verification - 3Scoreboad Verification Results

​ This article uses the system verilog language to verify a router.v module. The reference document is "SystemVerilog Testbench Lab Guide" published by Synopsys in 2012

The top-level file is shown in the figure below. The components in this section are all called in the file.

1. Scoreboard class

​ Create a new check class to compare input and output packets. The main function of the check class is to use mailbox es to communicate between Drivers and Recivers. A new covergroup method is added to this class. Use the covergroup function to verify how many packets need to be sent to the router in order to test all input and output ports. Add functional verification to the Scoreboard to verify the testbanch process and test all input and output combined ports. End the simulation when finished.

class Scoreboard;
  string   name;            // unique identifier
  event    DONE;            // flag to indicate goal reached
  Packet   refPkt[$];       // reference Packet array
  Packet   pkt2send;        // Packet object from Drivers
  Packet   pkt2cmp;         // Packet object from Receivers
  pkt_mbox  driver_mbox;    // mailbox for Packet objects from Drivers
  pkt_mbox  receiver_mbox;  // mailbox for Packet objects from Receivers

  bit[3:0] sa, da; // functional coverage properties

  covergroup router_cov;
    coverpoint sa;
    coverpoint da;
    cross sa, da; 

  extern function new(string name = "Scoreboard", pkt_mbox driver_mbox = null, receiver_mbox = null);
  extern virtual task start();
  extern virtual function void check();
endclass: Scoreboard

​ In the start() task, when a Packet package is found from receiver_mbox, the package will be assigned to pkt2cmp. Then wrap everything in driver_mbox into the refPkt[$] queue. Then in check(), the pkt2cmp packet is compared with the output port reference packet in refPkt specified by da in the packet, and if no reference packet is found in refPkt, an error message is printed.

function Scoreboard::new(string name, pkt_mbox driver_mbox, receiver_mbox);
  if (TRACE_ON) $display("[TRACE]%0t %s:%m", $time, name); = name;
  if (driver_mbox == null) driver_mbox = new();
  	this.driver_mbox = driver_mbox;
  if (receiver_mbox == null) receiver_mbox = new();
  	this.receiver_mbox = receiver_mbox;
  router_cov = new();
endfunction: new

task Scoreboard::start();
  if (TRACE_ON) $display("[TRACE]%0t %s:%m", $time, name);
    forever begin
      while (driver_mbox.num()) begin
        Packet pkt;
endtask: start

​ In the check() task, use the real variable coverage_result to save the verification coverage result, use the compare() method to compare the data of the received and sent packets, and use the display() method to print debugging information.

​ In the start() task driver_mbox, all packages are assigned to refPkt[ ] team List back , Find arrive r e f P k t [ ] queue, find refPkt[ ] queue, find the starting data in refPkt[] and assign it to pkt2send, and then compare the pkt2cmp with the pkt2cmp package. Then assign the variables sa and da in the pkt2cmp package to the class variables, and trigger the router_cov.sample() function verification function. Finally, use $get_coverage () to get the verification coverage. When the number of received packets reaches the value of the global variable run_for_n_packets or the verification coverage reaches 100%, the event signal DONE is triggered to stop the simulation.

function void Scoreboard::check();
  int    index[$];
  string message;
  static int  pkts_checked = 0;
  real coverage_result = 0.0;

  if (TRACE_ON) $display("[TRACE]%0t %s:%m", $time, name);
  index = refPkt.find_first_index() with (item.da == pkt2cmp.da);
  if (index.size() <= 0) begin
    $display("\n%m\n[ERROR]%0t %s not found in Reference Queue\n", $time,;
  pkt2send = refPkt[index[0]];
  if (!, message)) begin
    $display("\n%m\n[ERROR]%0t Packet #%0d %s\n", $time, pkts_checked, message);
  end =;
  this.da = pkt2send.da;
  coverage_result = $get_coverage();
  $display("[NOTE]%0t Packet #%0d %s Cvrg = %3.2f", $time, pkts_checked++, message, coverage_result);
  if ((pkts_checked >= run_for_n_packets) || ( coverage_result == 100.0))
endfunction: check

2. The result of running the code

​ At the beginning of the simulation, the reset() task will be executed first. It can be seen that 15 clock cycles after the reset_n signal is reset, frame_n will be pulled low, and only when frame_n pulls down the corresponding channel will its din have randomized data. .

​ Each channel will send three signals of address, beat, and data. As shown in the figure below, the signal corresponding to the first four clock cycles of the din[0] channel is 4'b1111, indicating that its output address is channel 15. Then, after waiting for four clock beats, it is found that the data of the dout[15] channel is consistent with the data of the din[0] channel.

​ The simulation results without adding functional verification, the packets sent 2000 times are verified correctly.

​ Add the simulation results of the verification function, and the verification ends automatically when the functional verification rate reaches 100%.

Tags: vim FPGA riscv

Posted by akforce on Sun, 13 Nov 2022 21:27:59 +0300