• Abtract

关于编写testbench的一些经验总结心得。

  • Introduction

  • 1.基本的Testbench结构

1)常用的编码结构

`timescale 1 ns / 1 ps       // 时间精度和刻度

module 模块名称;

DUT输入信号定义;      // DUT输入信号一般定义为reg类型

DUT输出信号定义;      // DUT输出信号一般定义为wire类型

...

DUT                    // 待测module

...

initial begin

// 定义相关信号初始值或者定义时钟复位等控制信号

// 监测、添加约束等

end

...

always                 // 处理相关需要变化的值

...

endmodule

2)常用结构图示

下节针对Testbench的基本结构的细节进行解析说明。

  • 2.DUT输入输出端口

1)输入端口

DUT的输入端口(input)一般定义为reg类型。

2)输出端口

DUT的输出端口(output)一般定义为wire类型。

3)双向端口

DUT的端口中如果存在双向端口(inout),则一般定义为wire类型。

注意:面对inout类型的处理,通常可以采用以下方法:

a.通过中间变量作为inout类型端口的输出寄存;

e.g.    inout  bi_port;

wire  bi_port;

reg   bi_port_reg;       // inout类型的中间变量为reg

reg   bi_port_en;

assign bi_port = bi_port_en ? bi_port_reg : 1'bz;

b.使用force和release语句

e.g.    force bi_port = 1'b1;    // 强制作为输入端口

release bi_port;        // 释放端口

4)模块之间连接

如果Testbench中存在多个模块,且多个模块之间存在互连,则相互之间的连线定义为wire类型。

关于Testbench中各种类型的定义如下如所示:

  • 3.initial定义使用方法

1)在initial语句中定义时钟

initial begin

...

clk = 1'b0;

forever #(clk_halfp) clk = ~clk;   // 其中clk_halfp为半周期

end

2)在initial语句中定义复位

initial begin

...

reset = 1'b0;        // 如果是低电平复位

#(reset_time);      // 复位时间

reset = 1'b1;        // 复位撤销

...

end

3)在initial语句中定义相关数据信号

initial begin

...

dat = 2'b00;        // 数据值1

#(gap_time);       // 数据间隔

dat = 2'b01;        // 数据值2

#(gap_time);       // 数据间隔

dat = 2'b11;        // 数据值3

...

#(gap_time);       // 数据间隔

dat = 2'b10;        // 数据值4

...

end

4)在initial语句中加入关键字

initial begin

...

$sdf_annotat("abc.sdf",top);        // 指定sdf文档路径和反标层次

...

$finish;                         // 程序结束

...

// 其他系统函数

...

$fsdbDumpfile("top.fsdb");         // 生成Novas调用的波形文档

$fsdbDumpvars(0, tb);
   ...

end

5)在initial语句中定义#0延时信号

6)initial语句的几个特性

u  initial语句在0时刻启动

u  initial语句只能执行一次

u  当Testbench中有多个initial语句,则所有的initial语句同时并行执行

7)initial语句中被赋值的变量通常为reg类型

8)常用系统函数可作为监控等,详见下文第7节。

  • 4.always定义使用方法

1)产生时钟

always

begin

...

# (clk_halfp) clk = ~clk       // clk_halfp为系统半时钟

...

end

2)产生数据

always @(敏感信号列表或者时钟)

begin

...

dat <= temp;       // 其中temp可以为DUT的反馈信号,用以产生dat作为DUT输

// 入信号

...

end

  • 5.DUT监测方法

1)调用系统函数对DUT运行状况进行实时监测($dispaly()、$strobe()、$monitor() 、$fwrite()等)

...

initial begin

fp = $fopen("log.txt","w");                                 // 打开存储数据的文件

...

$monitor("%0dns :\$monitor: a=%b b=%b"  , $stime, a, b);      // 实时监控a,b

$display("%0dns :\$display: a=%b b=%b"    , $stime, a, b);      // 显示a,b

$strobe ("%0dns :\$strobe : a=%b b=%b\n"  , $stime, a, b);      // 下时阶显示当前a,b

$fwrite(fp, "%0dns :\$fwrite : a=%b b=%b\n", $stime, a, b);      // 按引号中格式输出a,

// b的变化

...

$fclose(fp);                                             // 关闭存储数据的文件

end

...

关于系统函数的详细使用方法可以参阅相关Verilog书籍。

2)通过功能相似的IP核进行验证

通过SOURCE输入的激励信号同时发送给IP核(该IP功能与DUT功能相同),经过相应处理之后,将DUT与IP核的输出数据进行比较(CHECK),同时在CHECK中可以对相关的比较进行记录(可以调用系统函数,将结果输出到指定文档等)

  • 6.编写Testbench常用技巧

1)CGU:时钟产生电路

将时钟电路作为专门的电路单元或者task进行编写,同时参数化其中的周期参数等,在Testbench中进行例化与DUT进行连接,减少Testbench中的代码量,同时使Testbench中的代码更加简洁、模块化、参数化。

2)RGU:复位产生电路

RGU模块的作用类似于CGU。

3)CHECK:结果比较电路

基于Testbench简洁清晰化、模块化、参数化,可以讲CHECK专门作为一个模块,对测试验证的结果进行相应的处理加工。

4)PARAMETER:参数化设计

在对模块调用时,只需要在Testbench中例化模块式,填写相应的参数即可对模块进行中的相应参数进行修改,修改方便简洁。

e.g.    ...

parameter clk_halfp = 50;               // 定义时钟半周期

...

CGU  u_cgu #(.clk_halfp(clk_halfp))     // 配置CGU中参数clk_halfp,生成时钟

...

.clk(clk_sys)               // 输出时钟信号

...

可见,通过参数化处理,不仅可以配置时钟周期,还可以确定数据位宽等,当然在设计中同样可以使用include "abc_cfg.v"文件,对整个系统设计中的所有参数进行统一管理和定义。

5)IP REUSE:IP复用

随着IP设计的愈加成熟,复用已经成熟的IP进行设计和验证可以大大缩短设计和验证的周期,加快产品的开发,因此,建议在Testbench中可以复用已经成熟的IP进行设计和验证。

6)在initial语句中最好,定义$stop,用以指明仿真何时结束。

  • 7.常用系统函数使用举例

1)添加SDF文件

添加SDF文件不仅可以通过一些仿真工具进行增加,同时还可以使用$sdf_annotate函数进行指定。

e.g.  $sdf_annotate("sdf_file_name",module_instance,"scale_factors");

其中module_instance:使用sdf文件所对应的instance name;

scale_factors:针对timming delay中的最小延迟(min)、典型延迟(typ)、最大延时(max)

2)生成VCD文件,VCD文件可以记录仿真过程中信号的变化,只记录在函数中指定的层次中相关的信号。

e.g.    $dumpfile("filename");           // open database

$dumpvars(1,TB.u1);          // 只记录u1中的数据,记录深度仅为1层

注意:其中第一个参数表示深度,为0表示记录所有层次深度中的信号的变化;第二个参数表示scope,即表示要观测的模块的例化名,当省略时表示当前scope。

e.g.    $dumpvars;                   // depth = all;scope = all

$dumpvars(0);                 // depth = all;scopt = current

$dumpoff                    // 暂停记录数据的变化,此刻之后dumpop之前的

// 所有信号的变化将不计入database。

$dumpon            // 回复记录数据

3)文本文件的梳理

a.读取文本文件

用$readmemb系统任务从文本文件中读取二进制向量(可以包含输入输出),$readmemh用于读取十六进制文件。

e.g.    reg [7:0] mem [0:255]                   // the data is 8-0bit & the addr is 0~256

initial begin

$readmemh("mem.dat",mem);       // read the data from mem.dat to mem

$readmemh("mem.dat",mem,128,1);  // read the data addr is 1 to 128

end

b.输出文本文件

这里需要注意在对文件进行写操作之前需要打开建立文件,使用$fopen(),在写完文件之后要关闭文件$fclose()。

e.g.    integer out_file;              // 类似C语言中指定文件指针

out_file = $fopen("abc.dat");   //  abc.dat为要输出的文档名

可以通过$fmonitor,$fdisplay把需要观测的数据按照相应的格式输出到abc.dat中

e.g.    $fdisplay(out_file,data);       // output the data to the file abc.dat

转载:http://www.cnblogs.com/nanoty/archive/2012/11/02/2751873.html

Verilog TestBench Coding Style的更多相关文章

  1. (转帖) 有限狀態機FSM coding style整理 (SOC) (Verilog)

    来源:http://www.codesoso.net/Record/101092_95120_21.html 来源:http://www.cnblogs.com/oomusou/archive/201 ...

  2. 有限狀態機FSM coding style整理 (SOC) (Verilog)

    AbstractFSM在數位電路中非常重要,藉由FSM,可以讓數位電路也能循序地執行起演算法.本文將詳細討論各種FSM coding style的優缺點,並歸納出推薦的coding style. In ...

  3. 编程风格(Coding Style)要求

    编程风格(Coding Style)要求2.1.1 文件(1) 每个模块(module)一般应存在于单独的源文件中,通常源文件名与所包含模块名相同.(2) 每个设计文件开头应包含如下注释内容:? 年份 ...

  4. Linux 内核Coding Style整理

    转载:http://www.cnblogs.com/wang_yb/p/3532349.html 总结linux内核开发的coding style, 便于以后写代码时参考. 下面只是罗列一些规则, 具 ...

  5. linux c coding style

    Linux kernel coding style This is a short document describing the preferred coding style for the lin ...

  6. c coding style之学习篇

    1. 使用do-while结构去避免潜在的内存泄漏问题. do {     p1 = malloc(10);     if (null == p1)     {         break;     ...

  7. [中英对照]Linux kernel coding style | Linux内核编码风格

    Linux kernel coding style | Linux内核编码风格 This is a short document describing the preferred coding sty ...

  8. 谈谈Linux内核驱动的coding style【转】

    转自:http://www.cnblogs.com/wwang/archive/2011/02/24/1960283.html 最近在向Linux内核提交一些驱动程序,在提交的过程中,发现自己的代码离 ...

  9. Google's C++ coding style

    v0.2 - Last updated November 8, 2013 源自 Google's C++ coding style rev. 3.274 目录 由 DocToc生成     头文件   ...

随机推荐

  1. BZOJ1965 [Ahoi2005]SHUFFLE 洗牌 快速幂

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1965 题意概括 对于扑克牌的一次洗牌是这样定义的,将一叠N(N为偶数)张扑克牌平均分成上下两叠,取 ...

  2. kali上部署dvwa漏洞测试平台

    kali上部署dvwa漏洞测试平台 一.获取dvwa安装包并解压 二.赋予dvwa文件夹相应权限 三.配置Mysql数据库 四.启动apache2和mysql服务 五.在网页配置dvwa 六.登陆到D ...

  3. Java中A instanceof B是什么意思?

    instanceof用来判断内存中实际对象A是不是B类型 出现这种情况经常是需要强制转换的时候class Dog extends Animal譬如dog定义了自己的方法wangwang Animal ...

  4. android studio的汉化 教程 及解析

    android studio的汉化 教程 及解析 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com E-mail: 313134555 @qq.c ...

  5. 使用xlrd模块操作Excel

    table = data.sheets()[] table = data.sheet_by_index() print(table) #获取正行或是整列的值 con = table.row_value ...

  6. Celery入门指北

    Celery入门指北 其实本文就是我看完Celery的官方文档指南的读书笔记.然后由于我的懒,只看完了那些入门指南,原文地址:First Steps with Celery,Next Steps,Us ...

  7. weblogic10 部署 spring+cxf ,调用时报:cannot create a secure XmlInputFactory

    weblogic10 部署 spring+cxf ,调用时报:cannot create a secure XmlInputFactory   一个cxf webservice项目部署到tomcat能 ...

  8. ES6语法篇(其一)

    转载链接:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/es6-grammar-part-one/ 一.let命令 基本用法:ES ...

  9. [原创]Eclipse Memory Analyzer tool(MAT)工个使用介绍

    [原创]Eclipse Memory Analyzer tool(MAT)工个使用介绍

  10. AIX中vi编辑器使用

    3.1 vi 简介 vi 是 UNIX 世界里使用非常普遍的全屏幕文本编辑器,几乎任何一种UNIX系统都会提供这套软件.AIX当然也支持这种编辑器.熟悉DOS下的文本处理后,用户在开始接触vi时也许会 ...