【无标题】

1、interface

interface router_io(input bit clock);
	logic				reset_n;
	logic [15:0]	din;
	logic	 [15:0]	frame_n;
	logic [15:0]	valid_n;
  	logic [15:0]	dout;
  	logic [15:0]	valido_n;
  	logic [15:0]	busy_n;
  	logic [15:0]	frameo_n;
clocking cb @(posedge clock);
	default input #1ns output #1ns;
	output	reset_n;
	output	frame_n;
	output	valid_n;
	input	dout;
	input	valido_n;
	input	frameo_n;
	input	busy_n;
endclocking:cb

modport TB(clocking cb,output reset_n );

endinterface

2、transaction(packet)

class packet;
	rand reg	[3:0]	sa,da;       // random port selection
  	rand reg[7:0] payload[$];	// random data array
    string   name;		             // unique identifier

  constraint Limit {
    sa inside {[0:15]};
    da inside {[0:15]};
    payload.size() inside {[2:4]};
  }

  extern function new(string name = "Packet");   //将所有的function和task都放到class外面完成
  extern function void pre_randomize();
  extern function bit compare(Packet pkt2cmp, ref string message);
  extern function void display(string prefix = "NOTE");
endclass

function Packet::new(string name);  //构造函数new
  this.name = name;
endfunction

function void Packet::pre_randomize();  
  this.payload.delete();
endfunction

function bit Packet::compare(Packet pkt2cmp, ref string message);
  if (payload.size() != pkt2cmp.payload.size()) begin
    message = "Payload Size Mismatch:\n";
    message = { message, $psprintf("payload.size() = %0d, pkt2cmp.payload.size() = %0d\n", payload.size(), pkt2cmp.payload.size()) };
    return(0);
  end
  foreach(payload[i]) begin
    if (payload[i] == pkt2cmp.payload[i]) ;
    else begin
      message = "Payload Content Mismatch:\n";
      foreach(payload[i])
        message = { message, $psprintf("payload[%0d] = %0d,\tpkt2cmp.payload[%0d] = %0d\n", i, payload[i], i, pkt2cmp.payload[i]) };
      return(0);
    end
  end
  message = "Successfully Compared";
  return(1);
endfunction

function void Packet::display(string prefix = "NOTE");
  $display("[%s]%0d %s sa = %0d, da = %0d", prefix, $time, name, sa, da);
  foreach(payload[i])
    $display("[%s]%0d %s payload[%0d] = %0d", prefix, $time, name, i, payload[i]);
endfunction

3、generator

class generator;
  string  name;		    // unique identifier
  Packet  pkt2send;	// stimulus Packet object
  mailbox out_box[];	// mailbox to Drivers

  extern function new(string name = "Generator");
  extern virtual task gen();
  extern virtual task start();
endclass

function Generator::new(string name);
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  this.name = name;
  this.pkt2send = new();
  this.out_box = new[16];
  foreach(this.out_box[i])
    	this.out_box[i] = new();
endfunction

task Generator::gen();
  static int pkts_generated = 0;
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  pkt2send.name = $psprintf("Packet[%0d]", pkts_generated++);
  if (!pkt2send.randomize()) begin
    $display("\n%m\n[ERROR]%0d Randomization Failed!\n", $time);
    $finish;
  end
endtask

task Generator::start();
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  fork
    for (int i=0; i<run_for_n_packets || run_for_n_packets <= 0; i++) begin
      gen();
      begin
        Packet pkt = new pkt2send;
        out_box[pkt.sa].put(pkt);
      end
    end
  join_none
endtask

4、driver(此处包含driverbase和driver)

class driverbase;
	virtual router_io.TB router;
	string	name;
	reg	[3:0]	sa,da;
	reg	[7:0]	payload[$];
	packet	pkt2send;

	extern function new(string name="driverbase",virtual router_io.TB router);
	  extern virtual task send();
  	 extern virtual task send_addrs();
  	 extern virtual task send_pad();
  	 extern virtual task send_payload();
endclass

function DriverBase::new(string name, virtual router_io.TB router);
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  this.name   = name;
  this.router = router;
endfunction

task DriverBase::send();
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  send_addrs();
  send_pad();
  send_payload();
endtask

task DriverBase::send_addrs();
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  router.cb.frame_n[sa] <= 1'b0;
  for(int i=0; i<4; i++) begin
    router.cb.din[sa] <= da[i];
    @(router.cb);
  end
endtask

task DriverBase::send_pad();
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  router.cb.din[sa] <= 1'b1;
  router.cb.valid_n[sa] <= 1'b1;
  repeat(5) @(router.cb);
endtask

task DriverBase::send_payload();
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  foreach(payload[index]) begin
    for(int i=0; i<8; i++) begin
      router.cb.din[sa] <= payload[index][i];
      router.cb.valid_n[sa] <= 1'b0;
      router.cb.frame_n[sa] <= ((index == (payload.size() - 1)) && (i == 7));
      @(router.cb);
    end
  end
  router.cb.valid_n[sa] <= 1'b1;
endtask
`include "DriverBase.sv"
class Driver extends DriverBase;
  mailbox in_box;	// Generator mailbox
  mailbox out_box;	// Scoreboard mailbox
  semaphore sem[];	// output port arbitration

  extern function new(string name = "Driver", int port_id, semaphore sem[], mailbox in_box, out_box, virtual router_io.TB router);
  extern virtual task start();
endclass

function Driver::new(string name, int port_id, semaphore sem[], mailbox in_box, out_box, virtual router_io.TB router);
  super.new(name, router);
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  this.sa = port_id;
  this.sem = sem;
  this.in_box = in_box;
  this.out_box = out_box;
endfunction

task Driver::start();
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  fork
    forever begin
      in_box.get(pkt2send);
      if (pkt2send.sa != this.sa) continue;
      this.da = pkt2send.da;
      this.payload = pkt2send.payload;
      sem[this.da].get(1);
      send();
      out_box.put(pkt2send);
      sem[this.da].put(1);
    end
  join_none
endtask

// Do not uncomment!
// The following is the prototype of the DriverBase class:
//
// class DriverBase;
//   virtual router_io.TB router;	// interface signal
//   string    name;			// unique identifier
//   reg[3:0]  sa, da;			// source and destination addresses
//   reg[7:0]  payload[$];		// Packet payload
//   Packet    pkt2send;		// stimulus Packet object
//
//   extern function new(string name = "DriverBase", virtual router_io.TB router);
//   extern virtual task send();
//   extern virtual task send_addrs();
//   extern virtual task send_pad();
//   extern virtual task send_payload();
// endclass

5、receiver(monitor)

class ReceiverBase;
  virtual router_io.TB router;	// interface signals
  string   name;		               // unique identifier
  reg[3:0] da;			               // output port to monitor
  reg[7:0] pkt2cmp_payload[$];	// actual payload array
  Packet   pkt2cmp;		               // actual Packet object

  extern function new(string name = "ReceiverBase", virtual router_io.TB router);
  extern virtual task recv();
  extern virtual task get_payload();
endclass

function ReceiverBase::new(string name, virtual router_io.TB router);
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  this.name = name;
  this.router = router;
  pkt2cmp = new();
endfunction

task ReceiverBase::recv();
  static int pkt_cnt = 0;
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  get_payload();
  pkt2cmp.da = da;
  pkt2cmp.payload = pkt2cmp_payload;
  pkt2cmp.name = $psprintf("rcvdPkt[%0d]", pkt_cnt++);
endtask

task ReceiverBase::get_payload();
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  pkt2cmp_payload.delete();
  fork: frameo_wd_timer
    @(negedge router.cb.frameo_n[da]);
    begin
      repeat(1000) @(router.cb);
      $display("\n%m\n[ERROR]%0d Frame signal timed out!\n", $time);
      $finish;
    end
  join_any: frameo_wd_timer
  disable fork;
  while (!router.cb.frameo_n[da]) begin
    reg[7:0] datum;
    for (int i=0; i<8; i=i ) begin
      if (!router.cb.valido_n[da])
        datum[i++] = router.cb.dout[da];
      if (router.cb.frameo_n[da] && (i != 8)) begin
        $display("\n%m\n[ERROR]%0d Packet payload not byte aligned!\n", $time);
        $finish;
      end
      @(router.cb);
    end
    pkt2cmp_payload.push_back(datum);
  end
endtask
`include "ReceiverBase.sv"
class Receiver extends ReceiverBase;
  mailbox out_box;	// Scoreboard mailbox

  extern function new(string name = "Receiver", int port_id, mailbox out_box, virtual router_io.TB router);
  extern virtual task start();
endclass

function Receiver::new(string name, int port_id, mailbox out_box, virtual router_io.TB router);
  super.new(name, router);
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  this.da = port_id;
  this.out_box = out_box;
endfunction

task Receiver::start();
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  fork
    forever begin
      recv();
      begin
        Packet pkt = new pkt2cmp;
        out_box.put(pkt);
      end
    end
  join_none
endtask

// Do not uncomment!
//
// class ReceiverBase;
//   virtual router_io.TB router;	// interface signals
//   string   name;			// unique identifier
//   reg[3:0] da;			// output port to monitor
//   reg[7:0] pkt2cmp_payload[$];	// actual payload array
//   Packet   pkt2cmp;			// actual Packet object
//
//   extern function new(string name = "ReceiverBase", virtual router_io.TB router);
//   extern virtual task recv();
//   extern virtual task get_payload();
// endclass

6、scoreboard

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
  mailbox  driver_mbox;		// mailbox for Packet objects from Drivers
  mailbox  receiver_mbox;	// mailbox fro Packet objects from Receivers
  bit[3:0] sa, da;		            // functional coverage properties

  covergroup router_cov;    //覆盖点
    coverpoint sa;
    coverpoint da;
    cross sa, da;
  endgroup

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

function Scoreboard::new(string name, mailbox driver_mbox, receiver_mbox);   //构造函数
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  this.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

task Scoreboard::start();         //task
  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  fork
    while (1) begin
      receiver_mbox.get(pkt2cmp);
      while (driver_mbox.num()) begin
        Packet pkt;
        driver_mbox.get(pkt);
        refPkt.push_back(pkt);
      end
      check();
    end
  join_none
endtask

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

  if (TRACE_ON) $display("[TRACE]%0d %s:%m", $time, name);
  index = refPkt.find_first_index() with (item.da == pkt2cmp.da);
  if (index.size() <= 0) begin
    $display("\n%m\n[ERROR]%0d %s not found in Reference Queue\n", $time, pkt2cmp.name);
    pkt2cmp.display("ERROR");
    $finish;
  end
  pkt2send = refPkt[index[0]];
  refPkt.delete(index[0]);
  if (!pkt2send.compare(pkt2cmp, message)) begin
    $display("\n%m\n[ERROR]%0d Packet #%0d %s\n", $time, pkts_checked, message);
    pkt2send.display("ERROR");
    pkt2cmp.display("ERROR");
    $finish;
  end
  this.sa = pkt2send.sa;
  this.da = pkt2send.da;
  router_cov.sample();
  coverage_result = $get_coverage();
  $display("[NOTE]%0d Packet #%0d %s coverage = %0d", $time, pkts_checked++, message, coverage_result);
  if ((pkts_checked >= run_for_n_packets) || (coverage_result == 100))
    ->DONE;
endtask

7、top

module router_test_top;
  parameter simulation_cycle = 100;

  reg  SystemClock;
  router_io top_io(SystemClock);
  router_test test(top_io);
  router dut(
    .reset_n	(top_io.reset_n),
    .clock	(top_io.clock),
    .din	(top_io.din),
    .frame_n	(top_io.frame_n),
    .valid_n	(top_io.valid_n),
    .dout	(top_io.dout),
    .valido_n	(top_io.valido_n),
    .busy_n	(top_io.busy_n),
    .frameo_n	(top_io.frameo_n)
  );

  initial begin
    SystemClock = 0;
    forever begin
      #(simulation_cycle/2)
        SystemClock = ~SystemClock;
    end
  end

8、test

program automatic router_test(router_io.TB router);
int run_for_n_packets;		// number of packets to test
int TRACE_ON;			       // subroutine tracing control
`include "Packet.sv"
`include "Driver.sv"
`include "Receiver.sv"
`include "Generator.sv"
`include "Scoreboard.sv"

  semaphore  sem[];		// prevent output port collision
  Driver     drvr[];		// driver objects
  Receiver   rcvr[];		// receiver objects
  Generator  gen;		// generator object
  Scoreboard sb;		// scoreboard object

  initial begin
    $vcdpluson;
    run_for_n_packets = 3000;
    TRACE_ON = 0;
    sem = new[16];
    drvr = new[16];
    rcvr = new[16];
    gen = new();
    sb = new();
    foreach (sem[i])
      sem[i] = new(1);
    for (int i=0; i<drvr.size(); i++)
      drvr[i] = new($psprintf("drvr[%0d]", i), i, sem, gen.out_box[i], sb.driver_mbox, router);
    for (int i=0; i<rcvr.size(); i++)
      rcvr[i] = new($psprintf("rcvr[%0d]", i), i, sb.receiver_mbox, router);
    reset();
    gen.start();
    sb.start();
    foreach(drvr[i])
      drvr[i].start();
    foreach(rcvr[i])
      rcvr[i].start();
    wait(sb.DONE.triggered);
  end

  task reset();
    if (TRACE_ON) $display("[TRACE]%0d %m", $time);
    router.reset_n <= 1'b0;
    router.cb.frame_n <= '1;
    router.cb.valid_n <= '1;
    ##2 router.cb.reset_n <= 1'b1;
    repeat(15) @(router.cb);
  endtask

endprogram
program automatic test();
  int a;
  string message;

  initial begin
    $vcdpluson;
    message = "SUCCESS!";
    $display(message);
    a = 0;
    $display(a);
  end
endprogram
module dut;
  int a, b=0;
  initial begin
    a = b;
  end
endmodule
module dut_dut;
  dut d1;
  test t1;
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值