SV验证-1建立顶层文件
本文采用system verilog语言对一个router.v模块进行验证。参考文档为Synopsys公司2012年出版的《SystemVerilog Testbench Lab Guide》
1、router_test_top顶层文件
一个验证环境基本组件如下,包含验证测试test文件、待验证DUT文件及接口io信号。该顶层文件中例化一个router_io接口,和test、router两个模块,并将添加了时钟激励的接口连接两个模块。
module router_test_top;
parameter simulation_cycle = 100;
bit SystemClock = 0;
router_io top_io(SystemClock); //例化一个接口
test t(top_io); //将接口与test模块连接
router dut( //将接口与router模块连接
.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)
);
always begin
#(simulation_cycle/2) SystemClock = ~SystemClock;
end
endmodule
2、DUT简介:
该DUT的功能是实现信号的路由转发,路由器由16路输入端口和16路输出端口,每路端口由serial data、frame和valid这三种信号组成,信号数据类型为bit-vevtor类型。为了驱动某个端口,必须指定端口号,比如要驱动输入端口0,则指定din[0]、frame_n[0]、valid_n[0]即可
输入包数据结构:
- frame_n:信号上升沿表示第一个比特开始传输,信号下降沿表示最后一比特传输结束。
- din:包头信息(目的地址和打拍时间数)和有效数据信息;
- valid_n:数据信息有效则该信号为低,反之亦然。
复位信号:
- reset_n:低电平有效,复位后需等待15个时钟上升沿才能发送数据。
3、建立接口文件
在激励发生之前,采用接口(interface)进行stimulator与DUT的连接。只要同interface的接口类型一致,多个模块都可以使用这个interface,将其与interface连接不需要担心信号的驱动方向、连接性问题。所以interface不但可以方便多个模块之间的连接,也能将DUT同testbanch的连接隔离开。
- 连接信号(可实现多束信号、可重用)
- 能设置方向(modports)
- 能设置时间信息(clocking blocks)
- 能实现一定功能(initial/always blocks)
router_io.sv文件中先申明一个由时钟上升沿驱动的时钟块信号,再添加到modport中,用来同步驱动信号和采样。
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); #申明信号方向,cb是同步信号,reset_n是非同步信号
endinterface: router_io
4、创建test.sv文件
在此文件中申明一个测试代码块用来连接接口信号中的TB modport。其组建分布如下图,后面会逐渐讲解每个组建。
program automatic test(router_io.TB rtr_io);
`include "Packet.sv"
int run_for_n_packets; // number of packets to test
int TRACE_ON = 0;
`include "router_test.h"
`include "Driver.sv"
`include "Receiver.sv"
`include "Generator.sv"
`include "Scoreboard.sv"
semaphore sem[]; // prevent output port collision
Driver drvr[];
Receiver rcvr[]; // receiver
Generator gen[]; // generator
Scoreboard sb; // scoreboard
initial begin
run_for_n_packets = 2000;//发包数量
sem = new[16];//类的申明
drvr = new[16];
rcvr = new[16];
gen = new[16];
sb = new("Scoreboard");
//类的初始化
foreach (sem[i]) sem[i] = new(1);
foreach (gen[i]) gen[i] = new($sformatf("gen[%0d]", i), i);
foreach (drvr[i])
drvr[i] = new($sformatf("drvr[%0d]", i), i, sem, gen[i].out_box, sb.driver_mbox,rtr_io);
foreach (rcvr[i])
rcvr[i] = new($sformatf("rcvr[%0d]", i), i, sb.receiver_mbox, rtr_io);
reset();
sb.start();//开始
foreach (gen[i]) gen[i].start();
foreach (drvr[i]) drvr[i].start();
foreach (rcvr[i]) rcvr[i].start();
wait(sb.DONE.triggered);
end
task reset(); //复位任务,低电平有效,复位后等待15个时钟周期
rtr_io.reset_n = 1'b0;
rtr_io.cb.frame_n <= '1;
rtr_io.cb.valid_n <= '1;
repeat(2) @rtr_io.cb;
rtr_io.cb.reset_n <= 1'b1;
repeat(15) @(rtr_io.cb);
endtask: reset
endprogram: test