第14章对验证的支持学习内容1.理解Verilog文本输出2.理解不同的读取仿真时间的系统函数3.理解Verilog文件I/O功能验证系统中的任务(task)及函数(function)•Verilog读取当前仿真时间的系统函数$time$stime$realtime•Verilog支持文本输出的系统任务:$display$strobe$write$monitor仿真时间访问仿真时间•$time,$realtime,和$stime函数返回当前仿真时间。•这些函数的返回值使用调用模块中`timescale定义的时间单位•$time返回一个64位整数时间值。•$stime返回一个32位整数时间值。•$realtime返回一个实数时间值。$stime函数返回一个32位整数时间值。对大于232的时间,返回模232的值。使用它可以节省显示及打印空间。输出格式化时间信息`timescale10ns/100psmoduletop;regin1;notm1(o1,in1);initialbegin$timeformat(-9,2,ns,10);in1=0;#8in1=1;#10$display(%t%b%b,$realtime,in1,o1);#10$finish;endendmodule在这个例子中,显示的时间为:180.00nsunit:0(s)到-15(fs)之间的整数,表示时间度量precision:要显示的十进制小数位数。suffix:在时间值后显示的字符串min_width:显示前三项的最小宽度•若使用多个`timescale,以最小的时间精度显示时间值。•可用系统任务$timeformat结合格式符%t全局控制时间显示方式。•$timeformat系统任务的语法为:$timeformat(unit,precision,suffix,min_width);输出格式化时间信息`timescale1ns/10psmoduletop;regin1;not#9.53n1(o1,in1);initialbegin$display(timerealtimestime\tin1\to1);$timeformat(-9,2,ns,10);$monitor(%d%t%d\t%b\t%b,$time,$realtime,$stime,in1,o1);in1=0;#10in1=1;#10$finish;endendmoduletimerealtimestimein1o100.00ns00x109.53ns10011010.00ns10112019.53ns2010输出格式化时间信息对#延迟,Verilog将延迟值舍入最近(四舍五入)时间精度值。例如,上面的例子修改为:`timescale1ns/100psnot#9.42n1(o1,in1);结果为:timerealtimestimein1o100.00ns00x99.40ns9011010.00ns10111919.40ns1910`timescale1ns/100psnot#9.49n1(o1,in1);结果为:timerealtimestimein1o100.00ns00x99.50ns9011010.00ns10111919.50ns1910显示信号值—$display•$display输出参数列表中信号的当前值。语法:$display([“format_specifiers”,]argument_list)•$display输出时自动换行。$display($time,“%b\t%h\t%d\t%o”,sig1,sig2,sig3,sig4);$display($time,“%b\t”,sig1,“%h\t”,sig2,“%d\t”,sig3,“%o”,sig4);•$display支持二进制、八进制、十进制和十六进制。缺省基数为十进制。$display(sig1,sig2,sig3,sig4);$displayb(sig1,sig2,sig3,sig4);$displayo(sig1,sig2,sig3,sig4);$displayh(sig1,sig2,sig3,sig4);%h%o%d%b%c%s%v%m%thexoctaldecimalbinaryASCIIstringstrengthmoduletime\t\n\\\\1-3digitoctalnumber%0dtab换行反斜杠双引号上述的ASCII表示无前导0的十进制数格式符转义符显示信号值—$write和$strobe•$write与$display相同,不同的是不会自动换行。$write($time,“%b\t%h\t%d\t%o\t”,sig1,sig2,sig3,sig4);•$strobe与$display相同,不同的是在仿真时间前进之前的信号值。而$display和$write立即显示信号值。也就是说$strobe显示稳定状态信号值,而$display和$write可以显示信号的中间状态值。$strobe($time,“%b\t%h\t%d\t%o\t”,sig1,sig2,sig3,sig4);•$write和$strobe都支持多种数基,缺省为十进制。$writeb$strobeb$writeo$strobeo$writeh$strobeh显示信号值—$write和$strobe下面是模块textio仿真的输出:•$writeb输出:0xxxxxxxxx注意data是32位数据,由8位十六进制数表示。时间以没有前导零的十进制形式输出。缺省情况下,值以十进制显示,忽略前导零,与%0d格式符相同。可以在一个格式化符前插入一个0使Verilog忽略开头的零。•$displayh:00000000000000f000000101注意当前时间,一个64位量,需要16个十六进制的数。•$display:1020•$strobe:1030moduletextio;regflag;reg[31:0]data;initialbegin$writeb(%d,$time,,%h\t,data,,flag,\n);#15flag=1;data=16;$displayh($time,,data,,flag);endinitialbegin#10data=20;$strobe($time,,data);$display($time,,data);data=30;endendmodule监视信号值—$monitor•$monitor持续监视参数列表中的变量。•在一个时间片中,参数表中任何信号发生变化,$monitor将在仿真时间前进前显示参数表的信号值。•后面的$monitor将覆盖前面的$monitor。•可以用系统任务$monitoron和$monitoroff控制持续监视。•$monitor支持多种基数。缺省为十进制。$monitor($time,“%b\t%h\t%d\t%o”,sig1,sig2,sig3,sig4);监示信号值—$monitor•$monitor是唯一的不断输出信号值的系统任务。其它系统任务在返回值之后就结束。•$monitor和$strobe一样,显示参数列表中信号的稳定状态值,也就是在仿真时间前进之前显示信号。在一个时间步中,参数列表中信号值的任何变化将触发$monitor。但$time,$stime,$realtime不能触发。•任何后续的$monitor覆盖前面调用的$monitor。只有新的$monitor的参数列表中的信号被监视,而前面的$monitor的参数则不被监视。•可以用$monitoron和$monitoroff系统任务控制持续监视,使用户可以在仿真时只监视特定时间段的信号。•$monitor参数列表的形式与$display相同。•$monitor支持多种基数。缺省为十进制。$monitorb$monitoro$monitorh文件输出•$fopen打开一个文件并返回一个多通道描述符(MCD)。–MCD是与文件唯一对应的32位无符号整数。–如果文件不能打开并进行写操作,MCD将等于0。–如果文件成功打开,MCD中的一位将被置位。•以$f开始的显示系统任务将输出写入与MCD相对应的文件中。...integerMCD1;MCD1=$fopen(name_of_file);$fdisplay(MCD1,P1,P2,..,Pn);$fwrite(MCD1,P1,P2,..,Pn);$fstrobe(MCD1,P1,P2,..,Pn);$fmonitor(MCD1,P1,P2,..,Pn);$fclose(MCD1);...文件输出•$fopen打开参数中指定的文件并返回一个32位无符号整数MCD,MCD是与文件一一对应的多通道描述符。如果文件不能打开并进行写操作,它返回0。•$fclose关闭MCD指定的通道。•输出信息到log文件和标准输出的四个格式化显示任务($display,$write,$monitor,$strobe)都有相对应的任务用于向指定文件输出。•这些对应的任务($fdisplay,$fwrite,$fmonitor,$fstrobe)的参数形式与对应的任务相同,只有一个例外:第一个参数必须是一个指定向何哪个文件输出的MCD。MCD可以是一个表达式,但其值必须是一个32位的无符号整数。这个值决定了该任务向哪个打开的文件写入。•MCD可以看作由32个标志构成的组,每个标志代表一个单一的输出通道。文件输出...integermessages,broadcast,cpu_chann,alu_chann;initialbegincpu_chann=$fopen(cpu.dat);if(!cpu_chann)$finish;alu_chann=$fopen(alu.dat);if(!alu_chann)$finish;//channeltobothcpu.datandalu.datmessages=cpu_chann|alu_chann;//channeltobothfiles,standardout,andverilog.logbroadcast=1|messages;endalways@(posedgeclock)//printthefollowingtoalu.dat$fdisplay(alu_chann,acc=%hf=%ha=%hb=%h,acc,f,a,b);/*ateveryresetprintamessagetoalu.dat,cpu.dat,standardoutputandtheverilog.logfile*/always@(negedgereset)$fdisplay(broadcast,systemresetattime%d,$time);...必须声明为integer通道0(编号为1)为标准输出及verilog.log文件输入•Verilog中有两个系统任务可以将数据文件读入寄存器组。一个读取二进制数据,另一个读取十六进制数据:•$readmemb$readmemb(file_name,memory_name);$readmemb(file_name,memory_name,start_addr);$readmemb(file_name,memory_name,start_addr,finish_addr);•$readmemh$readmemh(file_name,memory_name);$readmemh(file_name,memory_name,start_addr);$readmemh(file_name,memory_name,start_addr,finish_addr);文件输入系统任务$readmemb和$readmemh从一个文本文件读取数据并写入存储器。•如果数据为二进制,使用$readmemb;如果数据为十六进制,使用$readmemh。•filenam