$display和\write是Verilog HDL中的两种主要的输出任务。并且这两个系统任务的语法格式都相同。语法格式如下:
$display("",);
$write("",);
$display和$write的区别:
$display在输出信息时带有行结束字符,即自动的在输出后进行换行;
$write在输出特定信息时不自动换行。如果想在一行里输出多个信息,可以使用$write。
格式控制:
格式控制由%和格式字符组成。其作用是将输出的数据转换成指定的格式输出。
下表是几种常用的输出格式:
格式输出 | 说明 |
---|---|
%h或%H | 以十六进制数的形式输出 |
%d或%D | 以十进制数的形式输出 |
%o或%O | 以八进制的形式输出 |
%b或%B | 以二进制的形式输出 |
%c或%C | 以ASCII码字符的形式输出 |
%v或%V | 输出网络型数据信号强度 |
%m或%M | 输出等级层次的名字 |
%s或%S | 以字符串的形式输出 |
%t或%T | 以当前的时间格式输出 |
%e或%E | 以指数的形式输出实型数 |
%f或%F | 以十进制的形式输出实型数 |
%g或%G | 以指数或十进制数的形式输出实型数 |
还有一些特殊字符的输出格式如下:
换码序列 | 功能 |
---|---|
\n | 换行 |
\t | 横向跳格(即跳到下一个输出区) |
\\ | 反斜杠字符\ |
\" | 双引号字符" |
\o | 1到3位八进制数代表的字符 |
%% | 百分符号% |
注意:
在使用$display输出变量时,总是用变量的最大可能值所占的位数来显示当前值。用十进制格式输出当前结果时有效数值前面的0用空格代替。其他进制,前面的0仍然会被显示出来。
可以在%个表示进制的字符间插入一个0,这时候$display会自动调整显示位宽,总是用最小的位宽来显示变量的当前值。
例如:
$display("d=%0d, h=%0h", data, addr);
$monitor也是用于信号输出显示的系统任务。
$monitor的语法格式:
$monitor("", );
$monitor会监控并输出参数列表中的变量值(或者表达式的值)。每当参数列表中的变量(或表达式)的值发生变化的时候,$monitor就会将参数列表中的变量(或表达式)的值输出一次。
如果同一时刻两个或多个参数的值发生变化,则在该时刻只输出显示一次。
$monitoron和$monitoroff任务的作用是通过打开和关闭监控标志来控制监控任务$monitor的启动和停止。
$monitoroff任务用于关闭监控标志,停止监控任务;$monitoron的作用与之相反。通常在通过$monitoron启动$monitor时,不管$monitor参数列表中的值是否发生变化,总是立刻输出显示当前时刻参数列表中的值。缺省情况下,控制标志在仿真的起始时刻已经被打开。
在多模块调试的情况下,许多模块中都调用了$monitor,但因为任何时刻只能有一个$monitor其作用,因此需要配合$monitoron和$monitoroff使用,把需要监控的模块用$monitoron打开,在监视完毕后及时用$monitoroff关闭,以便$monitor可以被其他模块使用。
使用$time和$realtime都可以得到当前的仿真时间。这两个函数被调用后都会返回当前时刻相对于仿真开始时刻的时间量值。不同的是,$time函数以64位整数值得形式返回仿真时间;而$realtime函数则以实型数据返回仿真时间。
$time返回的时间是以模块的仿真时间尺度为基准的。下面举例说明:
`timescale 10ns/1ns
module test;
reg set;
parameter p=1.6;
initial
begin
$monitor($time,,"set=",set);
#p set=0;
#p set=1;
end
endmodule
输出结果为:
0 set=x
2 set=0
3 set=1
在这个例子中,模块test想在时刻为16ns时设置寄存器set为0,在时刻为32ns时设置寄存器set为1。但是由$time记录的set变化时刻却和预想的不一样。这是由下面两个原因引起的:
是$realtime返回的时间数字是一个实型数,该数字也是以时间尺度为基准的。下面举例说明:
`timescale10ns/1ns
module test;
reg set;
parameter p=1.55;
initial
begin
$monitor($realtime,,"set=",set);
#p set=0;
#p set=1;
end
endmodule
输出结果为:
0 set=x
1.6 set=0
3.2 set=1
与$time的例子相比,模块的仿真时间单位和时间精度没有变化。所以p设置为1.55时,由于仿真精度的限制并不能在15.5ns完成set=0的赋值操作。而是在16ns时完成这一操作。同样,由于模块仿真精度的限制,也不能在31.5ns时完成set=1的赋值操作,只能在32ns是完成这一操作。有因为$realtime可以返回的时刻是一个实型数,不再需要取整,所以以仿真时间单位为标准输出的就是1.6和3.2。
系统任务$finish的作用是退出仿真器,返回主操作系统,也就是结束仿真过程。任务$finish可以带参数,根据参数的值输出不同的特征信息。语法格式如下:
$finish;
$finish(n);
如果不带参数,默认$finish的参数值为1。下面给出了对于不同的参数值,系统输出的特征信息:
n取值 | 含义 |
---|---|
0 | 不输出任何信息 |
1 | 输出当前仿真时刻和位置 |
2 | 输出当前仿真时刻,位置和在仿真过程中所用memory及CPU时间的统计 |
$stop任务的作用是把EDA工具(例如仿真器)置成暂停模式,在仿真环境下给出一个交互式的命令提示符,将控制权交给用户。这个任务可以带有参数表达式。根据参数值(0,1或2)的不同,输出不同的信息。参数值越大,输出的信息越多。语法格式如下:
$stop;
$stop(n);
问题:仿真停止后,怎么继续仿真?
在Verilog HDL程序中有两个系统任务 r e a d m e m b 和 readmemb和 readmemb和readmemh用来从文件中读取数据到存贮器(设计的ram)中。这两个系统任务可以在仿真的任何时刻被执行使用,其使用格式共有以下六种:
$readmemb("<数据文件名>",<存贮器名>);
$readmemb("<数据文件名>",<存贮器名>,<起始地址>);
$readmemb("<数据文件名>",<存贮器名>,<起始地址>,<结束地址>);
$readmemh("<数据文件名>",<存贮器名>);
$readmemh("<数据文件名>",<存贮器名>,<起始地址>);
$readmemh("<数据文件名>",<存贮器名>,<起始地址>,<结束地址>);
注意:
1.被读取的数据文件的内容只能包含:空白位置(空格,换行,制表格(tab)和form-feeds),注释行(//形式的和/…/形式的都允许),二进制或十六进制的数字。
2.数字中不能包含位宽说明和格式说明,对于$readmemb系统任务,每个数字必须是二进制数字,对于$readmemh系统任务,每个数字必须是十六进制数字。
3.数字中不定值x或X,高阻值z或Z,和下划线(_)的使用方法及代表的意义与一般Verilog HDL程序中的用法及意义是一样的。
4.数字必须用空白位置或注释行来分隔开。
5.存贮器单元的存放地址范围由系统任务声明语句中的起始地址和结束地址来说明,每个数据的存放地址在数据文件中进行说明。当数据文件被读取时,每一个被读取的数字都被存放到地址连续的存贮器单元中去。当地址出现在数据文件中,其格式为字符“@”后跟上十六进制数。对于这个十六进制的地址中,允许大写和小写的数字。在字符“@”和数字之间不允许存在空白位置。可以在数据文件里出现多个地址。
对于上面六种系统任务格式,需补充说明以下五点:
这个系统函数提供了一个产生随机数的手段。当函数被调用时返回一个32bit的随机数。它是一个带符号的整形数。语法格式为:
$ramdom%;
其中 number>0。它给出了一个范围在(-number+1):(number-1)中的随机数。
使用连接操作符可以得到一个0到number-1之间的随机数:
{$ramdom}%;