文档章节

Testbench编写技巧

o
 osc_fmg49rzg
发布于 2019/03/18 17:30
字数 1336
阅读 0
收藏 0
dat

精选30+云产品,助力企业轻松上云!>>>

一、基本架构(常用模板)

 1 `timescale 1ns/1ps  //时间精度
 2 `define    Clock 20 //时钟周期
 3 
 4 module my_design_tb;
 5 
 6 //==================<端口>==================================================
 7 reg                         clk                 ; //时钟,50Mhz
 8 reg                         rst_n               ; //复位,低电平有效
 9 reg  [XX:0]                 in                  ; //
10 wire [XX:0]                 out                 ; //
11 
12 //--------------------------------------------------------------------------
13 //--    模块例化
14 //--------------------------------------------------------------------------
15 my_design u_my_design
16 (
17     .clk                    (clk                ),
18     .rst_n                  (rst_n              ),
19     .in                     (in                 ),
20     .out                    (out                )
21 );
22 
23 //----------------------------------------------------------------------
24 //--    时钟信号和复位信号
25 //----------------------------------------------------------------------
26 initial begin
27     clk = 0;
28     forever
29         #(`Clock/2) clk = ~clk;
30 end
31 
32 initial begin
33     rst_n = 0; #(`Clock*20+1);
34     rst_n = 1;
35 end
36 
37 //----------------------------------------------------------------------
38 //--    设计输入信号
39 //----------------------------------------------------------------------
40 initial begin
41     in = 0;
42     #(`Clock*20+2); //初始化完成
43 
44     $stop;
45 end
46 
47 
48 
49 endmodule

 

二、时钟激励设计

`timescale 1ns/1ps  //时间精度
`define    Clock 20 //时钟周期

//==========================================================================
//==    方法一,50%占空比
//==========================================================================
initial begin
    clk = 0;
    forever
        #(`Clock/2) clk = ~clk;
end

//==========================================================================
//==    方法二,50%占空比
//==========================================================================
initial begin
    clk = 0;
    always
        #(`Clock/2) clk = ~clk;
end

//==========================================================================
//==    方法三,产生固定输入的时钟脉冲
//==========================================================================
initial begin
    clk = 0;
    repeat(6)
        #(`Clock/2) clk = ~clk;
end

//==========================================================================
//==    方法四,非50%占空比
//==========================================================================
initial begin
    clk = 0;
    forever begin
        #((`Clock/2)-2) clk = 0;
        #((`Clock/2)+2) clk = 1;
    end
end

 

三、复位信号设计

`timescale 1ns/1ps  //时间精度
`define    Clock 20 //时钟周期

//==========================================================================
//==    方法一,异步复位
//==========================================================================
initial begin
    rst_n = 0; #(`Clock*20+1);
    rst_n = 1;
end

//==========================================================================
//==    方法二,同步复位
//==========================================================================
initial begin
    rst_n = 0; #(`Clock*20);
    rst_n = 1;
end

 

四、task常用方法

//==========================================================================
//==    输入信号任务封装
//==========================================================================
task i_data;
    input [7:0] dut_data;
    begin
        @(posedge data_en); send_data=0;
        @(posedge data_en); send_data=dut_data[0];
        @(posedge data_en); send_data=dut_data[1];
        @(posedge data_en); send_data=dut_data[2];
        @(posedge data_en); send_data=dut_data[3];
        @(posedge data_en); send_data=dut_data[4];
        @(posedge data_en); send_data=dut_data[5];
        @(posedge data_en); send_data=dut_data[6];
        @(posedge data_en); send_data=dut_data[7];
        @(posedge data_en); send_data=1;
        #100;
    end
endtask

//调用方法:i_data(8'hXX);

//==========================================================================
//==    多输入信号任务封装
//==========================================================================
task more_input;
    input  [ 7:0]     a;
    input  [ 7:0]     b;
    input  [31:0]     times;
    output [ 8:0]     c;
    begin
        repeat(times) @(posedge clk)         //等待 times 个时钟上升沿
        c=a+b;
    end
endtask

//调用方法:more_input(x,y,t,z); //按声明顺序

 

 五、@和wait

//==========================================================================
//==    @为边沿触发
//==========================================================================
initial begin
    start = 1;
    repeat(5) @(posedge clk)    //等待5个时钟上升沿
    start = 0;
end

//==========================================================================
//==    wait为电平触发
//==========================================================================
initial begin
    start = 1;
    wait(en);                     //等待en==1
    start = 0;
end

 

六、常用仿真控制语句

$random         //产生随机数
$random % n     //产生范围 {-n,n} 的随机数
{$random} % n   //产生范围 { 0,n} 的随机数

$stop           //停止运行仿真,Modelsim 中可继续仿真
$finish         //结束运行仿真,Modelsim 中不可继续仿真

$stop(n)        //带参数系统任务,根据参数 0、1、2 不同,输出仿真信息
$finish(n)      //带参数系统任务,根据参数 0、1、2 不同,输出仿真信息
/*------------------------------------------------------------------------*\
    0:不输出任何信息
    1:输出当前仿真时刻和位置
    2:输出当前仿真时刻、位置和仿真过程中用到的 memory 以及 CPU 时间的统计
\*------------------------------------------------------------------------*/

 

七、仿真终端显示描述

$monitor      //仿真打印输出,打印出仿真过程中的变量,使其终端显示
/*------------------------------------------------------------------------*\
  $monitor($time,,,"clk=%d reset=%d out=%d",clk,reset,out);
\*------------------------------------------------------------------------*/

$display      //终端打印字符串,显示仿真结果等
/*------------------------------------------------------------------------*\
  $display(” Simulation start ! ");
  $display(” At time %t,input is %b%b%b,output is %b",$time,a,b,en,z);
\*------------------------------------------------------------------------*/

$time         //返回 64 位整型时间

$stime        //返回 32 位整型时间

$realtime     //实行实时模拟时间

 

八、文本输入

$readmemb/$readmemh("<数据文件名>",<存储器名>);
$readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>);
$readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>,<结束地址>);

$readmemb
/*------------------------------------------------------------------------*\
  读取二进制数据,读取文件内容只能包含:空白位置,注释行,二进制数
  数据中不能包含位宽说明和格式说明,每个数字必须是二进制数字。
\*------------------------------------------------------------------------*/

$readmemh
/*------------------------------------------------------------------------*\
  读取十六进制数据,读取文件内容只能包含:空白位置,注释行,十六进制数
  数据中不能包含位宽说明和格式说明,每个数字必须是十六进制数字.
\*------------------------------------------------------------------------*/

例如:

/*------------------------------------------------------------------------*\
    //mem.dat 文件内容
    @001
    AB CD
    @003
    A1
\*------------------------------------------------------------------------*/
reg [7:0]     memory[7:0]    ;//声明 8 个 8 位存储单元
integer       i              ;

initial begin
    $readmemh("mem.dat",memory);//读取系统文件到存储器中的给定地址
    for(i=0;i<4;i=i+1)
        $display("Memory[%d]=%h",i,memory[i]);
end

/*------------------------------------------------------------------------*\
    //仿真输出为
    Memory[0] = xx;
    Memory[1] = AB;
    Memory[2] = CD;
    Memory[3] = A1;
\*------------------------------------------------------------------------*/

 

九、简单的仿真案例

1.设计文件

 1 module add
 2 //==================<端口>==================================================
 3 (
 4 input  wire [ 5:0]            a                    ,
 5 input  wire [5:0]             b                    , // 输入信号b
 6 input  wire [5:0]             c                    , // 输入信号a
 7 input  wire [5:0]             d                    , // 输入信号b
 8 output wire [7:0]             e                       // 求和输出信号
 9 );
10 
11 //==================<设计>==================================================
12 assign e = a + b + c + d;
13 
14 
15 endmodule

 

2.仿真文件

 1 `timescale 1ns/1ps  //时间精度
 2 
 3 module add_tb;
 4 
 5 //==================<端口>==================================================
 6 //输入输出---------------------------------------
 7 reg  [5:0]                     a                    ;
 8 reg  [5:0]                     b                    ;
 9 reg  [5:0]                     c                    ;
10 reg  [5:0]                     d                    ;
11 wire [7:0]                     e                    ;
12 //中间变量---------------------------------------
13 reg  [5:0]                     i                    ;
14 
15 //--------------------------------------------------------------------------
16 //--    模块例化
17 //--------------------------------------------------------------------------
18 add u_add
19 (
20     .a                        (a                    ),
21     .b                        (b                    ),
22     .c                        (c                    ),
23     .d                        (d                    ),
24     .e                        (e                    )
25 );
26 
27 //----------------------------------------------------------------------
28 //--    设计输入信号
29 //----------------------------------------------------------------------
30 initial begin
31     a = 0;
32     b = 0;
33     c = 0;
34     d = 0;
35     for(i=1;i<31;i=i+1) begin
36         #10;
37         a = i;
38         b = i;
39         c = i;
40         d = i;
41     end
42 end
43 
44 initial begin
45     $monitor($time,,"%d + %d + %d + %d ={%d}",a,b,c,d,e); // 信号打印输出
46     #500;
47     $stop;
48 end
49 
50 
51 endmodule

3.Modelsim仿真

 

参考资料:

[1]米联客FPGA教程

[2]吴厚航. 深入浅出玩转FPGA[M]. 北京航空航天大学出版社, 2013.

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
【代码更新】同步FIFO design and IP level verification

一、前言   应聘IC前端相关岗位时,FIFO是最常考也是最基本的题目。FIFO经常用于数据缓存、位宽转换、异步时钟域处理。随着芯片规模的快速增长,灵活的system verilog成为设计/验证人员的基...

osc_xgq4n4ik
04/16
11
0
Xilinx Vivado的使用详细介绍(1):创建工程、编写代码、行为仿真、Testbench

新建工程 打开Vivado软件,直接在欢迎界面点击,或在开始菜单中选择即可新建工程。 点击 输入工程名称和路径。 选择,勾选(这样可以跳过添加源文件的步骤,源文件可以后面再添加)。 根据自...

osc_jd85vegy
2018/03/22
0
0
Xilinx Vivado的使用详细介绍(1):创建工程、编写代码、行为仿真

Xilinx Vivado的使用详细介绍(1):创建工程、编写代码、行为仿真 Author:zhangxianhe 新建工程 打开Vivado软件,直接在欢迎界面点击Create New Project,或在开始菜单中选择File - New Pr...

osc_wme0cmft
2018/10/13
2
0
Verilog TestBench Coding Style

Abtract 关于编写testbench的一些经验总结心得。 Introduction 1.基本的Testbench结构 1)常用的编码结构 `timescale 1 ns / 1 ps // 时间精度和刻度 module 模块名称; DUT输入信号定义; ...

osc_x4rg8g6r
2018/04/23
1
0
搭建Modelsim SE仿真环境-使用do文件仿真

摘要: 本章我们介绍仿真环境搭建是基于ModelsimSE的。Modelsim有很多版本,比如说Modelsim-Altera,但是笔者还是建议大家使用Modelsim-SE,Modelsim-Altera实际是针对Altera 的OEM版本,它事...

osc_lmvsge82
2018/04/17
2
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux系统检查用户账户到期时间

如果你在 Linux 上启用了密码策略。密码必须在到期前进行更改,并且登录到系统时会收到通知。如果你很少使用自己的帐户,那么可能由于密码过期而被锁定。在许多情况下,这可能会在无需密码登...

老孟的Linux私房菜
38分钟前
13
0
关于南京哪里有开餐饮费发票?

关于南京哪里有开餐饮费发票?聚焦餐饮行业,谈话〖18 7一電一7 5 3 8一徴一3331〗研究院昨发布数据显示,今年上半年,全国餐饮行业招聘需求增长46.18%,平均月薪6387元.随着餐饮行业的快速...

点击fojewio
今天
7
0
android studio 4.0 打开DDMS

1、先找到AndroidStudio配置的SDK路径; 2、在SDK的/tools/路径下有个monitor.bat 的批处理文件; 3、鼠标连续点击两下monitor.bat这个批处理文件,在屏幕上会打开一个类似CMD的命令行中输入...

chenhongjiang
今天
10
0
如何在Android中使用SharedPreferences来存储,获取和编辑值

问题: Closed . 已关闭 。 This question needs to be more focused. 这个问题需要更加集中。 It is not currently accepting answers. 它当前不接受答案。 Learn more . 了解更多 。 Want...

fyin1314
今天
6
0
【JDK1.8】LinkedList源码分析

LinkedList的特性 LinkedList内部使用双向链表作为存储结构,LinkedList可以理解为链表的扩展对象,封装了常用的和非常用的操作链表的方法。以及在通过索引获取元素时的简单优化,通常Linke...

XuePeng77
今天
40
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部