IC数字前端设计开发10 (labs svtb-lab6b实验说明)

1 源码下载地址:

https://download.csdn.net/download/times_poem/10659354

书籍推荐:芯片验证漫游指南

2 整个实验文件划分为以下模块,以便分析。

3 代码分析

公用文件层

3.1 router_io.sv

default input #1ns output #1ns;

p175 采样偏移量,输出偏移量。

通过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 din;
    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: router_io
 

3.2 Packet.sv

按照rtl数据传输类型,定义packet的数据。

compare 用于scoreboard.sv

display 用于打印当前packet的数据信息

copy 用于Receiver.sv

`ifndef INC_PACKET_SV
`define INC_PACKET_SV
class Packet;
  rand bit[3:0] sa, da;         // random port selection
  rand logic[7:0] payload[$];    // random payload 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");
  extern virtual function bit compare(Packet pkt2cmp, ref string message);
  extern virtual function void display(string prefix = "NOTE");
  extern virtual function Packet copy();
endclass
function Packet::new(string name);
  this.name = name;
endfunction
function bit Packet::compare(Packet pkt2cmp, ref string message);
  if (payload.size() != pkt2cmp.payload.size()) begin
    message = "Payload Size Mismatch:\n";
    message = { message, $sformatf("payload.size() = %0d, pkt2cmp.payload.size() = %0d\n", payload.size(), pkt2cmp.payload.size()) };
    return(0);
  end
    if (payload == pkt2cmp.payload) ;
    else begin
      message = "Payload Content Mismatch:\n";
      message = { message, $sformatf("Packet Sent:  %p\nPkt Received: %p", payload, pkt2cmp.payload) };
      return(0);
    end
  message = "Successfully Compared";
  return(1);
endfunction
function void Packet::display(string prefix);
  $display("[%s]%t %s sa = %0d, da = %0d", prefix, $realtime, name, sa, da);
  foreach(payload[i])
    $display("[%s]%t %s payload[%0d] = %0d", prefix, $realtime, name, i, payload[i]);
endfunction
function Packet Packet::copy();
    Packet pkt_copy = new();
    pkt_copy.sa = this.sa;
    pkt_copy.da = this.da;
    pkt_copy.payload = this.payload;
    return(pkt_copy);
endfunction
 
`endif
 

顶层模块相关

3.3 router_test_top.sv

产生时钟

dump fsdb数据

实例化dut

`timescale 1ns/100ps
 
module router_test_top;
  parameter simulation_cycle = 100;
 
  bit SystemClock = 0;
 
  router_io top_io(SystemClock);
 
  test t(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
    $timeformat(-9, 1, "ns", 10);
    //$fsdbDumpvars;
    $fsdbDumpfile("novas.fsdb");
    $fsdbDumpvars(0,"router_test_top");
  end
 
  always begin
    #(simulation_cycle/2) SystemClock = ~SystemClock;
  end
 
endmodule
 

3.4 test.sv

声明Environment

实例化

program automatic test(router_io.TB rtr_io);
 
import router_test_pkg::*;
 
  Environment env;
 
  initial begin
 
    env = new("env", rtr_io);
 
    env.configure();
 
    run_for_n_packets = env.run_for_n_packets;
 
 
    env.run();
    
  end
 
 
endprogram: test
 

3.5 Environment.sv

semaphore的使用:各个组件间通信,访问公共变量,防止同时读写操作。

整个系统的核心组件。

class Environment;
  string name;
  rand int run_for_n_packets;    // number of packets to test
  virtual router_io.TB rtr_io;
 
 
  semaphore  sem[];        // prevent output port collision
  Driver     drvr[];    // driver objects
  Receiver   rcvr[];    // receiver objects
  Generator  gen[];        // generator objects
  Scoreboard sb;        // scoreboard object
 
  constraint valid {
      this.run_for_n_packets inside { [1500:2500] };
  }
 
  extern function new(string name = "Env", virtual router_io.TB rtr_io);
  extern virtual task run();
  extern virtual function void configure();
  extern virtual function void build();
  extern virtual task start();
  extern virtual task wait_for_end();
  extern virtual task reset();
 
endclass: Environment
 
function Environment::new(string name = "Env", virtual router_io.TB rtr_io);
  if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, name);
  this.name = name;
  this.rtr_io = rtr_io;
endfunction: new
 
task Environment::run();
  if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);
  this.build();
  this.reset();
  this.start();
  this.wait_for_end();
endtask: run
 
function void Environment::configure();
    if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);
    this.randomize();
endfunction: configure
    
function void Environment::build();
    if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);
    if(this.run_for_n_packets == 0) this.run_for_n_packets = 2000;
    this.sem = new[16];
    this.drvr = new[16];
    this.rcvr = new[16];
    this.gen = new[16];
    this.sb = new();
    foreach (this.sem[i])
      this.sem[i] = new(1);
    foreach (this.gen[i])
      this.gen[i] = new($sformatf("gen[%0d]", i), i);
    foreach (this.drvr[i])
      this.drvr[i] = new($sformatf("drvr[%0d]", i), i, this.sem, this.gen[i].out_box, this.sb.driver_mbox, this.rtr_io);
    foreach (this.rcvr[i])
      this.rcvr[i] = new($sformatf("rcvr[%0d]", i), i, this.sb.receiver_mbox, this.rtr_io);
endfunction: build
 
task Environment::reset();
  if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);
  this.rtr_io.reset_n <= 1'b0;
  this.rtr_io.cb.frame_n <= '1;
  this.rtr_io.cb.valid_n <= '1;
  repeat(2) @this.rtr_io.cb;
  this.rtr_io.cb.reset_n <= 1'b1;
  repeat(15) @(this.rtr_io.cb);
endtask: reset
 
task Environment::start();
    if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);
    this.sb.start();
    foreach(this.gen[i])
      this.gen[i].start();
    foreach(this.drvr[i])
      this.drvr[i].start();
    foreach(this.rcvr[i])
      this.rcvr[i].start();
endtask: start
 
task Environment::wait_for_end();
    if (TRACE_ON) $display("[TRACE]%t %s:%m", $realtime, this.name);
    wait(this.sb.DONE.triggered);
endtask: wait_for_end
 

Driver层

3.6 Generator.sv

3.7 Driver.sv

3.8 DriverBase.sv

Monitor层

3.9 Receiver.sv

3.10 ReceiverBase.sv

DUT层

router.v

 
————————————————
版权声明:本文为CSDN博主「Times_poem」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Times_poem/article/details/82626242

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值