Testbench
作者:桂。
时间:2017-08-15 07:11:50
链接:http://www.cnblogs.com/xingshansi/p/7363048.html
前言
Testbench主要用于module的测试,这里仅记录一般的操作流程。
〇、verilog与C的区别
RTL级的verilog其实就是常说的verilog语言中可综合的那部分,它是verilog语言的一个子集。所谓的RTL级建模,其实也就是用verilog语言去描述实际电路的行为,比如用verilog语言去描述一个ram或者是一个移位寄存器。
对于这个层次上的建模,最重要的思想就是“硬件意识”,也就是说,我们在写代码的时候,大脑里要先知道我们设计的是什么样的电路,然后再用verilog语言将它描述出来。其实,在出现硬件描述语言之前,电路设计都是用原理图去搭的,这种设计过程也是我们心中先有了电路,然后用一种计算机能够识别的方式进行描述,现在的verilog HDL只是相当于我们有了更先进的描述方法,但是在RTL级的设计过程还是不变----心中先有电路,再将它翻译成verilog代码。
刚才我们说了,RTL的设计其实就是用verilog去描述电路的行为,那么,我们要怎么去理解这个“电路的行为”呢?
第一,电路在物理上是并行工作的。
我们知道,在写C程序的时候,由于CPU在任一时刻最多只能执行一条指令,程序都是顺序执行的,即使是我们平时说的多任务操作系统,所谓的并行任务也只是从宏观上来说的(人感觉不到而已),但从微观上来说它仍然是顺序执行的。所以我们设计C程序时思维是串行或者说是并行的。所以看语言不能从上往下看调用逻辑,而是要抓住数据的流向,各个In/out的调用顺序。
但是数字电路设计则不然,数字电路芯片无非是由一些门电路和触发器组成,从物理上看,在任何时刻,芯片内部各部分电路都是同时工作的。所以在设计的时候,我们需要以一种并发的思维去思考。以下面例子为例:
例3:
always @(posedge clk or negedge rst_n)
begin
if ( rst_n == 1'b0 )
begin
wren <= 1’b0;
rden <= 1’b0;
end
else
begin
wren <= a&b;
rden <= c&d;
end
end
在综合成实际电路之后,wren和rden的赋值是同时进行的,并不会因为wren在rden前面就先对wren赋值(其实将赋值理解高低电平的传递会更好一些)。事实上,当综合成网表文件后,这种赋值的先后顺序也就不存在了。
第二,电路行为的先后顺序是通过时钟节拍去完成的。
在一些时候,我们需要完成这样的功能:在STATE0状态下,当事件A来了后,去触发状态STATE1;在状态STATE1下,外部总线上读取数据;在处理完后,又进入到状态STATE2,将数据突发传送到背板总线上,并回到STATE0。
这就有了一种逻辑上的先后关系,但是由于我们的电路都是并行工作的,我们不能像C语言的方式将代码在一个进程中按先后顺序排放后就可以完成功能。那我们要怎么去实现呢?我们知道,我们人类去判别先后顺序是按通过时间完成的,也就是说,如果我们是基于时钟节拍去设计的话----即在节拍n事件A到来,在节拍B进入状态STATE0,在n+1到n+k节拍中每x个节拍从外部总线上取一个数,在n+k节拍后,每一个节拍将缓存在FIFO的数据放到背板总线上,就可以实现这种逻辑的先后顺序。总结起来,就是电路行为的逻辑先后顺序是通过时钟节拍去体现的,设计时可以通过将事件安排在不同的时钟节拍去完成。
二、Testbench的基本操作
A-基本操作
对于testbench而言,端口与被测module一一对应,input声明为reg,output声明为wire,如果是systemveriog,则可以统一定义为logic。
1-直接赋值
initial操作:
module exam();
reg rst_n;
reg clk;
reg data; initial
begin
clk=1'b0;
rst=1'b1;
#10
rst=1'b0;
#500
rst=1'b1;
end always
begin
#10
clk=~clk;
end
注意到有个#符号,该符号的意思是指延迟相应的时间单位。该时间单位由timscale决定.一般在testbench的开头定义时间单位和仿真 精度,比如`timescale 1ns/1ps,前面一个是代表时间单位,后面一个代表仿真时间精度。以上面的例子而言,一个时钟周期是20个单位,也就是20ns。而仿真时间精度的概 念就是,你能看到1.001ns时对应的信号值,而假如timescale 1ns/1ns,1.001ns时候的值就无法看到。对于一个设计而言,时间刻度应该统一,如果设计文件和testbench里面的时间刻度不一致,仿真 器默认以testbench为准。一个较好的办法是写一个global.v文件,然后用include的办法,可以防止这个问题。
2-重复操作
例如写某一个字符串,需要重复操作且字符串内容有变更,这个时候可以借助task来完成。
task load_count;
input [3:0] load_value;
begin
@(negedge clk_50);
$display($time, " << Loading the counter with %h >>", load_value);
load_l = 1’b0;
count_in = load_value;
@(negedge clk_50);
load_l = 1’b1;
end
endtask //of load_count initial
begin
load_count(4’hA); // 调用task
end
其他像forever,for,function等等语句用法类似,虽然不一定都能综合,但是用在testbench里面即使是偏高级的语言也不要紧,写testbench与写普通的module思路略有差异。
3-文件输入
有时候,需要大量的数据输入,直接赋值的话比较繁琐,可以先生成数据,再将数据读入到寄存器中,需要时取出即可。用 $readmemb系统任务从文本文件中读取二进制向量(可以包含输入激励和输出期望值)。$readmemh 用于读取十六进制文件。例如:
reg [7:0] mem[1:256] // a 8-bit, 256-word 定义存储器mem
initial $readmemh ( "E:/readhex/mem.dat", mem ) // 将.dat文件读入寄存器mem中
initial $readmemh ( "E:/readhex/mem.dat", mem, 128, 1 ) // 参数为寄存器加载数据的地址始终
B-查看仿真结果
对于简单的module来说,要在modelsim的仿真窗口里面看波形,就用add wave ..命令,比如,testbench的顶层module名叫tb,要看时钟信号,就用add wave tb.clk。要查看所有信号的时候,就用 add wave /*。当然,也可以在workspace下的sim窗口里面右键单击instance来添加波形。
对于复杂的仿真,免不了要记录波形和数据到文件里面去。 这一块的资料可搜索关键词:$dumpvar
C-testbench编写技巧
1).如果激励中有一些重复的项目,可以考虑将这些语句编写成一个task,这样会给书写和仿真带来很大方便。例如,一个存储器的testbench的激励可以包含write,read等task。
2).如果DUT中包含双向信号(inout),在编写testbench时要注意。需要一个reg变量来表示其输入,还需要一个wire变量表示其输出。
3).如果initial块语句过于复杂,可以考虑将其分为互补相干的几个部分,用数个initial块来描述。在仿真时,这些initial块会并发运行。这样方便阅读和修改。
4).每个testbench都最好包含$stop语句,用以指明仿真何时结束。
5).加载测试向量时,避免在时钟的上下沿变化,比如数据最好在时钟上升沿之前变化,这也符合建立时间的要求。
三、常用的时钟/复位
时钟clk以及复位rst是除了测试模块外,必须要考虑的信息。
initial
begin
Clk = 0 ;
# delay ;
forever
# (period/2) Clk = ~ Clk ;
end
注意一定要给时钟赋初始值,因为信号的缺省值为z,如果不赋初值,则反相后还是z,时钟就一直处于高阻z状态。产生的时钟信号如下
initial
Clk= 0 ;
always
# (period/2) Clk = ~ Clk ;
initial
begin
Clk = 0 ;
repeat ( 6 )
# (period/2) Clk = ~ Clk ;
end
该例使用repeat产生 3个时钟脉冲,产生的波形如下:
(d)产生占空比非50%的时钟
initial
Clk = 0 ;
always
begin
# 3 Clk=~Clk;
#2 Clk=~Clk;
end
B-产生复位信号的几种形式
initial
begin
Rst = 1 ;
# 100 ;
Rst = 0 ;
# 500 ;
Rst = 1 ;
end
- http://blog.csdn.net/wordwarwordwar/article/details/53885209
Testbench的更多相关文章
- UVM Top Testbench
top testbench在top_tb中包含进所有的文件,将DUT放在top_tb中(例化DUT),连接好各个端口,提供clk时钟和rst_n复位信号.最主要的是要给组件中的虚接口设置接口,一般是给 ...
- VHDL TestBench基础(转)
TestBench的主要目标是: 实例化DUT-Design Under Test 为DUT产生激励波形 产生参考输出,并将DUT的输出与参考输出进行比较 提供测试通过或失败的指示 TestBench ...
- VHDL的testbench的编写(转)
大多数硬件设计人员对verilog的testbench比较熟悉,那是因为verilog被设计出来的目的就是为了用于测试使用,也正是因为这样verilog的语法规则才被设计得更像C语言,而verilog ...
- quartus II 自动生成testbench
如果自己不想写这些testbench的这些固定格式,可以在quartus里自动生成testbench文件的模板,然后往里面写信号就行了 步骤:processing->start->star ...
- testbench中将外部数据引入输出的方法(转载)
在进行HDL的仿真测试时,除了用较为直观的波形仿真图像以外,通过编写测试文件testbench进行仿真并将仿真结果保存在对应的文件,显得尤为重要.文件的操作主要用到读和写两种操作. 1. 读操作 读操 ...
- 关于使用ModelSim中编写testbench模板问题
对于初学者来说写Testbench测试文件还是比较困难的,但Modelsim和quartus ii都提供了模板,下面就如何使用Modelsim提供的模板进行操作. Modelsim提供了很多Testb ...
- IIC模块TestBench的书写方法
今天在看黑金AX309FPGA开发板自带教程中的EEPROM那一章,考虑如何写其中iic_com模块的TestBench,难点在于1. 该模块存在一个inout型的端口信号:2. 时序较为复杂,不可能 ...
- Testbench(转)
本来还打算自己写下对Testbench的理解,后来发现百度百科名片解释得很好,所以就直接转了. 原文百度百科链接:http://baike.baidu.com/link?url=dxzsOAs32IE ...
- vcs+Makefile实现简单的testbench
网络上找的文章,实现了一遍. 步骤如下: 1. 创建verilog代码, 包括8位加法器代码和testbench代码. adder8.v module adder8 ( input clk, inpu ...
- Verilog TestBench Coding Style
Abtract 关于编写testbench的一些经验总结心得. Introduction 1.基本的Testbench结构 1)常用的编码结构 `timescale 1 ns / 1 ps ...
随机推荐
- dubbo+maven多模块项目单元测试
基本上就是记录各种报错的解决办法.基本上就是将散落在项目各个模块中的配置文件复制到测试模块中. 目录结构: ——src ——java ——test ——java ——DaoTest.java ——re ...
- Cognos报表展示图片小技巧
场景:在销售行业,比如手机,服装行业,如果仅仅的显示数字.文字那就显得不是很生动了,例如可以显示一下图片,那种样子的产品受大家喜欢. 样例1:在报表头都喜欢加上一些公司的logo,让报表看上去专业点. ...
- 我对REST的理解
1:rest的由来 REST即表述性状态传递(英文:Representational State Transfer,简称REST) 通俗点说:资源在网络中以某种表现形式进行状态转移. 源于REST之父 ...
- [HTML5] Avoiding CSS Conflicts via Shadow DOM CSS encapsulation
Shadow DOM is part of the web components specification. It allows us to ship self contained componen ...
- ImportError: No module named arcpy
好久没写Python脚本了,今天一运行就报错:未找到名称为 arcpy 的模块(ImportError: No module named arcpy). 多半是环境变量出问题了,Python最令人讨厌 ...
- MVC Linq动态排序
在nuget 中searh System.Linq.Dynamic 安装对应的版本, 这样都可以使用了 var orderExpression = string.Format("{0} {1 ...
- LR函数基础(一)
函数用到:web_reg_find(). lr_log_message(). lr_eval_string().strcmp().atoi() Action(){ web_reg_find(&q ...
- 转载:【微信小程序】 wx:if 与 hidden(隐藏元素)区别
条件渲染 顾名思义所谓的条件渲染,就是通过条件来判断是否需要渲染该代码块.条件渲染主要是用到wx:if 和 block wx:if 这两个,第一个相信好理解,第二个是在block里面进行条件渲染,这里 ...
- 一个PHP操作大变量的例子
By C extensions we can directly manipulate the large PHP variables, such as:GET,POST,SERVER You can ...
- webview使用遇到 It is possible that this object was over-released, or is in the process of deallocation错误的解决办法
使用wekwebview时,push后,再pop返回,报错了: Cannot form weak reference to instance (xxxx) of class xxxx. It is p ...