zoukankan      html  css  js  c++  java
  • Testbench编写技巧

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

     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.

  • 相关阅读:
    视频流媒体服务器EasyNVR录像存储为什么会出现规律性中断现象?
    如何使用EasyNVR流媒体平台在办公楼建立全天远程视频监控系统?
    视频流媒体平台EasyNVR直播出现卡顿及重复播放视频片段问题应该如何解决?
    视频流媒体服务器EasyNVR如何开启多进程工作方式?
    视频流媒体平台搭建采用Mysql数据库忘记密码怎么办?
    视频流媒体服务器测试服务搭建配置JDK环境运行项目日志报Illegal key size错误
    视频流媒体解决方案EasyNVR如果出现摄像头拉取不到视频流的情况怎么办?
    在Centos8下搭建部署视频流媒体平台EasyNVR如何穿透防火墙到指定端口?
    视频流媒体平台如何接入监控摄像头实现明厨亮灶?
    视频流媒体服务器EasyNVR在校园监控中使用source指令导入sql文件进mysql报错问题解决
  • 原文地址:https://www.cnblogs.com/xianyufpga/p/11353455.html
Copyright © 2011-2022 走看看