一、$readmemh和 $readmem
在Verilog程序中有两个系统任务$readmemh和$readmem用来从文件读取数据到存储器中。在两个系统任务可以在仿真的任何时刻被执行使用,其语法格式共有一下:
(1) $readmemb(“<file_name>”,<memory_name>);
(2) $readmemb(“<file_name>”,<memory_name>,<start_addr>);
(3) $readmemb(“<file_name>”,<memory_name>,<start_addr>,<finish_addr>);
(4) $readmemh(“<file_name>” ,<memory_name>);
(5) $readmemh(“<file_name>”,<memory_name>,<start_addr>);
(6) $readmemh(“<file_name>”,<memory_name>,<start_addr>,<finish_addr>);
例:$readmemh和$readmem系统任务实例
module read_mem_tb;
reg [7:0] memory_b [0:7];
reg [7:0] memory_h [0:31];
integer i;
initial
begin
$readmemb("init_b.txt",memory_b); //把数据文件init_b.txt读入存储器中的指定地址
$readmemh("init_h.txt",memory_h);
for(i = 0;i < 8; i=i+1)
begin
$display("memory_b[%0d] = %b",i.memory_b[i]);
$display("memory_h[%0h] = %h",i.memory_h[i]);
end
end
endmodule
文件init_b.txt和init_h.txt包含初始化数据。用@<address>在数据文件中指定地址。其中,"init_b.txt"指定二进制数据从第二位地址开始写入;而"init_h.txt"指定十六进制数据从地一位地址写入。样本文件如下:
init_b.txt:
@002
11111111 01010101
00000000 10101010
@001
1111zzzz 00001111
init_h.txt:
@001
00000000000000000000000000000011
00000000000000000000000000000111
00000000000000000000000000001111
00000000000000000000000000011111
二、$random
$random是产生随机数的系统函数,每次调用该函数将返回一个32位的随机数,该随机数是一个带符号的整数。语法格式:
$random%<number>;
这个系统函数提供了一个产生随机数的手段。当函数被调用时返回一个32bit 的随机数。它是一个带符号的整形数。
$random一般的用法是:$ramdom%b,其中b>0,它给出了一个范围在(-b + 1):(b - 1)中的随机数。
`timescale 1ns/1ns
module random_pulse(dout);
output [9:0] dout;
reg dout;
integer delay1,delay2,k;
initial
begin
#10 dout=0;
for(k=0;k<100;k=k+1)
begin
delay1 = 20 * ({$random} % 6);
delay2 = 20 * (1 +{$random} % 3);
#delay1 dout= 1 << ({$random}%10);
$delay2 dout = 0;
end
end
endmodule
三、$display和 $write
语法格式:
$display("<format_specifiers>", <signal1 , signal2, ..., signaln>);
$write("<format_specifiers>", <signal1, signa12, ..., signaln>);
"<format_specifiers>"通常称为“格式控制”
"<signal1, signa12, …, signaln>"为”信号输出列表“
$display自动地在输出后进行换行
$write输出特定信息是不换行
输出格式说明,由“%"和格式字符组成,其作用是将输出的数据转换成指定的格式输出。
常用的几种输出格式如下表:
一些特殊的字符可以通过表中的转换序列来输出:
例:$display和 $write语句
module disp_tb;
reg[31 :0] rval;
pulldown(pd);
initial
begin
rval=101;
$display("\\\t%%\n\"\123”);
$display("rval=%h hex %d decimal" rval, rval);
$display("rval=%o otal %b binary", rval, rval);
$display("rval has %c ascii character value",rval);
$display("pd strength value is %v", pd);
$display("current scope is %m");
$display("%s is ascii value for 101",101);
$write("simulation time is");
$write("%t\n", $time);
end
endmodule
module disp_tb;
reg[31 :0] rval;
pulldown(pd);
initial
begin
rval=101;
$display("\\\t%%\n\"\123”);
$display("rval=%h hex %d decimal" rval, rval);
$display("rval=%o otal %b binary", rval, rval);
$display("rval has %c ascii character value",rval);
$display("pd strength value is %v", pd);
$display("current scope is %m");
$display("%s is ascii value for 101",101);
$write("simulation time is");
$write("%t\n", $time);
end
endmodule
在$display中,输出列表中数据的显示宽度是自动按照输出格式进行调整的,总是用表达式的最大值所占的位数来显示表达式的当前值。
四、$monitor与 $stobe
$monitor与$stobe都提供了监控和输出参数列表中字符或变量的值的功能
(1)$monitor语法格式:
$monitor("<format_specifiers>", <signal1, signal2, ..., signaln>);
任务$monitor提供了监控和输出参数列表中的表达式或变量值的功能。每当参数列表中变量或表达式的值发生变化时,整个参数列表中变量或表达式的值都将输出显示。
例如:$monitor($time, , “rxd=%b txd=%b”,rxd txd);
注意在上面的语句中,", ,"代表一个空参数。空参数在输出时显示为空格。
$monitoron和$monitoroff任务的作用是通过打开和关闭监控标志来控制监控任务$monitor的启动和停止,这样使得程序员可以很容易的控制$monitor何时发生。
$monitor与$display的不同处在于$monitor往往在initial块中调用,只要不调用$monitoroff,$monitor便不间断地对所设定的信号进行监视。
例:$monitor系统任务的应用
module monitor_tb;
integer a,b;
initial
begin
a = 2;
b = 2;
forever
begin
#5 a = a + b;
#5 b = a - 1;
end
end
initial $monitor($time,"a = %d,b = %d",a, b);
endmodule
(2)$strobe语法格式:
$strobe(<functions_or_signals>);
$strobe("<string_and/or_variables>",<functions_or_signals>);
探测任务用于在某时刻所有时间处理完后,在这个时间步的结尾输出一行格式化的文本。常用的系统任务如下:
$stobe:在所有时间处理完后,以十进制格式输出一行格式化的文本;
$strobeb:在所有时间处理完后,以二进制格式输出一行格式化的文本;
$strobeo:在所有时间处理完后,以八进制格式输出一行格式化的文本;
$strobeh:在所有时间处理完后,以十六进制格式输出一行格式化的文本。
$strobe任务在被调用的时刻所有的赋值语句都完成了,才输出相应的文字信息。$strobe任务提供了另一种数据显示机制,可以保证数据只在所有赋值语句被执行完毕后才被显示。
五、$time和 $reltime
用这两个时间系统函数可以得到当前的仿真时刻,不同的是,$time函数以64位整数值的形式返回仿真时间,而 $realtime函数则以实数型数据返回仿真时间。
(1)系统函数 $time
例:$time系统任务的应用实例
`timescale 1ns/1ns
module time_tb;
reg ts;
parameter dalay = 2;
initial
begin
#delay ts = 1;
#delay ts = 0;
#delay ts = 1;
#delay ts = 0;
end
initial
$monitor($time,,"ts = %b",ts);
$time
endmodule
输出结果:
0 ts = x
3 ts = 1
5 ts = 0
8 ts = 1
10 ts = 0
(2) $realtime系统函数
$realtime返回的时间数字是一个实型数,该数字也是以时间尺度为基准的。
例:$realtime 系统任务的应用实例:
`timescalel 1ns/1ns
module realtime_tb;
reg set;
parameter p=2;
initial
begin
$monitor($realtime, ,"set=b%" ,set);
#p set=0;
#p set=1;
end
endmodule
`timescalel 1ns/1ns
module realtime_tb;
reg set;
parameter p=2;
initial
begin
$monitor($realtime, ,"set=b%" ,set);
#p set=0;
#p set=1;
end
endmodule
输出结果:
0 set=x
2 set=0
4 set=1
六、$finish和 $stop
系统任务$finish和$stop是用于对仿真过程进行控制,分别表示结束仿真和中断仿真。其语法格式:
$finish;
$fimsh(n);
$stop;
$stop(n);
其中,n是$finish和$stop的参数,n可以取0、1或2几个值,分别表示如下含义,如下表所示。
$finish的作用是退出仿真器,返回主操作系统,也就是结束仿真过程。任务$finish可以带参数,根据参数的值输出不同的特征信息。如果不带参数,默认$finish的参数值为1。
$stop任务的作用是把EDA工具(例如仿真器)置成暂停模式,在仿真环境下给出一个交互式的命令提示符,将控制权交给用户。这个任务可以带有参数表达式。根据参数值(0,1或2)的不同,输出不同的信息。参数值越大,输出的信息越多。
$finish的实例
module finish_tb;
integer a,b;
initial
begin
a = 2;
b = 4;
forever
begin
#5 a = a + b;
#5 b = a - 1;
end
end
initial #40 $finish; //程序执行到40个时间单位时退出仿真器
initial
begin
$monitor($time,"a = %d,b = %d",a,b);
end
endmodule
$stop的实例
module stop_tb;
integer a,b;
initial
begin
a = 2;
b = 4;
forever
begin
#5 a = a + b;
#5 b = a - 1;
end
end
initial #40 $stop; //程序执行到40个时间单位时停止仿真
initial
begin
$monitor($time,"a = %d,b = %d",a,b);
end
endmodule