怎样写testbench写法

& & &想要开始学testbench的主要原因之一是之前一直做的都是比较容易上板验证的东西,但我发现一旦牵扯到图像处理啊、信号处理之类的,不是很好能验证(需要在板子上加入各种信号信号啊或一些抽象的数据),所以开始学一下仿真。
& & &所以这里不得不提到仿真中数据的读入和写出,读入:比如说一个灰度图像,写:一个处理过的图像,如果在板子上验证一个图像的处理,首先得要有图像(摄像头啊、flash里烧一个啊等等),还要看得到或能了解输出的图像(得要显示器或其他显示方法),这样对于算法级别的验证实在是绕远路。
& & 在verilog中可以使用$readmemb进行数据的读入,¥fdisplay进行写数据到文件中,这两个的使用方法我是参考这篇博客,十分简洁清楚:
/iqstudy/articles/1853552.html
& & 代码:
& & 读入数据到mem中,并把它们写入到另一个txt中:
module read_tb(
& & reg[3:0] mem[15:0];
& & initial
& & fid = $fopen(&D:/Xilinx/Vivado/2013.4/examples/Vivado_Tutorial/Projects/read/read.srcs/sim_1/new/memout.txt&,&w&);
& & initial
& & $readmemb(&D:/Xilinx/Vivado/2013.4/examples/Vivado_Tutorial/Projects/read/read.srcs/sim_1/new/mem.txt&,mem);
& & initial
& & begin: app
& & reg[4:0]
& & for(addr = 0;addr&16;addr=addr+1)
& & & & #10 $display(&mem[%d] = %d&,addr,mem[addr]);
& & & & #10 $fdisplay(fid,&b&,mem[addr]);
& & #10 $fclose(fid);
跟c语言差不多,如果输出写$fdisplay(fid,&4b&,mem[addr]);,会出现这种鬼:
不是很清楚该如何控制输出的位数~
还有一定别忘了fclose,刚开始怎么也写不进文件中,结果是忘写fclose了,晕。
通过matlab将一些信号数值化存在txt中,然后通过处理完后再通过matlab显示,这样就能做很多事情了!!~~!!
旗下网站:
与非门科技(北京)有限公司 All Rights Reserved.
京ICP证:070212号
北京市公安局备案编号: 京ICP备:号(转)如何编写testbench的总结(非常实用的总结) - 撒萌萌 - 博客园
全文地址:
如何编写testbench的总结(非常实用的总结)
1.激励的设置
相应于被测试模块的输入激励设置为reg型,输出相应设置为wire类型,双向端口inout在测试中需要进行处理。
方法1:为双向端口设置中间变量inout_reg作为该inout的输出寄存,inout口在testbench中要定义为wire型变量,然后用输出使能控制传输方向。
inout [0:0]bi_dir_
wire[0:0]bi_dir_
reg[0:0]bi_dir_port_
regbi_dir_port_
assign bi_dir_port=bi_dir_port_oe?bi_dir_port_reg:1'
用bi_dir_port_oe控制端口数据方向,并利用中间变量寄存器改变其值。等于两个模块之间用inout双向口互连。往端口写(就是往模块里面输入)
方法2:使用force和release语句,这种方法不能准确反映双向端口的信号变化,但这种方法可以反映块内信号的变化。具体如示:
module test();
wire data_
force data_inout=1'//强制作为输入端口
...............
release data_//释放输入端口
从文本文件中读取和写入向量
1)读取文本文件:用 $readmemb系统任务从文本文件中读取二进制向量(可以包含输入激励和输出期望值)。$readmemh 用于读取十六进制文件。例如:
reg[7:0]mem[1:256]//a 8-bit, 256-word 定义存储器mem
initial$readmemh ( "mem.data", mem ) // 将.dat文件读入寄存器mem中
initial$readmemh ( "mem.data", mem, 128, 1 ) // 参数为寄存器加载数据的地址始终
2)输出文本文件:打开输出文件用?$fopen 例如:
integer out_// out_file 是一个文件描述,需要定义为 integer类型
out_file = $fopen ( " cpu.data " ); // cpu.data 是需要打开的文件,也就是最终的输出文本
设计中的信号值可以通过$fmonitor, $fdisplay,
2. Verilog和Ncverilog命令使用库文件或库目录ex). ncverilog -f run.f -v lib/lib.v -y lib2 +libext+.v //一般编译文件在run.f中, 库文件在lib.v中,lib2目录中的.v文件系统自动搜索使用库文件或库目录,只编译需要的模块而不必全部编译
3.Verilog Testbench信号记录的系统任务:
1). SHM数据库可以记录在设计仿真过程中信号的变化. 它只在probes有效的时间内记录你set probe on的信号的变化.ex). $shm_open("waves.shm"); //打开波形数据库$shm_probe(top, "AS"); // set probe on "top",第二个参数: A -- signals of the specific scrope S -- Ports of the specified scope and below, excluding library cellsC -- Ports of the specified scope and below, including library cellsAS -- Signals of the specified scope and below, excluding library cellsAC -- Signals of the specified scope and below, including library cells还有一个 M ,表示当前scope的memories, 可以跟上面的结合使用, "AM" "AMS" "AMC"什么都不加表示当前scope的$shm_close //关闭数据库2). VCD数据库也可以记录在设计仿真过程中信号的变化. 它只记录你选择的信号的变化.ex). $dumpfile("filename"); //打开数据库$dumpvars(1, top.u1); //scope = top.u1, depth = 1第一个参数表示深度, 为0时记录所有深度; 第二个参数表示scope,省略时表当前的scope.$ //depth = all scope = all$dumpvars(0); //depth = all scope = current$dumpvars(1, top.u1); //depth = 1 scope = top.u1$dumpoff //暂停记录数据改变,信号变化不写入库文件中$dumpon //重新恢复记录3). 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_PLIPtrfsdb数据库文件的记录方法,是使用$fsdbDumpfile和$fsdbDumpvars系统函数,使用方法参见VCD注意: 在用ncverilog的时候,为了正确地记录波形,要使用参数: "+access+rw", 否则没有读写权限
在记录信号或者波形时需要指出被记录信号的路径,如:tb.module.u1.clk.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
关于信号记录的系统任务的说明:
在testbench中使用信号记录的系统任务,就可以将自己需要的部分的结果以及波形文件记录下来(可采用sigalscan工具查看),适用于对较大的系统进行仿真,速度快,优于全局仿真。使用简单,在testbench中添加:initial begin
$shm_open("waves.shm");
$shm_probe("要记录信号的路径&,&AS&);
$shm_ 即可。
4. ncverilog编译的顺序: ncverilog file1 file2 ....有时候这些文件存在依存关系,如在file2中要用到在file1中定义的变量,这时候就要注意其编译的顺序是从后到前,就先编译file2然后才是file2.5. 信号的强制赋值force首先, force语句只能在过程语句中出现,即要在initial 或者 always 中间. 去除force 用 release 语句.initial begin force sig1 = 1'b1; ... ; release sig1; endforce可以对wire赋值,这时整个net都被赋值; 也可以对reg赋值.
6.加载测试向量时,避免在时钟的上下沿变化
为了模拟真实器件的行为,加载测试向量时,避免在时钟的上下沿变化,而是在时钟的上升沿延时一个时间单位后,加载的测试向量发生变化。如:
assign #5 c=a^b
@(posedge clk)#(0.1*`cycle)A=1;
******************************************************************************
//testbench的波形输出
$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之下所有层的所有数据信号
//产生随机数,seed是种子
$random(seed);
ex: din &= $random(20);
//仿真时间,为unsigned型的64位数据
timecondition_happen_
condition_happen_time = $
$monitor($time,"data output = %d", dout);
parameterpara1 = 10,
para2 = 20,
para3 = 30;
//显示任务
$display();
//监视任务
$monitor();
//延迟模型
//describ pin-to-pin delay
endspecify
module nand_or(Y,A,B,C);
input A,B,C;
AND2 #0.2 (N,A,B);
OR2#0.1 (Y,C,N);
(A*-&Y) = 0.2;
(B*-&Y) = 0.3;
(C*-&Y) = 0.1;
endspecify
//时间刻度
`timescale单位时间/时间精确度
1.打开文件
integer file_
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_
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调整延迟参数
//generate语句,在Verilog-2001中定义.用于表达重复性动作
//必须事先声明genvar类型变量作为generate循环的指标
generate for(i = 0; i & 4; i = i + 1)
assign = din[i] = i % 2;
endgenerate
//资源共享
always @(A or B or C or D)
sum = sel ? (A+B):(C+D);
//上面例子使用两个加法器和一个MUX,面积大
//下面例子使用一个加法器和两个MUX,面积小
always @(A or B or C or D)
tmp1 = sel ? A:C;
tmp2 = sel ? B:D;
always @(tmp1 or tmp2)
sum = tmp1 + tmp2;
******************************************************************************
//定义一个没有输入输出的module
reg &&//将DUT的输入定义为reg类型
wire&&//将DUT的输出定义为wire类型
//在这里例化DUT
&&//在这里添加激励(可以有多个这样的结构)
always&&//通常在这里定义时钟信号
//在这里添加比较语句(可选)
//在这里添加输出语句(在屏幕上显示仿真结果)
一下介绍一些书写Testbench的技巧:
1.如果激励中有一些重复的项目,可以考虑将这些语句编写成一个task,这样会给书写和仿真带来很大方便。例如,一个存储器的testbench的激励可以包含write,read等task。
2.如果DUT中包含双向信号(inout),在编写testbench时要注意。需要一个reg变量来表示其输入,还需要一个wire变量表示其输出。
3.如果initial块语句过于复杂,可以考虑将其分为互补相干的几个部分,用数个initial块来描述。在仿真时,这些initial块会并发运行。这样方便阅读和修改。
4.每个testbench都最好包含$stop语句,用以指明仿真何时结束。
最后提供一个简单的示例(转自Xilinx文档):
module shift_reg (clock, reset, load, sel, data, shiftreg);
input [1:0]
input [4:0]
output [4:0]
always @ (posedge clock)
if (reset)
shiftreg = 0;
else if (load)
shiftreg =
case (sel)
2&b00 : shiftreg =
2&b01 : shiftreg = shiftreg && 1;
2&b10 : shiftreg = shiftreg && 1;
default : shiftreg =
Testbench:
// declare testbench name
// declaration of signals
wire [4:0]
// 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 = ~
initial begin// this process block specifies the stimulus.
reset = 1;
data = 5&b00000;
sel = 2&b00;
reset = 0;
data = 5&b00001;
sel = 2&b01;
sel = 2&b10;
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);如何写好Testbench
如何写好Testbench
FPGATestbench&&
FPGAVerilog HDL
Writing Efficient
TestbenchesMujtaba HamidXAPP199 (v1.0) June 11, 2001
TESTBENCHESJanick BergeronQualis Design Corporation
(Design Under
TestbenchVerilog VHDLC
DUTinputregDUToutputwireDUTinoutwire
`timescale 1ns/1ns
testbench_
reg&&&&&&&&&&&&
reg&&&&&&&&&&&&
reg [7:0] &
reg [7:0] &
reg [8:0] &&&&&&
always #5 clk =
#20 rst&&&&&&
#40 rst&&&&&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
adder adder_isr(.clk(clk),
.rst(rst), .a(a), .b(b), .r(r));
封装重复使用的功能单元
Testbenchtask
input [80*8:1]&&&
&&&&&&&&&&&&&&&&&&
$display ("-ERROR- at %t:%s", $time, msg);
结构化的Testbench
Testbench4
taskinitialinitialtask
双向IO的测试
DUTinoutTestbench
reg &&&&&&&&&&
[1:0] data_
wire& [1:0]
wire& [1:0]
bidir_infer uut (
&&&&&&&&&&&&&&&&&&
.data(datat), &&&&&&&&&&&&&&&
// datainout
&&&&&&&&&&&&&&&&&&
.rw(read_writet));
assign datat&&&&&&&&
= (read_writet == 1) ? data_in : 2’bZ;
assign data_out&& =
(read_writet == 0) ? datat : 2’bZ;
initial begin
&&&&&&&&&&&&&&&&&&
read_writet = 1;
&&&&&&&&&&&&&&&&&&
data_in = 11;&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
#50 read_writet = 0;&&&
测试中常用到的系统命令
$display,$write,$monitor
initial $display(“%t”,
$display”\n”
$monitor("%h",data_out);
$readmemb,$readmemh
[7:0]&&&&&&&&&
mem[19:0];
$readmemh(“data.txt”,
tabform-feeds//Verilog-27.5
$fdisplay,$fwrite,$fmonitor$display,$write,$monitor
EXPdata_outdata_out.txt
integer w_
initial w_file =
$fopen("data_out.txt");
always @(i)
$fdisplay(w_file,"%h",data_out);
if(i == 8'd255)&&&
&&&&&&&&&&&&&&&&&&
$fclose(w_file);
&&&&&&&&&&&&&&&&&&
代码的顺/并执行
变量的生命周期
Verilogbegin endC{}begin endbegin endinitialalwaysbegin endalwaysEXP1EXP2
always begin
for (i=0; i&32; i++)&&&&
always begin
for (i=0; i&32; i++)&&&&
begin:BLOCK_1
for (i=0; i&32; i++)&&&&
begin:BLOCK_2
for (i=0; i&32; i++)&&&&
EXP1ialwaysEXP2ialways
VerilogalwaysTestbenchPCalwaysEXP1EXP2
`timescale 1ns/1ns
module tb_rw_
parameter CLK_PERIOD&&&&
reg&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
forever #(CLK_PERIOD/2) clk = ~
&&&&&&&&&&&&&&&&&&
count = 0;
&&&&&&&&&&&&&&&&&&
// always_1
always @ (posedge clk)
&&&&&&&&&&&&&&&&&&
count = count + 1;&&&&&
// always_2
always @ (posedge clk)
&&&&&&&&&&&&&&&&&&
$display ("Count is ", count);
`timescale 1ns/1ns
module tb_rw_
parameter CLK_PERIOD&&&&
reg&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
forever #(CLK_PERIOD/2) clk = ~
&&&&&&&&&&&&&&&&&&
count = 0;
&&&&&&&&&&&&&&&&&&
// always_1
always @ (posedge clk)
&&&&&&&&&&&&&&&&&&
count &= count + 1;
// always_2
always @ (posedge clk)
&&&&&&&&&&&&&&&&&&
$display ("Count is ", count);
EXP1alwaysEXP20,1,2…9always_1countalways_2count1
防止同时调用同一个task
#100 write(8'h5A,8'h34);
#100 write(8'h5B,8'h43);
EXP1writeEXP2
input [7:0]
input [7:0]
reg&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
if (in_use == 1'b1)&&&&&&
&&&&&&&&&&&&&&&&&&
in_use&&&&&&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&
in_use&&&&&&&
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Quartus13+Modelsim仿真testbench应该怎么写呢?菜鸟已经吐血了 - FPGA|CPLD|ASIC论坛 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
Quartus13+Modelsim仿真testbench应该怎么写呢?菜鸟已经吐血了
14:11:42  
在Quartus中写了一个非常简单的分频器module testdiv(mclk, out),编译OK,quartus生成testbench模板如下,在always块加入时钟产生语句,out=~如下
`timescale 1 ps/ 1 ps
module testdiv_vlg_tst();
// constants& && && && && && && && && && && && && && &
// general purpose registers
// test vector input registers
// wires& && && && && && && && && && && && && && && &&&
// assign statements (if any)& && && && && && && && &&&
testdiv i1 (
// port map - connection between master ports and signals/registers& &
& & & & .mclk(mclk),
& & & & .out(out)
);
initial& && && && && && && && && && && && && && && && &
begin& && && && && && && && && && && && && && && && &&&
// code that executes only once& && && && && && && && &
// insert code here --& begin& && && && && && && && &&&
& && && && && && && && && && && && && && && && && && &
// --& end& && && && && && && && && && && && && && && &
$display(&Running testbench&);& && && && && && && &&&
end& && && && && && && && && && && && && && && && && &
always& && && && && && && && && && && && && && && && &
// optional sensitivity list& && && && && && && && && &
// @(event1 or event2 or .... eventn)& && && && && && &
begin& && && && && && && && && && && && && && && && &&&
// code executes for every event on sensitivity list& &
// insert code here --& begin& && && && && && && && &&&
&font color=&Red&&# 10 mclk=~mclk& &;& && && && && && && && && && && && && && && && && &&/font&
@& && && && && && && && && && && && && && && &
// --& end& && && && && && && && && && && && && && && &
end& && && && && && && && && && && && && && && && && &
复制代码然后添加testbench,点击RTL Simulation调用Modlesim仿真,结果不出来波形啊,如下图:
QQ截图09.png (117.35 KB, 下载次数: 0)
14:09 上传
才接触Modlesim,折腾好久了,真心不知道该怎么搞了,求大大们拯救啊
21:11:28  
在initial块里添加了mclk的初始化语句,mclk=0,然后mclk可以显示波形了,但是输出仍然没有波形,该怎么办,大大们,求解救
21:16:13  
大大们不给力啊,问题原因找到了,reg没有初始化,所有的reg都要在initial里面初始化,不然modlesim就划定为未知状态而没有波形,代码不严谨啊,花一天买了一个教训
Powered byVHDL_Testbench Altera官方的 教程,想学怎么写 的话,强烈建议看 。(英文的 -FPGA-Verilog 238万源代码下载-
&文件名称: VHDL_Testbench
& & & & &&]
&&所属分类:
&&开发工具: VHDL
&&文件大小: 314 KB
&&上传时间:
&&下载次数: 214
&&提 供 者:
&详细说明:Altera官方的VHDL_Testbench教程,想学怎么写Testbench的话,强烈建议看一看。(英文的文档,不过都不难。耐心看完吧!)-Altera official VHDL_Testbench tutorial, want to learn how to write Testbench, then strongly recommended that a look. (English document, but are not difficult. The patience to read it!)
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&VHDL_Testbench.pdf
&近期下载过的用户:
&相关搜索:
&&&&&&&&&&
&输入关键字,在本站238万海量源码库中尽情搜索:
&[] - 交通灯,在CPLD的开发板上实现交通灯的程序
&[] - vhdl实现RS232串口通信,压缩包内有完整的quartus2工程,由顶层,波特率,发送,接收四个模块构成。外部电路只需要一片MAX232就能与串口助手或单片机通信。
&[] - FPGA时序设计时必备的软件。可以有效的提高逻辑设计的速度,调整设计时的时序。
&[] - crc校验的vhdl验证,模块分为编码组帧解帧解码模块
&[] - 这是一个Modelsim的教程,包括Modelsim6.0及其使用的教程介绍
&[] - 这是讲述如何编写testbench的,我认为很经典的。值得一看
&[] - modelsim破解工具
安装modelsim后运行它即可破解
&[] - IC验证,一本不可多得的好书,讲的非常全面。
&[] - 多功能数字钟,、在quartus 2环境中编译通过;
4、仿真通过并得到正确的波形;
5、给出相应的设计报告}

我要回帖

更多关于 vhdl写testbench 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信