(1)格式说明,由“%”和格式字符组成。它的作用是将输出的数据转换成指定的格式输出。
下表给出了常用的几种输出格式。 ? %h 或%H : 十六进制 ? %d 或%D : 十进制 ? %o 或%O : 八进制 ? %b 或%B : 二进制 ? %c 或%C : ASCII字符 ? %v 或%V : 线网信号长度 ? %m 或%M : 层次名 ? %s 或%S : 字符串
? %t 或%T : 当前时间格式
(2) 下面表中的字符形式用于格式字符串参数中,用来显示特殊的字符。
(3) 显示任务的格式控制举例 module disp; begin
$display(“\\\\\\t%%\\n\\”\\123”) ; end endmodule
结果是: \\ % \
3.2 时间度量系统函数 $time
? 系统函数$time:
$time可以返回一个64比特的整数来表示的当前仿真时刻值。该时刻是以模块的仿
真时间尺度为基准的。 ? 系统函数$realtime:
$realtime和$time的作用是一样的,只是$realtime返回的时间数字是一个实型数,
该数字也是以时间尺度为基准的。
3.3 系统任务 $readmemb 和$readmemh
? 系统任务$readmemb和$readmemh用来从文件中读取数据到存贮器中。这两个系统任
务可以在仿真的任何时刻被执行使用。
1) $readmemb(\数据文件名>\存贮器名>);
2) $readmemb(\数据文件名>\存贮器名>,<起始地址>);
3) $readmemb(\数据文件名>\存贮器名>,<起始地址>,<结束地址>); $readmemh用法和$readmemb用法相同
? 文件包含空白空间、注释和二进制(对于$readmemb)或十六进制(对于$readmemh)
数字。每个数字由空白空间隔离。当执行系统任务时,每个读取的数字被指派给存储器内的一个地址。开始地址对应于存储器最左边的索引。
例1: reg [0:3] Mem_A [0:63]; initial
$readmemb(\
//读入的每个数字都被指派给从0开始到63的存储器单元。 例2: $readmemb(\
//从文件“rx.vec”中读取的第一个数字被存储在地址15中,下一个
存储在地址16,并以此类推直到地址30。
3.4 系统任务 $random
? 系统函数$random提供了一个产生随机数的手段。当函数被调用时返回一个32bit
的随机数。它是一个带符号的整形数。
$ramdom % b ,其中 b>0.
它给出了一个范围在(-b+1):(b-1)中的随机数。
reg[7:0] rand;
rand = $random % 60; 给出了一个范围在-59到59之间的随机数
? 并置操作符({})将$random函数返回的有符号整数变换为无符号数。
reg[7:0] rand; rand = {$random} `;
通过位并接操作产生一个值在0到59之间的数
4.编译预处理
Verilog-HDL语言中有几种特殊命令,编译系统先对这些特殊命令进行“预处理”,然后将预处理的结果和源程序一起进行通常的编译处理。 这些预处理命令:
? 以重音符号ˋ开头 ? 行末尾不加分号
常用预处理命令:
`include, `define, `undef , `timescale `ifdef, `else, `endif, `default_nettype `resetall
4.1 `include指令
? `include 编译器指令用于嵌入内嵌文件的内容。文件既可以用相对路径名定义,也
可以用全路径名定义, 例如:
`include \
? 编译时,这一行由文件“ ../../primitives.v” 的内容替代。
? 常常在一个芯片设计之前定义一系列全局型的参数,放在define.v文件里面,然后
在每个模块中来引入。可以有效地提高编码效率和可扩展性。
4.2 `define命令和`undef命令
? `define指令用于文本替换,它很像C语言中的#define指令,如:
? `define MAX_BUS_SIZE 32 ? ...
? reg [`MAX_BUS_SIZE-1:0] AddReg;
? 一旦`define指令被编译,其在整个编译过程中都有效。调用时候,前面要
用`,注意与参数parameter的不同。
? `undef指令取消前面定义的宏。例如:
? `define WORD 16 //建立一个文本宏替代。 ? ...
? wire [`WORD:0] Bus; ? ...
? `undef WORD //在`undef编译指令后,WORD的宏定义不再有效。
4.3 `ifdef、`else 和`endif
? 这些编译指令用于条件编译,如下所示:
? ` ifdef WINDOWS
? parameter WORD_SIZE=16 ? `else
? parameter WORD_SIZE=32 ? `endif
? 在编译过程中,如果已定义了名字为WINDOWS的文本宏,就选择第一种参数声明,
否则选择第二种参数说明。
? `else程序指令对于`ifdef指令是可选的。
4.4 `default_nettype和`resetall命令
? `default_nettype指令用于为隐式线网指定线网类型。也就是将那些没有被说明的
连线定义线网类型。
例如: `default_nettype wand
? 该实例定义的缺省的线网为线与类型。因此,如果在此指令后面的任何模块中没有
说明的连线,那么该线网被假定为线与类型。
? `resetall指令将所有的编译指令重新设置为缺省值。该指令使得缺省连线类型为
线网类型。
4.5 ˋtimescale命令
? 在Verilog HDL 模型中,所有时延都用单位时间表述。使用`timescale编译器指令
将时间单位与实际时间相关联。该指令用于定义时延的单位和时延精度。 ? 格式为:`timescale time_unit / time_precision
? time_unit和time_precision由值1、10、和100以及单位s、ms、us、ns、ps和
fs组成。
例如:`timescale 1ns / 100ps
表示时延单位为1ns,时延精度为100ps。`timescale编译器指令在模块说明外部出现,并且影响后面所有的时延值。 例:ˋtimescale 1ns/ 100ps
module AndFunc (Z, A, B); output Z; input A, B;
and # 5.22 A1 (Z, A, B); endmodule
编译器指令定义时延以ns为单位,并且时延精度为1/10 ns(100 ps)。 因此,时延值5.22对应5.2 ns。
注:当一个设计中的多个模块带有自身的`timescale编译指令时,模拟器总是定位在所有模块的最小时延精度上,并且所有时延都相应地换算为最小时延精度。
4.6 时延(补充内容)
? assign #6 Ask = Quiet | | Late;
? 规定右边表达式结果的计算到其赋给左边目标需经过6个时间单位时延。
? 例如,如果在时刻5,Late值发生变化,则赋值的右端表达式被计算,并且Ask在
时刻11( = 5 +6)被赋于新值。
三个时延:
? 对于每个时延定义,总共能够指定三类时延值:
1.上升时延 2.下降时延 3.关闭时延
assign # (rise, fall, turn-off) LHS = RHS_expr ;
? 如果右端从非0向量变化到0向量,那么就使用下降时延。如果右端值到达z,那
么使用关闭时延;否则使用上升时延。
assign #4 Ask = Quiet | | Late; // One delay value. assign # (4,8) Ask = Quick ; // Two delay values.
assign # (4,8,6) Arb = & DataBus; // Three delay values. assign Bus = MemAddr[7:4]; // No delay value.
关于时延的探讨:
? 如果右端在传输给左端之前变化,右端发生在时延间隔内的变化被滤掉。 例如:assign #4 Cab = Drm;
? 由上图看出,右端值变化在能够传播到左端前必须至少保持时延间隔;如果在时延
间隔内右端值变化,则前面的值不能传输到输出。
线网时延: 例:
wire # 5 Arb;
assign # 2 Arb = Bod & Cap;
因为定义了线网时延,实际对Arb的赋值发生在时刻17( = 10 + 2 + 5)。