如何编写Testbench
更新时间:2023-10-10 00:57:01 阅读量: 综合文库 文档下载
2 如何编写Testbench
1) 何时使用initial和always
initial和always 是2个基本的过程结构语句,在仿真的一开始即开始相互并行执行。通常被动的检测响应使用always语句,而主动的产生激励使用initial语句。
initial和always的区别是always 语句不断地重复执行,initial语句则只执行一次。但是,如果希望在initial里的多次运行一个语句块,怎么办?这时可以在initial里嵌入循环语句(while,repeat,for,forever 等),如: initial begin
forever /* 无条件连续执行*/ begin …… end end
其它循环语句请参考一些教材,这里不作赘述。
另外,如果希望在仿真的某一时刻同时启动多个任务,可以使用fork....join语句。例如,在仿真开始的 100 ns 后,希望同时启动发送和接收任务,而不是发送完毕后再进行接收,如下所示: initial begin #100 ;
fork /*并行执行 */ Send_task ; Receive_task ; join End
2) 如何作多种工作模式的遍历测试
如果设计的工作模式很多,免不了做各种模式的遍历测试,而遍历测试是需要非常大的工作量的。我们经常遇到这样的情况:很多时候,各种模式之间仅仅是部分寄存器配置值的不同,而各模式间的测试都是雷同的。有什么方法可以减轻这种遍历测试的工作量?不妨试
试for循环语句,采用循环变量来传递各种模式的配置值,会帮助减少很多测试代码,而且不会漏掉每一种模式. initial begin
for ( i = 0 ; i < m ; i = i + 1 ) /*遍历模式1至模式m*/ for ( j = 0 ; j < n ; j = j +1 ) /*遍历子模式1至子模式n */ begin
case ( j ) /* 设置每种模式所需的配置值 */ 0 : 配置值 = a ; 1 : 配置值 = b ; 2 : 配置值 = c ; …… endcase /*共同的测试向量*/ end end
3) 如何加速问题定位过程
在这部分里,通过一些实际例子,介绍在出现问题时如何借助 testbench 加快问题的定位过程。
1、监测内存分配
内存分配和回收示意图
在这个例子里,假设总共有2K的内存块,希望在测试程序里监测内存分配和回收的块号是否正确,监测是否存在同一块号重复分配、重复回收的情况。设置一个 2K位的变量对内存的使用情况进行记录,每一位对应一个内存块,空闲的块号记为1,被占用的块号记为0。
该变量的初始值为全1,当分配一 个块号出去时先判断该位是否为空闲,若是空闲则将该位设置为被占用,否则就为重复分配错误。相反,当回收一个块号时,先判断该位是否被占用,若是被占用则将该位设置为空闲,否则就为重复回收错误。程序如下: always @(posedge Clk or negedge Rst ) begin
if ( Rst == 1'b0 ) Mem_status <= 2048 {1'b1} ; else begin
if ( 层次路径 . rd ) /* 监测内存分配,block_rd 是分配的内存块号*/ if ( Mem_status [ block_rd ] == 1'b1 ) Mem_status [ block_rd ] <= 1'b0 ; else begin
$display ( \重复分配同一内存块! \$stop ; end
if ( 层次路径 . wr ) /* 监测内存回收,block_wr 是回收的内存块号*/ if ( Mem_status [ block_wr ] == 1'b0 ) Mem_status [ block_wr ] <= 1'b1 ; else begin
$display ( \重复回收同一内存块! \ $stop ; end end End
2、监测内部接口
如果你是位验证工程师,在做芯片级的仿真时,相信你会或曾遇到过这样的问题:在一个端口输入了激励数据,但另一端口却得不到正确的响应,而且这条路径涉及到很多模块和很多个不同设计者,为了定位问题,你可能很盲目地逐个找来设计人员,逐个模块地记录仿真波形,到解决问题时,可能几天已经过去了。
我们都知道,如果问题定位在越小的范围,就越便于解决问题。所以,我们可以把模块接口间交换的数据记录到文件里,当出现问题时,就可以查看各接口的记录数据,看问题到底出现在哪个区间,简单地查看记录文件后,你就明确该找那位designer来解决问题。 3、记录有用的DEBUG信息
记录有用的debug信息,输出到标准的I/O设备上(屏幕或文件),会给你的debug带来很大的便利,由上面的例子也可见一斑,在检测到有错误时也可使用$stop令仿真停下来。
值得注意的是,UNIX系统只有32个I/O,每个输出文件占用1个I/O设备号,其中第1个是屏幕显示,设备号是32'b1,其它I/O设备号由输出文件占用,一个信息可同时输出到屏幕和文件,如: initial begin
Ptr_log = $fopen (\创建一个文件,获得文件指针 */ Ptr_log = Ptr_log | 32'b1 ; /* 指针同时指向 log.txt 文件和屏幕 */ end
always @(……) begin
$fwrite ( Ptr_log, \……) ; /*信息除了记录到文件同时,还显示到屏幕*/ …… end
虽然记录文件会给debug带来很多便利,但文件操作会降低仿真的速度,因此应当适可而止。
另外写文件通常有2种方式,不同的仿真工具有所差异。一种是每写一个字节打开关闭一次文件,如Verilog-XL。另一种是先把字符暂存到内存,等累积到一定数量(如8K字节)后再通过DMA方式把字符从内存写到文件,如Verilog-NC。因此,后一种方式就大大地降低了文件的操作次数,有利于提高仿真速度。 3 编写Testbench的一些高级技巧
Verilog HDL提供很多方便和高效的建模语句,这在大多数参考书上都有介绍,在这节,只介绍一些参考教材很少介绍而较有用的建模语句。 1) force 和 release
望文生义,force即是可以对变量和信号强制性地赋予确定的值,而release就是解除force的作用,恢复为驱动源的值。例如: wire a ;
assign a = 1'b0 ; initial begin #10 ;
force a = 1'b1 ; #10 release a ; end
在10 ns时,a 的值由0变为1,在20ns时,a 的值又恢复为0 。
force 和release并不常用,有时,可以利用它们和仿真工具做简单的交互操作。例如,Verilog-XL的图形界面可以方便的将一个信号或变量force 为0或1,在 Testbench 里,可以检测变量是否被force为固定的值,当被force为固定的值时就执行预定的操作,实现了简单交互操作。 2) 事件
事件有些类似于任务。首先需要定义一个事件,而事件可以作为敏感变量激活一个语句块的操作,事件可由“->”符号进行触发,如下例: event e1 ; /*定义一个事件*/
always @( e1 ) /*事件e1 作为敏感变量*/ begin ..... end initial begin
—> e1 ; /*创建事件e1来触发上面的always语句*/ ..... end
事件(event )与任务(task)的区别是:执行事件触发后可以立即继续往下执行语句,只起一个触发作用,至于被触发的事件何时执行完毕并不影响程序继续执行。而调用一个任务后,必须等待任务完成才能返回控制权。
正在阅读:
如何编写Testbench10-10
小学数学学科二年级下册教学计划08-27
艺术与咖啡——世界各地伟大艺术咖啡馆简介07-21
直埋电缆沟的开挖尺寸08-31
爱国主义主题教育活动征文03-27
编程题 vb 习题05-10
2022年-2022年人教版新课标八年级英语上期末考试试卷含答案04-09
传承传统文化的必要性05-20
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- Testbench
- 编写
- 如何