zoukankan      html  css  js  c++  java
  • [转载]VHDL的testbench的编写

    来源:http://blog.ednchina.com/jlx_cuc/1993759/Message.aspx

    大多数硬件设计人员对verilog的testbench比较熟悉,那是因为verilog被设计出来的目的就是为了用于测试使用,也正是因为这样verilog的语法规则才被设计得更像C语言,而verilog发展到后来却因为它更接近C语言的语法规则,设计起来更加方便,不像VHDL那也死板严密,所以verilog又渐渐受到硬件设计者们的青睐。但其实VHDL在最开始也是具有测试能力的,而且它的语法严密,但我们同样可以用它来编写我们的测试文件。

    下面以一个8bit计数器为例子给出个简单的testbench模板及注释:

          

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_arith.all;
    use ieee.std_logic_unsigned.all;

    entity tb_CNT is
    end tb_CNT ;

    architecture testbench of tb_CNT is
    --Component Declaration for the Unit Under Test(UUT)
    component MY_CNT
    port(
    CLK,RESET:
    instd_logic;
    D_IN:
    instd_logic_vector(7downto0);
    LOAD:
    instd_logic;
    CE :
    instd_logic;
    UPDW:
    instd_logic;
    Q_OUT:
    outstd_logic_vector(7downto0)
    );
    endcomponent;

    --Inputs
    signal CLK: std_logic :='0';
    signal RESET: std_logic :='0';
    signal D_IN: std_logic_vector(7downto0):=(others=>'0');
    signal LOAD: std_logic :='0';
    signal CE: std_logic :='0';
    signal UPDW: std_logic :='0';
    --Outputs
    signal Q_OUT: std_logic_vector(7downto0);
    constant CLK_period: TIME:=1ns;
    begin
    --例化计数器模块
    UUT: MY_CNT
    portmap(
    CLK
    => CLK,
    RESET
    =>RESET,
    D_IN
    =>D_IN,
    LOAD
    =>LOAD,
    CE
    =>CE,
    UPDW
    =>UPDW,
    Q_OUT
    =>Q_OUT
    );
    --时钟实现模块
    --上面定义了CLK period时间常量来表示时钟周期
    --以下通过一个process来实现时钟
    CLK_process:
    process
    begin
    CLK
    <='0';
    waitfor CLK_period/2;
    CLK
    <='1';
    waitfor CLK_period/2;
    endprocess;
    --其它信号量的控制
    --时序逻辑的仿真的时间单位都为CLK周期来实现的
    --所以将时钟周期定义为常量是个很方便的做法

    stim_proc:
    process
    begin
    --hold reset state for 100ms.
    waitfor 100ms;

    waitfor CLK_period*10;
    --insert stimulus here.
    endprocess;
    end testbench;

    通过编写testbench来仿真和通过拖波形来仿真,最大的好处就是,当测试数据无比庞大时,可以简易得通过testbench中的算法来实现,而另一个更为重要的方面就是,可以通过testbench对数据文件进行读写操作,从而简化我们的仿真工作。

    首先介绍下时间控制语句——wait:(其实wait语句是通过控制仿真的两种状态——执行和挂起,来控制时间的)

    1.wait——无线等待;语法【wait;】,类似于Verilog中的¥Stop

    2.wait on——敏感信号量变化;语法【wait on 信号;】,表示当信号发生变化的时候,仿真开始继续执行,从而结束挂起状态

    3.wait until——条件满足;语法【wait until 表达式】,表达式为一个布尔表达式,表示当表达式为“真”时,仿真继续执行,结束挂起状态

    4.wait for——时间控制;语法【wait for 时间表达式】,例:【wait for 30ns;】

    VHDL也提供了文件I/O的操作,以下简单介绍在我们大部分情况下如何通过VHDL来进行文件操作。

    --File process
    file_process:
    process
    file file_out: textisout"data_out.txt";
    file file_in : text;
    variable fstatus: FILE_OPEN_STATUS;
    --定义文件状态指示变量,一般有OPEN OK, STATUS ERROR, NAME ERROR, MODE ERROR 四种状态;
    variable count: integer:=5;
    --定义integer 型写入数据;
    variable stringdata:string (5downto1):="whwhn";
    --定义string 型写入数据;
    variable vectordata: bit_vector(5downto0):="001000";
    --定义bit_vector 型写入数据;
    variable value:std_logic_vector(3downto0):="1111";
    --定义std_logic_vector型的写入数据;
    variable stddata:std_logic;
    variable BUFO:LINE;
    begin
    --file_open(fstatus,file_out,"data_out.txt",write_mode);
    file_open(fstatus,file_in,"data_in.txt",read_mode);

    file类型:文件句柄,用于定义文件。语法1【file 文件变量名:text is 读取或者写入类型 “文件名”;】text——文件类型为文本类型,读取类型为in,写入类型为out;语法2【file 文件变量名:text;】只是定义了文件变量名,并没有给赋予初值。

    用第二种方式定义文件变量则需要用到函数file_open();语法【file_open(文件状态指示,文件变量,“文件名”,读写状态);】如上图实例。

    LINE类型:如下图,为std库中TEXTIO文件中的定义


    --LINE类型:为std库中TEXTIO文件中的定义
    for i in0to29loop
    readline (file_in,BUF0);
    read(BUF0,stddata);
    LOAD
    <= stddata;
    waitfor CLK_period;
    endloop;

    LINE 为存取类型的变量,它表示该变量是指向字符串的指针,它是TEXTIO 中所有操作的基本单元。读文件时,先按行(LINE)读出一行数据,再对LINE 操作来读取各种数据类型的数据;写文件时, 先将各种的数据类型组合成LINE,再将LINE 写入文件。在用户使用时, 必须注意只有变量才可以是存取类型, 而信号则不能是存取类型。

    TEXTIO还定义了一些基本的文件操作过程:

    【READLINE(文件变量,行变量);】从指定的文件中读取一行。

    【READ(行变量,数据变量);】从一行中读取一个数据。

    【WRITELINE(文件变量,行变量);】将行变量中数据写入到指定文件。

    【WRITE(行变量,数据变量);】将数据写入到一行中。

    【WRITE(行变量,数据变量,起始位置,字符数);】比上个过程多了起始位置和字符数的指定。

    ---为循环从数据文件中读取出数据,赋值给信号量
    write(file_out,string'("the first parameter is="));
    write(BUF0,count);
    writeline(file_out,BUF0);
    waitfor20 ns;

    write(file_out,string'("the second parameter is="));
    write(BUF0,value);
    writeline(file_out,BUF0);
    waitfor20 ns;

    write(file_out,string'("the third parameter is="));
    write(BUF0,vectordata);
    writeline(file_out,BUF0);
    waitfor20 ns;

    write(file_out,string'("the forth parameter is="));
    write(BUF0,stringdata);
    writeline(file_out,BUF0);
    write(BUF0,string'("end of file"));
    writeline(file_out,BUF0);
    waitfor10 ns;

    waitfor2000 ns;
    file_close(file_out);
    file_close(file_in);
    endprocess;

    上图事例为循环从数据文件中读取出数据,赋值给信号量。

    --为了说明行变量与各个变量之间的转换,行变量可与任何变量类型进行转换,
    --并且原样输出到指定文件中。
    packageTEXTIOis
    --Type definitions fortext I/O;
    typeLINEisaccessSTRING; --A LINEis a pointer to a STRING value.
    typeTEXTisfileofSTRING; --A fileofvariable-length ASCII records.
    typeSIDEis (RIGHT,LEFT); --For justifying output data within fields.
    subtypeWIDTHis NATURAL; --For specifying widths ofoutput fields.

    上图事例为了说明行变量与各个变量之间的转换,行变量可与任何变量类型进行转换,并且原样输出到指定文件中。

    另外再推荐个语句:ASSERT——断言语句。它和VC中的_TRACE语句一样,在调试程序中非常有用非常方便。

    assert是一个调试仿真时的专用语法,他可以判断一个boolean变量,如果该变量为假就输出一个用户指定的信息到终端(控制台),用户可以附带输出信息的严格等级,从低到高依次是:note,warning,error,failure,可以让用户区分信息的类型。同样assert语句也是不能被综合的。

    assert可以是同步语句(在process外),此时assert后面的任何变量变化都会引起assert语句判断一次。

    assert还可以是顺序语句,此时assert存在于process中。

  • 相关阅读:
    Sort函数的相关知识
    javascript常用排序算法总结
    机票项目辅助类
    解析机票舱位和子舱位方法
    一个哥们总结的技术知识点
    随鼠标移动的div
    【转】Qt在pro中设置运行时库MT、MTd、MD、MDd,只适合VS版本的Qt
    C++异常及捕获_01
    Qt5_QString_测试
    Qt5_容器_知识点记录
  • 原文地址:https://www.cnblogs.com/zlh840/p/2101504.html
Copyright © 2011-2022 走看看