作者:桂。

时间: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是除了测试模块外,必须要考虑的信息。

  A-产生时钟的几种方式
(a)使用initial方式产生占空比50%的时钟
initial
begin
Clk = 0 ;
# delay ;
forever
# (period/2) Clk = ~ Clk ;
end

  注意一定要给时钟赋初始值,因为信号的缺省值为z,如果不赋初值,则反相后还是z,时钟就一直处于高阻z状态。产生的时钟信号如下

(b)使用always方式
initial
Clk= 0 ;
always
# (period/2) Clk = ~ Clk ;
(c)使用repeat产生确定数目的时钟脉冲
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-产生复位信号的几种形式

(a)异步复位
initial
begin
Rst = 1 ;
# 100 ;
Rst = 0 ;
# 500 ;
Rst = 1 ;
end
(b)同步复位信号
initial
begin
Rst = 1 ;
@( negedge Clk) ; //等待时钟下降沿
Rst = 0 ;
# 30 ;
repeat(3)@( negedge Clk) ; //等待3个时钟下降沿
Rst = 1 ;
end
 
参考
  • http://blog.csdn.net/wordwarwordwar/article/details/53885209

Testbench的更多相关文章

  1. UVM Top Testbench

    top testbench在top_tb中包含进所有的文件,将DUT放在top_tb中(例化DUT),连接好各个端口,提供clk时钟和rst_n复位信号.最主要的是要给组件中的虚接口设置接口,一般是给 ...

  2. VHDL TestBench基础(转)

    TestBench的主要目标是: 实例化DUT-Design Under Test 为DUT产生激励波形 产生参考输出,并将DUT的输出与参考输出进行比较 提供测试通过或失败的指示 TestBench ...

  3. VHDL的testbench的编写(转)

    大多数硬件设计人员对verilog的testbench比较熟悉,那是因为verilog被设计出来的目的就是为了用于测试使用,也正是因为这样verilog的语法规则才被设计得更像C语言,而verilog ...

  4. quartus II 自动生成testbench

    如果自己不想写这些testbench的这些固定格式,可以在quartus里自动生成testbench文件的模板,然后往里面写信号就行了 步骤:processing->start->star ...

  5. testbench中将外部数据引入输出的方法(转载)

    在进行HDL的仿真测试时,除了用较为直观的波形仿真图像以外,通过编写测试文件testbench进行仿真并将仿真结果保存在对应的文件,显得尤为重要.文件的操作主要用到读和写两种操作. 1. 读操作 读操 ...

  6. 关于使用ModelSim中编写testbench模板问题

    对于初学者来说写Testbench测试文件还是比较困难的,但Modelsim和quartus ii都提供了模板,下面就如何使用Modelsim提供的模板进行操作. Modelsim提供了很多Testb ...

  7. IIC模块TestBench的书写方法

    今天在看黑金AX309FPGA开发板自带教程中的EEPROM那一章,考虑如何写其中iic_com模块的TestBench,难点在于1. 该模块存在一个inout型的端口信号:2. 时序较为复杂,不可能 ...

  8. Testbench(转)

    本来还打算自己写下对Testbench的理解,后来发现百度百科名片解释得很好,所以就直接转了. 原文百度百科链接:http://baike.baidu.com/link?url=dxzsOAs32IE ...

  9. vcs+Makefile实现简单的testbench

    网络上找的文章,实现了一遍. 步骤如下: 1. 创建verilog代码, 包括8位加法器代码和testbench代码. adder8.v module adder8 ( input clk, inpu ...

  10. Verilog TestBench Coding Style

    Abtract 关于编写testbench的一些经验总结心得. Introduction 1.基本的Testbench结构 1)常用的编码结构 `timescale 1 ns / 1 ps       ...

随机推荐

  1. Jmeter-Maven-Plugin高级应用:Proxy Configuration

    Proxy Configuration Pages 12 Home Adding additional libraries to the classpath Advanced Configuratio ...

  2. linux 硬连接与软连接

    1.linux中文件占用一个inode,inode指向文件内容.2.文件名可以认为是一个指针,指向inode.硬连接相当于指针的整体拷贝,并不是对文件内容的拷贝.两个文件名(两个指针)都能修改文件,删 ...

  3. Android实现固定头部信息,挤压动画(相似通讯录)

    半年前,那时候我还是个大四的学生,每天都在找工作度过,想去北京体验一下蚁族生活,奋然离开了济南,哎...在济南我们学校还是数得着的好学校,去了北京就什么都不是了,一切的辛酸仅仅有自己知道,那时候的我仅 ...

  4. 基于Teigha.Net实现CAD到SHP的转换方案

    CAD在测绘领域运用广泛,所以,现在有很多成果都是CAD格式,但其自身存在很多局限性,需将其转为支持更加广泛,存储更加完善的 SHP文件.ArcGIS中直接提供相关转换工具,但不能转换Xdata,Ar ...

  5. Python中的乱码

        我把写好的Python脚本导入到ArcGIS中的ToolBox中,在本机测试是没有问题的.为了把工具分享给其他人,即在其他电脑上使用,我必须将脚本文件(*.py)导入到工具箱文件(*.tbx) ...

  6. 算法笔记_176:历届试题 最大子阵(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大. 其中,A的子矩阵指在A中行和列均连续的一块. 输入格式 输入 ...

  7. IO习题

    1.Java实现将九九乘法表输入到文本文件 public class Test1 { public static void main(String[] args) throws FileNotFoun ...

  8. Stage3d AGAL GPU处理照片 旧照片效果 sepia || pixelbender

    如果看不到下边的flash,请更新flash player到最新版本. 利用AGAL实现旧照片效果,大家可以对照一下之前一篇文章,关于图像处理(pixelbender).硬件处理肯定会更快,但这里无法 ...

  9. springmvc自己定义拦截器

    Spring MVC也能够使用拦截器对请求进行拦截处理,用户能够自己定义拦截器来实现特定的功能,自己定义的拦截器必须实现HandlerInterceptor接口. 直接看下样例: package co ...

  10. 通过jdbc使用PreparedStatement,提升性能,防止sql注入

    为什么要使用PreparedStatement? 一.通过PreparedStatement提升性能 Statement主要用于执行静态SQL语句,即内容固定不变的SQL语句.Statement每执行 ...