精华内容
下载资源
问答
  • Plug ' kdurant/verilog-testbench ' 用法 运行:Testbench生成testbench模板 运行:VerilogInstance生成组件实例 运行:VerilogInterface生成接口(SystemVerilog)模板 运行:VerilogClass生成类(SystemVerilog)模板...
  • Verilog测试:TestBench结构

    万次阅读 多人点赞 2019-07-18 09:18:55
    1. 完整的TESTBENCH文件结构 2.时钟激励产生 3.复位信号设计 4.双向信号设计 5. 特殊信号设计 6.仿真控制语句以及系统任务描述 7.加法器的仿真测试文件编写   Verilog功能模块HDL设计完成后,并不代表设计...

    目录

    1. 完整的TESTBENCH文件结构

    2.时钟激励产生

    3.复位信号设计

    4.双向信号设计

    5. 特殊信号设计

    6.仿真控制语句以及系统任务描述

    7.加法器的仿真测试文件编写


      

    Verilog功能模块HDL设计完成后,并不代表设计工作的结束,还需要对设计进行进一步的仿真验证。掌握验证的方法,即如何调试自己的程序非常重要。在RTL逻辑设计中,要学会根据硬件逻辑来写测试程序即写Testbench。Verilog测试平台是一个例化的待测(MUT)模块,重要的是给它施加激励并观测其输出。逻辑块与其对应的测试平台共同组成仿真模型,应用这个模型就可以测试该模块能否符合自己的设计要求。

      编写TESTBENCH的目的就是为了测试使用HDL设计的电路,对其进行仿真验证、测试设计电路的功能、性能与设计的 预期是否相符。通常,编写测试文件的过程如下:

    •        产生模拟激励(波形)
    •       将产生的激励加入到被测试模块中并观察其响应;
    •       将输出响应与期望值比较。

    1. 完整的TESTBENCH文件结构

     

    module Test_bench()//一般简单的测试文件无输入输出
    
    信号或变量声明定义
    
    逻辑设计中输入信号在这里对应reg型变量
    
    逻辑设计中的输出信号在这里对应wire型
    
    使用initial或always语句块产生激励
    
    例化猜测是模块UT
    
    监控和比较输出响应
    
    endmodule

    2.时钟激励产生

     下面列举一些常用的生成时钟激励的方法:

    方法一: forever

    //*========================================================
                   50%占空比时钟
    ==========================================================*//
    parameter ClockPeriod = 10 ;
    
    initial
      beign
       clk_i = 0;
      forever 
        # (ClockPeriod/2) clk_i = ~clk_i ;
      
     end

    方法2: always块

    //=========================================================
                         50%时钟占空比
    ==============================================================*/
    Parameter ClockPeriod = 10 ;
    
    initial
       begin
    
        clk_i =0 ;
        always #(ClockPeriod/2) clk_i =~clk_i ;
      end

    方法3:产生固定数量的时钟脉冲

    parameter CloclPeriod = 10 ;
    
    initial
      begin
         clk_i = 0 ;
        repeat(6)
          #(ClockPeriod/2) clk_i =~ clk_i;
    
       end

    方法4:产生占空比非 50%的时钟

    parameter ClockPeriod  =  10 ;
    
    initial
       begin
    
          clk_i = 0 ;
          forever
             begin
               #((ClockPeriod/2)-2) clk_i = 0 ;
              #((ClockPeriod/2)+2) clk_i = 1;
             end
       end
    

    3.复位信号设计

    方法1:异步复位

    initial
       begin
         rst_n_i = 1 ;
         #100 ;
        rst_n_i = 0 ;
        #100 ;
        rst_n_i = 1;
      
       end

    方法2:同步复位

    initial
       begin
        rst_n_i = 1;
        @(negedge clk_i)  
            rst_n_i = 0;
        #100 ;    //这里给的是固定时间复位
       
        repeat(10) @(negedge clk_i) ;  //这里可以设置 固定数量的时钟周期
        @(negedge clk_i)
          rst_n_i = 1;
        end 
       

    方法3:对复位进行任务封装

    task reset ;
       input[31:0] reset_timer  ; //将复位的时间作为输入,达到复位时间可调的目的
       RST_ING = 0              ;//复位的方式可调,低电平有效或高电平有效
       begin
          rst_n = RST_ING ;   //复位中 
          #reset_time         //设置的复位时间
          rst_n_i = ~ RST_ING ;
       end
    endtask
    

    4.双向信号设计

    双向信号的描述方式并不唯一,常用的方法如下:

    描述方式1: inout在testbench中定义为wire型变量

    //为双向端口设置中间变量inout_reg作为intou的输出寄存,其中inout变量定义为wire型,使用输出使能控制
    //传输的方向
    //inout bir_port;
    
    wire birport      ;  //将双向接口变量定义为wire型
    reg  bir_port_reg ;  //定义一个reg型的中间变量,作为双向口的输出寄存
    reg  bi_port_oe   ;  //定义输出使能,用于控制传输的方向
    
    assign birport = (bir_port_oe)?bir_port_reg:1'bz;
    

    描述方式2:强制force

    当双向端口作为输出端口时,不需要对其进行初始化,而只需开通三态门;当双向接口作为输入时,只需要对其初始化,并关闭三态门,初始化赋值需要使用wire数据,通过force命令来对双向端口进行输入赋值

    //assign dinout = (!en)din: 16'hz ; 完成双向赋值
    
    initial
      begin
        for dinout = 20 ;
        #200 
        force dinout = dinout -1 ;
      
      end

    5. 特殊信号设计

    1.输入信号任务的封装

    方便产生激励数据。

    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
    
    //调用该task的方法: i_data(8'hXX) ;

    2.多输入信号任务封装

    task more_input;
    
    input [7:0] a;
    input [7:0] b;
    input [31:0] times ;
    output[8:0] c;
    
    begin
       repeat(times)                //等待times个时钟上升沿
        @(posedge clk_i)    
             c= a+b ;//时钟上升沿, a和b相加
    end
    
    endtask
    
    //调用方法: more_input(x,y,t,z);

    3.输入信号产生,一次SRAM写信号产生

    initial
        begin
            cs_n = 1 ;     //片选无效
            wr_n = 1 ;     //写使能无效
            rd_n =1  ;     //读使能无效
            addr = 8'hxx;  //地址无效
            data = 8'hxx;  //数据无效
            #100 ;
    
            cs_n = 0 ;
            wr_n = 0 ;
            addr = 8'hF1 ;
            data = 8'h2C ;
            #100  ;
            
            cs_n = 1;
            wr_n = 1 ;
            #10  ;
    
            addr = 8'hxx;
            data = 8'hxx;
        end

    Testbench中的 和 wait

    //wait都是使用电平触发

    intial
      begin
         start = 1'b1    ;
         wait(en = 1'b1) ;
         #10;
         start = 1'b0    ;
    
    end

     

    6.仿真控制语句以及系统任务描述

    仿真控制语句以及系统能够任务描述: 

    $stop        //停止运行仿真,modelsim中可以继续仿真
    $stop(n)     //带参数系统任务,根据参数0,1,或2不同,输出仿真信息
    $finish      //结束运行仿真,不可继续仿真
    $finish(n)   //带参数系统任务,根据参数的不同:0,1或2,输出仿真信息
                     // 0: 不输出任何信息
                    // 1: 输出当前仿真时刻和位置
                   // 2:输出房前仿真时刻、位置和仿真过程中用到的memory以及cpu时间的统计
    $random        //产生随机数
    $random%n     //产生范围-n到n之间的随机数
    {$random}%n    //产生范围0到n之间的随机数
    

    仿真终端显示描述

    $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位整型时间
    $realtiime //实行实型模拟时间

    文本输入方式:$readmemb /$readmemh

    //激励具有复杂的数据结构 
    
    //verilog提供了读入文本的系统函数 
    $readmemb/$readmemh("<数据文件名>",<存储器名>); 
    $readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>); 
    $readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>,<结束地址>); 
    
    $readmemb:
         /*读取二进制数据,读取文件内容只能包含:空白位置,注释行,二进制数 
    数据中不能包含位宽说明和格式说明,每个数字必须是二进制数字。*/ 
    
    $readmemh: /*读取十六进制数据,读取文件内容只能包含:空白位置,注释行,十六进制数数据中不能包含位宽说明和格式说明,每个数字必须是十六进制数字。*/ 
    
     /*当地址出现在数据文件中,格式为@hh...h,地址与数字之间不允许空白位置, 可出现多个地址*/
    module ;
    
    reg [7:0] memory[0:3];//声明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
    endmodule

    mem.dat的文件内容格式:

    //mem.dat文件内容
    @001
    AB CD
    @003
    A1 
     
    //仿真输出为
    // Memory[0] = xx;
    // Memory[1] = AB; 
    //Memory[2] = CD; 
    //Memory[3] = A1; 

     

     

    7.加法器的仿真测试文件编写

         上面只例举了常用的 testbench 写法,在工程应用中基本能够满足我们需求,至于其他更为复杂的 testbench写法,大家可参考其他书籍或资料。 

         这里提出以下几点建议供大家参考: 

    •               封装有用且常用的 testbench,testbench 中可以使用 task 或 function 对代码进行封装,下次利用时灵活调用即可;
    •              如果待测试文件中存在双向信号(inout)需要注意,需要一个 reg 变量来表示输入,一个 wire 变量表示输出; 
    •              单个 initial 语句不要太复杂,可分开写成多个 initial 语句,便于阅读和修改;
    •              Testbench 说到底是依赖 PC 软件平台,必须与自身设计的硬件功能相搭配。

    下面具体看一段程序:

    module add(a,b,c,d,e);// 模块接口 
    input [5:0] a; // 输入信号a 
    input [5:0] b; // 输入信号b 
    input [5:0] c; // 输入信号a 
    input [5:0] d; // 输入信号b 
    
    output[7:0] e; // 求和输出信号 
    
    wire [6:0]outa1,outa2; // 定义输出网线型 
    assign e = outa2+outa1; // 把两部分输出结果合并 
    
    /* 
    通常,我们模块的调用写法如下: 
    被调用的模块名字- 自定义的名字- 括号内信号 
    这里比如括号内的信号,.ina(ina1) 
    这种写法最常用,信号的顺序可以调换 
    另外还有一种写法没可以直接这样写 
    adder u1 (ina1,inb1,outa1); 
    这种写法必须确保信号的顺序一致,这种写法几乎没有人采用 */ 
    
    adder u1 (.ina(a),.inb(b),.outa(outa1)); // 调用adder 模块,自定义名字为u1 
    adder u2 (.ina(c),.inb(d),.outa(outa2)); // 调用adder 模块,自定义名字为u2
    endmodule 
    //adder 子模块 
    
    module adder(ina,inb,outa );// 模块接口 
    input [5:0] ina; // ina-输入信号 
    input [5:0] inb; // inb-输入信号 
    output [6:0] outa; // outa-输入信号 
    assign outa = ina + inb; // 求和 
    endmodule // 模块结束 

    仿真文件:

    `timescale 1ns / 1ps 
    module add_tb(); 
    
    reg [5:0] a;
    reg [5:0] b; 
    reg [5:0] c; 
    reg [5:0] d; 
    wire[7:0] e; 
    reg [5:0] i; //中间变量 
    
    // 调用被仿真模块模块 
    add uut (
    .a(a), 
    .b(b),
    .c(c),
    .d(d),
    .e(e)); 
    
    initial 
         begin    // initial 是仿真用的初始化关键词 
           a=0 ;  // 必须初始化输入信号 
           b=0 ;
           c=0 ;
           d=0  
              for(i=1;i<31;i=i+1)
                 begin 
                  #10 ; a = i; b = i; c = i; d = i; 
                 end
          end 
    initial 
        begin 
           $monitor($time,,,"%d + %d + %d + %d ={%d}",a,b,c,d,e); // 信号打印输出
           #500 
           $finish; 
        end 
    endmodule 
            
    

     

    仿真波形:

    终端显示:

     

     

     

     

     

    展开全文
  • 针对VerilogTestbench 例程,需要写Testbench 可以参考……
  • testbench实例

    2021-01-13 15:22:51
    Verilog Testbench与仿真 Verilog Testbench与仿真为通过软件验证Verilog语言设计实例的逻辑功能,需要编写 Testbench,也称为测试模块,并通过仿真软件ModelSim进行仿真。 ...test/confirm 用 HDL 写出来的测试文件...

    Verilog Testbench与仿真 Verilog Testbench与仿真为通过软件验证Verilog语言设计实例的逻辑功能,需要编写 Testbench,也称为测试模块,并通过仿真软件ModelSim进行仿真。 ...

    test/confirm 用 HDL 写出来的测试文件称为 test bench 被测试的模块成为 ...模块实例化 测试中常用的波形有两类: initial 块及块内延迟来产生特定序列 ......

    verilog HDL 的系统任务及 testbench 写法硬件知识 2010...

    end 用HDL代码生成DUT的输入激励码 module TestBench_Name ; 参数说明; 寄存器、线网类型变量的定义、说明; DUT的输出端口 必须连线网类型 的变量 DUT 实例语句;......

    编写testbench的一些技巧_计算机软件及应用_IT/计算机_专业资料。1 Testbench 的结构 1) 单顶层结构 一种结构是 testbench 只有一个顶层,顶层再把所有的模块实例......

    (2)映射后仿 真和布局布线后仿真都要用到 SDF 文件, 并且要将 SDF 文件关联到设计中的实例。 所以在映 射后仿真和布局布线后仿真的 testbench 中,第一,要......

    ? ? 7 例1:使用元件实例化方法编写的testbench ---目标文件fu...

    如图所示是一个标准的 HDL 验证流程,图中表达了上述的 Testbench 功能。 TestBench 的主要目标是: 实例化 DUT-Design Under Test 为 DUT 产生激励波形 产生参考......

    08:29 56 Testbench实例 ? ? ..\\..\\verilog_H...

    55. 56. i1 : cnt6 PORT MAP ( clk => clk, clr => clr, en => en, q => q ); --实例名称,i 为 instance 缩写 --端口映射,把 testbench ......

    4 结构化 Testbench 的设计实例 end endtask endmod...

    一般在 testbench 的开头定义时间单位和仿真精度,比如`timescale 1ns/1ps 前面一个是代表时间单位,后面一个代表仿真时间精度。 以上面的例子而言,一个时钟周期是 ......

    endcase /*共同的测试向量*/ end end .3 如何加速问题定位过程 在这部分里,通过一些实际例子,介绍在出现问题时如何借助 testbench 加快问题的定位过 程。 1、......

    编写Testbench技巧和要求 模块例化--位置映射的说明 1 可以将模块的实例通过端口连接起来构成 一个大的系统或原件 2 在上面的例子中,REG4有模块DFF的四个实例。...

    2、开始写testbench 单击New File ? 如右图,单击New File弹出一个名称 为...后两个 分别为A和B的输入; – inst是AND_2实例化的名; – initial语句和......

    (Stimulus) 实例化DUT (Design Under Test) 使用仿真工具比 较仿真结果 自动比较测试结 果的正确性 从图中可以清晰地看出Testbench的 主要功能: (1)为DUT提供......

    仿真实例分析本文以一个虚拟的 xlab 项目为例,基于 linux OS 平台,详细分析了通过 testbench 和仿 真模型等对 DUT (Design Under Test) 加入激励, 对 DUT ......

    跳出编辑窗 口 在菜单栏中 选中 Source->show Language Templates,然后在 Language Templates 中撞击 Create Testbench, 图3.Testbench 创建向导 然后在 work 下面......

    现在问题就出 在编写 testbench 仿真总线 inout 口,能看到测试模块给源模块的...xcykii (2010-4-16 20:28:31) tb 里面实例化的时候用 tri 类型的 net ......

    49" // Verilog Test Bench template ...

    展开全文
  • verilog编写testbench的注意事项,有实例辅助说明
  •   楼主在初学verilog的时候就一直对testbench该怎么写感到困惑,之后的学习过程中也陆陆续续地看过一些testbench文件,其中有一些其实相当于就在testbench里重写了一下要验证地模块,个人感觉这有点”鸡生蛋“和”...

      楼主在初学verilog的时候就一直对testbench该怎么写感到困惑,之后的学习过程中也陆陆续续地看过一些testbench文件,其中有一些其实相当于就在testbench里重写了一下要验证地模块,个人感觉这有点”鸡生蛋“和”蛋生鸡“那味儿了。虽说在testbench里写不用考虑能否综合的问题,可以用一些更为方便的写法,但是终归还是用的Verilog体系内的语法,描述待测试模块预期的功能时很有可能会犯类似的错误,因此楼主觉得这种testbench的写法应付比较简单的模块可能还行,比较简单直接,但是应对复杂点的模块则出错的可能性偏大,不太可取。
      除了前述testbench的写法外,遍历穷举应该是常见的testbench写法之一,即借由高级语言穷举生成所有的输入和对应的输出,来比对模块的输出以达到验证的目的,因此本文就分享一个适用于这种穷举遍历思路的testbench模板,下面就借由一个原码输入原码输出的带饱和处理的减法器模块进行这一模板的写法说明。

    原码减法器

      选取被减数 A A A和减数 B B B的数据位宽为 4 4 4,输出结果 r e s res res的数据位宽也为4,设计框图如下
    在这里插入图片描述

    设计说明如下:

    1. 输入为原码(Sign-magnitude,SM)表示,而加减法一般习惯用二的补码(2’s compliment,2’s),因此先将 A A A B B B转换为补码形式,其中 B B B为被减数,可以考虑直接对(-B)进行补码转换,即上图中的红色减号,此时后续”减法“则转为加法进行;
    2. 二的补码加法比较简单,直接相加即可,本设计并不需要用到进位,因此可以只在模块内声明一下作为连线即可;
    3. 最后再进行溢出时的饱和处理,即溢出时符号位不变,幅值取最大值。具体到溢出的判断,本设计就不考虑最高位进位和次高位进位的溢出判断了,而是直接用输入和输出的符号位作为判断依据,比较直观。

    Verilog模块

      代码如下所示

    /**
     * @function:
     *   compute res = A - B and get sign-magnitude representation result
     * @input:
     *   A, B -> sign-magnitude representation
     * @output:
     *   res  -> sign-magnitude representation
    **/
    module SmSub #(
      parameter WIDTH = 4
    ) (
      input  [(WIDTH - 1) : 0] A,
      input  [(WIDTH - 1) : 0] B,
      output [(WIDTH - 1) : 0] res
    );
      
    
      wire [(WIDTH - 1) : 0] tmpA;         // magnitude part of A
      wire [(WIDTH - 1) : 0] complA;       // 2's complement representation of A
      wire [(WIDTH - 1) : 0] complB;       // 2's complement representation of B
      wire [(WIDTH - 1) : 0] complRes;     // 2's complement representation of res
      reg  [(WIDTH - 1) : 0] tmpRes;       // for negative result
      wire                   carry;
      reg  [(WIDTH - 1) : 0] satcomplRes;  // saturated complRes
      wire [(WIDTH - 1) : 0] negMax;       // maximum negative value using 2's complement representation
    
    
      // sign-magnitude -> 2's complement for A
      assign tmpA   = {1'b0, A[(WIDTH - 2):0]};
      assign complA = (1'b1 == A[(WIDTH - 1)]) ? ((~tmpA[(WIDTH - 1):0]) + 1) : A[(WIDTH - 1):0];
    
      // sign-magnitude -> 2's complement for (-B)
      assign complB = (1'b1 == B[(WIDTH - 1)]) ? {1'b0, B[(WIDTH - 2):0]} : ((~B[(WIDTH - 1):0]) + 1);
    
      // get result
      assign {carry, complRes} = complA + complB;
    
      // overflow process
      always @(*) begin
        case ({complA[(WIDTH - 1)], complB[(WIDTH - 1)], complRes[(WIDTH - 1)]})
          // postive spillover
          3'b001: begin
            satcomplRes = {1'b0, {(WIDTH - 1){1'b1}}};
          end
          // negtive spillover
          3'b110: begin
            satcomplRes = {1'b1, {(WIDTH - 1){1'b1}}};
          end
          // no spillover
          default: begin
            // 2's complement -> sign-magnitude for complRes
            tmpRes      = (~complRes[(WIDTH - 1):0]) + 1;
            satcomplRes = (1'b1 == complRes[(WIDTH - 1)]) ? {1'b1, tmpRes[(WIDTH - 2):0]} : complRes[(WIDTH - 1):0];
          end
        endcase
      end
    
      // handle special case N'b1000…000
      assign negMax = {1'b1, {(WIDTH - 1){1'b0}}};
      assign res    = (negMax[(WIDTH - 1):0] == satcomplRes[(WIDTH - 1):0]) ? {1'b1, {(WIDTH - 1){1'b1}}} : satcomplRes[(WIDTH - 1):0];
    
    endmodule
    

    matlab生成数据

      matlab代码如下所示,即穷举所有输入的情况,一共 2 4 × 2 4 = 256 2^4\times 2^4=256 24×24=256种,算出对应的输出,借由dec2bin()函数转为二进制形式写入到result.txt文件中,以供testbench读入。

    注:下列代码整体风格其实与C很像,之所以不用C而是用matlab只是图matlab里有现成的十进制转二进制函数罢了……

    dataWidth = 4;
    fileName = "../result.txt";
    fileID = fopen(fileName, "w");
    
    dataNum = power(2, dataWidth);
    magnitudeMax = power(2, dataWidth - 1) - 1;
    result = zeros(dataNum, dataNum);
    for i = 1 : dataNum
        for j = 1 : dataNum
            % convert to sign-magnitude representation
            if (i <= power(2, dataWidth - 1)) 
                tmpI = i - 1;
            else
                tmpI = power(2, dataWidth - 1) + 1 - i;
            end
            if (j <= power(2, dataWidth - 1)) 
                tmpJ = j - 1;
            else
                tmpJ = power(2, dataWidth - 1) + 1 - j;
            end
            tmpRes = tmpI - tmpJ;
    
            % saturated the results and convert to binary representation
            if tmpRes < 0
                if abs(tmpRes) >= magnitudeMax      % saturated
                    fprintf(fileID, "%s\n", dec2bin(magnitudeMax + power(2, dataWidth - 1), dataWidth));        % sign-magnitude representation
                else
                    fprintf(fileID, "%s\n", dec2bin(abs(tmpRes) + power(2, dataWidth - 1), dataWidth));
                end
            else
                if tmpRes >= magnitudeMax           % saturated
                    fprintf(fileID, "%s\n", dec2bin(magnitudeMax, dataWidth));
                else
                    fprintf(fileID, "%s\n", dec2bin(tmpRes, dataWidth));
                end
            end
        end
    end
    
    fclose(fileID);
    

    testbench编写

      本文的重头戏来了,先放代码

    `timescale 1 ns/ 10 ps
    `define period	10
    
    module SmSub_tb();
    /********** 1. ports and signal declaration **********/
      reg  [3:0] A;
      reg  [3:0] B;
      wire [3:0] res;
    
      reg [3:0] refResMem[0:(16 * 16 - 1)];
    
      integer i;
      integer j;
      integer tmpIdx;
      integer errCnt;
      
    /********** 2. module instantiation and assignment **********/
      SmSub #( 
        .WIDTH(4) 
      ) uut0 (
         .A(A),
         .B(B),
         .res(res)
        );
    	
    /********** 3. Initialization **********/
      initial begin
        errCnt = 0;
        $readmemb("./sim/result.txt", refResMem);
    
        for (i = 0; i < 16; i = i + 1) begin
          for (j = 0; j < 16; j = j + 1) begin
            A = i;  B = j;
            #(`period / 2) checkOutputs;
            #(`period / 2);
          end
        end
    
        if (errCnt) begin
          $display("***************** Total Errors: %d *****************\n", errCnt);
        end
        else begin
          $display("***************** No Errors! *****************\n");
        end
        #(`period*10) $stop;
    	end           
    
      /********** 4. check part **********/
      task checkOutputs;
        begin
          tmpIdx = (i * 16) + j;
          if (res != refResMem[tmpIdx]) begin
            error;
          end
        end
      endtask
    
      task error;
        begin
          errCnt = errCnt + 1;
          $display("ERROR AT %d: expected -> %h, get -> %h", tmpIdx, refResMem[tmpIdx], res);
        end
      endtask
    
    endmodule
    

    说明如下:

    • 第一部分就是testbench都有的端口和接下来要用的信号声明;
    • 第二部分是测试模块的实例化,较为复杂点的模块可能还需要在testbench里额外添加一些连线;
    • 第三部分为初始化,先将错误计数变量初始化为0,再用系统函数$readmemb/$readmemh将前一步用matlab生成的参考输出读入,而考虑到本模块中的输入比较有规律,所以输入用整型变量ij产生,若数据量较大或不规律,可以参照前一步,用高级语言生成对应的输入文件读入。再之后,每产生一个输入,就调用对应的checkOutputs任务进行输出对比,如果存在错误则调用error任务进行错误处理即打印出错信息到终端,并对错误进行计数。最后则是检查错误个数,打印对应的输出信息,并调用$stop中止仿真。
    • 第四部分即输出对比函数和错误处理函数,本设计并不复杂,所以只是简单的比对仅有的一个输出,错误处理也只是单纯地打印,并不算复杂;

    总结

      这一模板是楼主学Verilog以来感觉比较好用的一个,当然了,这种遍历穷举的验证方式在实际工程中还是有不小局限性的,输入比特数较大时往往就只能随机生成众多输入情况的一部分进行验证了,最终还是要借助于系统的验证方法学。尽管如此,个人感觉这一模板还是对初学Verilog的人来说还是比较友好的!

    展开全文
  • `timescale 1ns/100psmodule testbench;localparam DATA_WIDTH = 32;localparam CLK_100_PERIOD = 5;localparam CLK_200_PERIOD = 2.5;localparam SIM_TIME = 150000;localparam ;localparam ;reg clk_100, clk_200;...

    `timescale 1ns/100ps

    module testbench;

    localparam DATA_WIDTH = 32;

    localparam CLK_100_PERIOD = 5;

    localparam CLK_200_PERIOD = 2.5;

    localparam SIM_TIME = 150000;

    localparam ;

    localparam ;

    reg clk_100, clk_200;

    wire clk;

    assign clk = clk_100;

    always

    begin

    clk_100 = 0;

    forever #CLK_100_PERIOD clk_100 = ~clk_100;

    end

    always

    begin

    clk_200 = 0;

    forever #CLK_200_PERIOD clk_200 = ~clk_200;

    end

    reg rstn;

    integer fp_testin;

    integer fp_matlab_out;

    integer fp_sim_out;

    integer fp_outdiff;

    reg signed [DATA_WIDTH/2-1:0] matlab_in_re,   matlab_in_im;

    reg signed [DATA_WIDTH/2-1:0] matlab_out_re,  matlab_out_im;

    reg signed [DATA_WIDTH/2-1:0] matlab_diff_re, matlab_diff_im;

    reg signed [DATA_WIDTH/2-1:0] matlab_diff_re2, matlab_diff_im2;

    reg signed [DATA_WIDTH/2-1:0] max_diff_re,    max_diff_im;

    initial begin

    max_diff_re = 0;

    max_diff_im = 0;

    rstn = 0;

    #500

    rstn = 1;

    #SIM_TIME

    sim_finish();

    $stop();

    end

    task sim_finish;

    begin

    if(fp_testin!=0)

    $fclose(fp_testin);

    if(fp_matlab_out!=0)

    $fclose(fp_matlab_out);

    if(fp_sim_out)

    $fclose(fp_sim_out);

    if(fp_outdiff!=0)

    $fclose(fp_outdiff);

    end

    endtask

    initial

    begin

    fp_testin = 0;

    fp_testin= $fopen("txt_file/input_data.txt","r");

    if(fp_testin==0)

    begin

    $display("input_data.txt open failed!");

    sim_finish();

    $stop();

    end

    else begin

    $fscanf(fp_testin, "%d, %d\n",matlab_in_re,matlab_in_im);

    end

    fp_matlab_out = 0;

    fp_matlab_out = $fopen("txt_file/matlab_out.txt","r");

    if(fp_matlab_out==0)

    begin

    $display("fp_matlab_out.txt open failed!");

    sim_finish();

    $stop();

    end

    else begin

    $fscanf(fp_matlab_out,"%d, %d\n",matlab_out_re,matlab_out_im);

    end

    fp_sim_out = 0;

    fp_sim_out = $fopen("txt_file/modelsim_out.txt","w");

    if(fp_sim_out == 0)

    begin

    $display("modelsim_out_re.txt open failed!");

    sim_finish();

    $stop();

    end

    fp_outdiff = 0;

    fp_outdiff = $fopen("text_file/outdiff.txt","w");

    if(fp_outdiff==0)

    begin

    $display("outdiff.txt open failed!");

    sim_finish();

    $stop();

    end

    end

    always @(posedge clk)

    begin

    if(stest_wvalid && stest_wready)         //ready to change

    begin

    if(~$feof(fp_testin))

    $fscanf(fp_testin, "%d, %d\n",matlab_in_re,matlab_in_im);

    end

    else

    begin

    matlab_in_re <= matlab_in_re;

    matlab_in_im <= matlab_in_im;

    end

    end

    always @(posedge clk_100)

    begin

    if(mfc_wready && mfc_wvalid)

    begin

    matlab_diff_re  <= mfc_wdata_re  - matlab_out_re;

    matlab_diff_im  <= mfc_wdata_im  - matlab_out_im;

    matlab_diff_re2 <= matlab_out_re - mfc_wdata_re ;

    matlab_diff_im2 <= matlab_out_im - mfc_wdata_im ;

    if(max_diff_re < matlab_diff_re)

    begin

    max_diff_re <= matlab_diff_re;

    $display("max_diff_re:%d max_diff_im:%d\n",max_diff_re,max_diff_im);

    end

    else if(max_diff_re < matlab_diff_re2)

    begin

    max_diff_re <= matlab_diff_re2;

    $display("max_diff_re:%d max_diff_im:%d\n",max_diff_re,max_diff_im);

    end

    if(max_diff_im < matlab_diff_im)

    begin

    max_diff_im <= matlab_diff_im;

    $display("max_diff_re:%d max_diff_im:%d\n",max_diff_re,max_diff_im);

    end

    else if(max_diff_im < matlab_diff_im2)

    begin

    max_diff_im <= matlab_diff_im2;

    $display("max_diff_re:%d max_diff_im:%d\n",max_diff_re,max_diff_im);

    end

    $fscanf(fp_matlab_out,"%d, %d\n",matlab_out_re,matlab_out_im);

    $fwrite(fp_sim_out, "%d, %d\n", mfc_wdata_re,mfc_wdata_im);

    $fwrite(fp_outdiff, "%d, %d\n",matlab_diff_re,matlab_diff_im);

    end

    end

    endmodule

    展开全文
  • Verilog testbench总结(一)

    万次阅读 多人点赞 2016-12-26 12:50:18
    对于testbench而言,端口应当和被测试的module一一对应。端口分为input,output和inout类型产生激励信号的时候,input对应的端口应当申明为reg, output对应的端口申明为wire,inout端口比较特殊,下面专门讲解。 1...
  •    在编写testbench做简单的模块功能验证时,initial初始化的过程块和模块的实例化是常见的两个块,这两者的执行顺序一般来说认为是并行执行的,但是笔者在实际仿真过程中发现并不是这样的,现举例记录和说明如下...
  • 基于脚本和testbench的ncverilogASIC仿真实例分析本文以一个虚拟的xlab项目为例,基于linuxOS平台,详细分析了通过testbench和仿真模型等对DUT(DesignUnderTest)加入激励,对DUT进行验证的方法。另外通过monitor,...
  • 笔者使用开发工具的是QuartusII在使用过程中也遇到很多问题不过经过咨询还是成功解决,下面是一个简单的二选一选择器的testbench。 先贴出来二选一多选器的模型 module muxtwo(out,a,b,sl); input a,b,sl; output...
  • VHDL与VerilogHDL的Testbench模板 一般而言,一个testbench需要包含的部分如下: (1)VHDL:entity 和 architecture的声明;Verilog:module declaration (2)信号声明 (3)实例化待测试文件 (4)提供仿真激励 ...
  • Verilog HDL代码 //led breathe display module led_breathe_display( input clk, input rst_n, output [3:0] led_data ); //--------------------------- //generate for 1us delay signal //...
  • Verilog测试(仿真)文件TestBench如何编写

    万次阅读 多人点赞 2020-07-27 01:24:35
    编写TestBench测试仿真文件 在Vivado软件中,在左侧的 Flow Navigator 窗口点击 Add Source, 选择 Add or create simulation sources,点击 Next,点击 Create File, 给测试文件命名,通常格式为 “tb_被测试模块名...
  • Testbench   内容来自启芯-System Verilog视频 ==============================================================  目录结构: 1、什么是验证? 2、验证目标? 3、验证过程 4、Testbench架构 5、testbench搭建 6、...
  • 改进基于VScode插件 在Vscode的插件安装目录找到上述图片插件安装位置 在替换out目录下的extension.js中 修改sendText中的命令 (实例化和激励共两个) ...Testbench 自动在当前目录下生成对应模块名的
  • Verilog testbench总结

    千次阅读 2019-01-20 16:23:06
    对于testbench而言,端口应当和被测试的module一一对应。端口分为input,output和inout类型产生激励信号的时候,input对应的端口应当申明为reg, output对应的端口申明为wire,inout端口比较特殊,下面专门讲解。 1)...
  • Verilogtestbench入门

    2016-04-20 12:39:00
    Test benchVerilog需要编写的测试文件。在module设计完成、综合之后我们需要通过测试文件完成对设计module的测试。 Test bench大致分为下面三个部分: 时钟控制 clock control 一般采用always实现 实例化...
  • 转自:https://blog.csdn.net/times_poem/article/details/52036592需求说明:Verilog设计基础内容 :testbench的设计 读取文件 写入文件来自 :时间的诗十大基本功之 testbench1. 激励的产生对于 testbench 而言,...
  • ModelSim-TestBench完整设计方法及实例

    千次阅读 2020-07-21 23:28:10
    2 ModelSim介绍及仿真流程 ModelSim是Model Technology(Mentor Graphics的子公司)的HDL硬件描述语言的仿真软件,该软件可以用来实现对设计的VHDL、Verilog HDL 或是两种语言混合的程序进行仿真,同时也支持IEEE...
  • VHDL与Verilog硬件描述语言在数字电路的设计中使用的非常普遍,无论是哪种...VHDL与Verilog语言的语法规则不同,它们的TestBench的具体写法也不同,但是应包含的基本结构大体相似,在VHDL的仿真文件中应包含以下几点...
  • 三、TestBench 左边导航栏(Flow Navigator)选择 A d d S o u r c e s → A d d   o r   c r e a t e   s i m u l a t i o n   s o u r c e s → C r e a t e   F i l e Add Sources \rightarrow Add\ or\ ...
  • CPU 接口仿真实例 3.1 设计简介 3.2 一种 testbench 3.2.1 进入工程目录 3.2.2 运行仿真 3.2.3 查看仿真结果 3.3 另一种 testbench 4. 结构化 testbench 思想 4.1 任务和函数 4.2 总线模型重用 4.3 测试套具 4.4 ...
  • Modelsim联合仿真时,需要自行编写TestBench来产生激励信号,下面进行简要的介绍。 对于2选1数据选择器,其verilog代码如下: module mux21( input a,b,c, output y; assign y=(a&~c)|(b&c); ...
  • 一、TestBench简介 一个完整的设计,除了好的功能描述代码,对于程序的仿真验证是必不可少的。学会如何去验证自己所写的程序,即如何调试自己的程序是一件非常重要的事情。而 RTL 逻辑设计中,学会根据硬件逻辑来写...
  • 原文链接:testbench编写流程的简单举例 ———————————————— 目录顶层结构生成clk_tb生成resetb初始化变量DUT例化写任务读任务测试实现仿真结果参考文献 顶层结构 将模块device_regs_withfunction作为...
  • Verilogtestbench的设计,文件读取和写入操作

    万次阅读 多人点赞 2017-09-24 12:02:33
    对于 testbench 而言,端口应当和被测试的 module 一一对应。 端口分为 input,output 和 inout 类型产生激励信号的时候, input 对应的端口应当申明为 reg, output 对应的端口申明为 wire, inout 端口比较特殊,下面...
  • Verilog时序问题和SystemVerilog TestBench激励时序 学习笔记 最近我温习《SystemVerilog验证-测试平台编写指南(第二版)》这本书,看到了第4.3节,激励时序的问题,还是花了一些时间去看。SV这条路任重道远。本文中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,157
精华内容 462
关键字:

testbench实例verilog