mafan88的个人空间 https://blog.eetop.cn/162539 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

testbench总结

已有 2197 次阅读| 2012-2-3 09:15 |个人分类:脚本

Verilog和Ncverilog命令使用库文件或库目录

ex). ncverilog -f run.f -v lib/lib.v -y lib2 +libext+.v //一般编译文件在run.f中, 库文件在lib.v中,lib2目录中的.v文件系统自动搜索使用库文件或库目录,只编译需要的模块而不必全部编译.
2). Debussy fsdb数据库也可以记录信号的变化,它的优势是可以跟debussy结合,方便调试.
如果要在ncverilog仿真时,记录信号, 首先要设置debussy:
a. setenv LD_LIBRARY_PATH :$LD_LIBRARY_PATH
(path for debpli.so file (/share/PLI/nc_xl//nc_loadpli1))
b. while invoking ncverilog use the +ncloadpli1 option.
ncverilog -f run.f +debug +ncloadpli1=debpli:deb_PLIPtr
fsdb数据库文件的记录方法,是使用$fsdbDumpfile和$fsdbDumpvars系统函数,使用方法参见VCD
注意: 在用ncverilog的时候,为了正确地记录波形,要使用参数: "+access+rw", 否则没有读写权限
在记录信号或者波形时需要指出被记录信号的路径,如:tb.module.u1.clk.
3)

ncverilog编译的顺序

ncverilog file1 file2 ....
有时候这些文件存在依存关系,如在file2中要用到在file1中定义的变量,这时候就要注意其编译的顺序是
从后到前,就先编译file1然后才是file2.

4

信号的强制赋值force

首先, force语句只能在过程语句中出现,即要在initial 或者 always 中间. 去除force 用 release 语句.
initial begin force sig1 = 1'b1; ... ; release sig1; end
force可以对wire赋值,这时整个net都被赋值; 也可以对reg赋值.

5

加载测试向量时,避免在时钟的上下沿变化

为了模拟真实器件的行为,加载测试向量时,避免在时钟的上下沿变化,而是在时钟的上升沿延时一个时间单位后,加载的测试向量发生变化。如:

assign #5 c=a^b
……
@(posedge clk) #(0.1*`cycle) A=1;

6

testbench的波形输出

module top;
...
initial
begin
$dumpfile("./top.vcd"); //存储波形的文件名和路径,一般是.vcd格式.
$dumpvars(1,top); //存储top这一层的所有信号数据
$dumpvars(2,top.u1); //存储top.u1之下两层的所有数据信号(包含top.u1这一层)
$dumpvars(3,top.u2); //存储top.u2之下三层的所有数据信号(包含top.u2这一层)
$dumpvars(0,top.u3); //存储top.u3之下所有层的所有数据信号
end
endmodule
7

产生随机数,seed是种子

$random(seed);
ex: din <= $random(20);

8

仿真时间

//仿真时间,为unsigned型的64位数据

$time
ex:
...
time condition_happen_time;
...
condition_happen_time = $time;
...
$monitor($time,"data utput = %d", dout);

9

参数

parameter para1 = 10,
para2 = 20,
para3 = 30;

延迟模型

specify
...
//describ pin-to-pin delay
endspecify

ex:

module nand_or(Y,A,B,C);
input A,B,C;
output Y;
AND2 #0.2 (N,A,B);
OR2 #0.1 (Y,C,N);
specify
(A*->Y) = 0.2;
(B*->Y) = 0.3;
(C*->Y) = 0.1;
endspecify
endmodule

文件I/O

1.打开文件

integer file_id;
file_id = fopen("file_path/file_name");

2.
写入文件

//$fmonitor
只要有变化就一直记录
$fmonitor(file_id, "%format_char", parameter);
eg:$fmonitor(file_id, "%m: %t in1=%d o1=%h", $time, in1, o1);
//$fwrite
需要触发条件才记录
$fwrite(file_id, "%format_char", parameter);
//$fdisplay
需要触发条件才记录
$fdisplay(file_id, "%format_char", parameter);
$fstrobe();

3.
读取文件

integer file_id;
file_id = $fread("file_path/file_name", "r");

4.
关闭文件
$fclose(fjile_id);

5.
由文件设定存储器初值
$readmemh("file_name", memory_name"); //
初始化数据为十六进制
$readmemb("file_name", memory_name"); //
初始化数据为二进制

仿真控制

$finish(parameter); //parameter = 0,1,2
$stop(parameter);

读入SDF文件

//
$sdf_annotate("sdf_file_name", module_instance, "scale_factors");
//module_instance: sdf
文件所对应的instance.
//scale_factors:
针对timming delay中的最小延时min,典型延迟typ,最大延时max调整延迟参数

一些书写Testbench的技巧

1.如果激励中有一些重复的项目,可以考虑将这些语句编写成一个task,这样会给书写和仿真带来很大方便。例如,一个存储器的testbench的激励可以包含writereadtask

2.
如果DUT中包含双向信号(inout),在编写testbench时要注意。需要一个reg变量来表示其输入,还需要一个wire变量表示其输出。

3.
如果initial块语句过于复杂,可以考虑将其分为互补相干的几个部分,用数个initial块来描述。在仿真时,这些initial块会并发运行。这样方便阅读和修改。

4.
每个testbench都最好包含$stop语句,用以指明仿真何时结束。

最后提供一个简单的示例(转自Xilinx文档)

DUT


module shift_reg (clock, reset, load, sel, data, shiftreg);

input clock;

input reset;

input load;

input [1:0] sel;

input [4:0] data;

output [4:0] shiftreg;

reg [4:0] shiftreg;

always @ (posedge clock)

begin

if (reset)

shiftreg = 0;

else if (load)

shiftreg = data;

else

case (sel)

2’b00 : shiftreg = shiftreg;

2’b01 : shiftreg = shiftreg << 1;

2’b10 : shiftreg = shiftreg >> 1;

default : shiftreg = shiftreg;

endcase

end

endmodule

Testbench


module testbench; // declare testbench name

reg clock;

reg load;

reg reset; // declaration of signals

wire [4:0] shiftreg;

reg [4:0] data;

reg [1:0] sel;

// instantiation of the shift_reg design below

shift_reg dut(.clock (clock),

.load (load),

.reset (reset),

.shiftreg (shiftreg),

.data (data),

.sel (sel));

//this process block sets up the free running clock

initial begin

clock = 0;

forever #50 clock = ~clock;

end

initial begin// this process block specifies the stimulus.

reset = 1;

data = 5’b00000;

load = 0;

sel = 2’b00;

#200

reset = 0;

load = 1;

#200

data = 5’b00001;

#100

sel = 2’b01;

load = 0;

#200

sel = 2’b10;

#1000 $stop;

end

initial begin// this process block pipes the ASCII results to the

//terminal or text editor

$timeformat(-9,1,"ns",12);

$display(" Time Clk Rst Ld SftRg Data Sel");

$monitor("%t %b %b %b %b %b %b", $realtime,

clock, reset, load, shiftreg, data, sel);

end

endmodule


》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》

testbench

在顶层调用设计内部层次信号,无需将信号从端口引出,可以使用verilog的层次化调用

wire [7:0]  data = test_top.dut.data ;



点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 6

    粉丝
  • 0

    好友
  • 15

    获赞
  • 6

    评论
  • 105786

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-5-26 00:41 , Processed in 0.016625 second(s), 7 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部