• Testbench代码设计技巧


    Testbench代码设计技巧

    " There are many ways " to code a test case, it all depens on the creativity ot the Testbench designer.

    Testbench代码设计技巧 1

    1. Clock logic设计技巧 1

    2. Asynchronous reset设计技巧 1

    3. System task之打印数据 2

    4. System task之生成.vcd文件 3

    5. System task之生成vec(vector file)档 3

    1. Clock logic

    为方便对时钟进行修改,已经后续代码中的应用,定义为parameter或者`define更为方便,如下所示:

    //-------------------------------

    //clock units

    parameter PERIOD = 20; //20ns,50MHz

    always

    #(PERIOD/2) clk = !clk;

    2. Asynchronous reset

    意在设计一个异步复位的信号,故可在clk下降沿复位,同时也在clk下降沿释放。因此在testbench中我们要设计一段“释放→复位→释放”的代码。“event”是在testbench中能被触发,同时也能被监视的事件,过程如下:

    1) 释放

    2) 在某一时刻reset_trigger 触发事件

    3) 等待clk下降沿,复位

    4) 等待下一个下降沿,释放

    5) 触发reset_done_trigger事件(可在其他testbench中应用)

    代码如下所示:

    //-------------------------------

    //asynchronous reset event(low valid)

    event reset_trigger;

    event reset_done_trigger;

    initial

    begin

    forever

    begin

    @(reset_trigger);

    @(negedge clk);

    rst_n = 0;

    @(negedge clk);

    rst_n = 1;

    -> reset_done_trigger;

    end

    end

    //-------------------------------

    //asynchronous reset

    initial

    #50 -> reset_trigger;

    如上代码所示50ns后启动异步复位信号,波形如下所示。可见输出数据都为三态,知道复位开始有效。

    wps_clip_image-27514

    注:在时序严谨的工程中,asynchronous reset必须同步化,言外之音,此处画龙点睛介绍此方法!

    wps_clip_image-30344

    1) 设计verilog代码,用触发器对异步复位信号同步化

    2) 整合例化

    3) 编译,仿真调试

    4) 在Instance中选择sync_ctrl下的sys_rst_n信号进行观察

    wps_clip_image-2617

    代码和波形如下所示:

    `timescale 1ns / 1ns

    module sync_ctrl

    (

    input clk,

    input rst_n,

    output sys_rst_n

    );

    //--------------------------------------

    //asynchronous rst_n synchronism

    reg     rst_nr1, rst_nr2;

    always @(posedge clk or negedge rst_n)

    begin

    if(!rst_n)

    begin

    rst_nr1 <= 1'b0;

    rst_nr2 <= 1'b0;

    end

    else

    begin

    rst_nr1 <= 1'b1;

    rst_nr2 <= rst_nr1;

    end

    end

    assign sys_rst_n = rst_nr2;

    Endmodule

    wps_clip_image-29705

    3. Asynchronous enable

    雷同以上异步reset信号,用event来完成对enable的仿真。此处异步enable信号在异步reset完成后,维持10clk,之后释放。在是能有效的时候addout自增,代码和波形如下所示:

    //-------------------------------

    //asynchronous reset & enable

    initial

    begin

    #10 -> reset_trigger; //asynchronous reset

    @(reset_done_trigger); //reset done

    @(negedge clk); //asynchronous enable

    enable = 1;

    repeat(10) //hold 10 cycles

    begin

    @(negedge clk);

    enable = 0; //asynchronous release

    end

    endwps_clip_image-15780

    此处

    4. Reset & enable random

    自然是随机的,因此极端情况下,我们也可以把异步复位和使能信号设置为随机信号,如下所示:

    //------------------------------

    //asynchronous reset & enable with random

    initial

    begin

    #10 -> reset_trigger;

    @(reset_done_trigger);

    fork

    repeat(10)

    begin

    @(negedge clk)

    enable = $random;

    end

    repeat(10)

    begin

    @(negedge clk)

    #100 rst_n = $random;

    end

    join

    End

    wps_clip_image-10913

    5. Simulation Terminate

    以上可见到,其实异步enable信号的initial到10个clk以后,test case没完,但是simulate 已经终止了。但如果有到个test case,每个case simulate完都进入terminate_sim,进行某些操作,会很方便。可在代码中稍作修改,写成terminate_sim的event,代码如下:

    //-------------------------------

    //asynchronous reset & enable

    event terminate_sim;

    initial

    begin

    #10 -> reset_trigger; //asynchronous reset

    @(reset_done_trigger); //reset done

    @(negedge clk); //asynchronous enable

    enable = 1;

    repeat(10) //hold 10 cycles

    @(negedge clk);

    enable = 0; //asynchronous release

    #10 -> terminate_sim;

    end

    //------------------------------

    //terminate state

    initial

    begin

    @(terminate_sim);

    $display("Terminating Simulation!");

    #10 $finish;

    end

    6. Task任务模块

    对于需要多次操作或者循环的任务,可以用task封装,方便调用。

    此处只做简单的介绍:

    //-------------------------------

    //stimulate random drive

    task din_task;

    begin

    //for()

    din1 = $random % 256;

    din2 = $random % 256;

    end

    endtask

    always@(negedge clk)

    datain_task;wps_clip_image-10604

    7. System task之自检Error

    在系统模拟验证中,采用比较模拟验证法代替波形观察法,以提高效率.

    无非是复制verilog中的内容,再写一遍,结果是不是一样,没有什么需要提的.

    8. System task之打印数据

    //-------------------------------

    //print the value to screen

    initial begin

    $display(" time, dout");

    $monitor("%d, 4'h%x,",$time,dout);

    end

    Display: 正如C语言中的printf

    Monitor: 比print个稍微强大点,实时监测数据变化,变化的时候输出数据

    如下图所示,数据打印到screen如下(monitor检测的数据输出不能顶格很郁闷)

    wps_clip_image-12852

    9. System task之生成vcd文件

    Vcd文件即为value change dump,用固定格式保存波形数据。

    //-------------------------------

    //save the warmform

    initial begin

    $dumpfile("wave_test.vcd" );

    $dumpvars;

    End

    当本次仿真结束的时候,将波形数据保存到wave_test.vcd中,一边以后用warmform viewer查看。如下所示(不知道怎么看~~~~(>_<)~~~~ ):

    wps_clip_image-17685

    10. System task之生成vec文件

    Vec文件即为vector file矢量数据文件,用于Modelsim中保存数据的文件,在仿真测试中,相关数据测试,在必要的情况下有很大的好处。相关testbench代码如下所示,保存了仿真400ns过程中addout的变化:

    //-------------------------------

    //generate vector file

    integer openfile;

    initial

    begin

    //output to "wave_test.vec" and standard display

    openfile = $fopen("wave_test.vec");

    //generate header file of vector file

    $fdisplay(openfile,"/*------------------------------------------------------------------------");

    $fdisplay(openfile,"This confidential and proprietary software may be only used as authorized");

    $fdisplay(openfile,"by a licensing agreement from CrazyBingo.");

    $fdisplay(openfile,"(C) COPYRIGHT 2012 CrazyBingo. ALL RIGHTS RESERVED");

    $fdisplay(openfile,"This is the wave_test.vec vector file");

    $fdisplay(openfile,"-------------------------------------------------------------------------*/");

    $fdisplay(openfile," time, addout");

    //output all the information of node transition in the vector file

    $fmonitor(openfile,"%d, 4'h%x",$time,addout);

    end

    生成的文件信息如下所示:

    wps_clip_image-3764

    11. Others

    $display,$fdisplay,$monitor,

    $strobe,$fopen,$fclose,$dump,$finish,

    $time,$write,$stop

    $random

    1) fork...join:并行任务

    2) integer i;for(i=0,i<256,i++) 循环

    3) $readmemb(“File_Name”, Test_Vector);  从文件中读取二进制输入激励码向量

    4) $readmemh(“File_Name”, Test_Vector); 从文件中读取二进制输入激励码向量

    5) reg [7:0] stim_array[0:15] 数组的运用

    转自:http://www.cnblogs.com/crazybingo/archive/2012/02/18/2356682.html#commentform

  • 相关阅读:
    保研练习题(5)
    保研练习题(4)
    保研练习题(3)
    保研练习题(2)
    保研练习题(1)
    基于邻接矩阵的拓扑排序--升级版
    基于邻接矩阵的拓扑排序
    vue 父组件调用子组件的函数
    vue 子组件调用父组件的函数
    JS 打乱数组顺序
  • 原文地址:https://www.cnblogs.com/lueguo/p/3581142.html
Copyright © 2020-2023  润新知