Verilog HDL 有两大类数据类型。
1) 线网类型。 net type 标明 Verilog 结构化元件间的物理连线。它的值由驱动元件的值决议,例如接连赋值或门的输出。假如没有驱动元件衔接到线网,线网的缺省值为 z 。
2) 寄存器类型。 register type 标明一个笼统的数据存储单元,它只能在 always 句子和 initial 句子中被赋值,而且它的值从一个赋值到另一个赋值被保存下来。寄存器类型的变量具有 x 的缺省值。
线网类型
线网数据类型包括下述不同品种的线网子类型。
* wire
* tri
* wor
* trior
* wand
* triand
* trireg
* tri1
* tri0
* supply0
* supply1
简略的线网类型阐明语法为:
net_kind [msb:lsb] net1, net2, . . . , netN;
net_kind 是上述线网类型的一种。 msb 和 lsb 是用于界说线网规模的常量表达式;规模界说是可选的;假如没有界说规模,缺省的线网类型为 1 位。下面是线网类型阐明实例。
wire Rdy, Start; //2 个 1 位的连线。
wand [2:0] Addr; //Addr 是 3 位线与。
当一个线网有多个驱动器时,即对一个线网有多个赋值时,不同的线网发生不同的行为。例如,
wor Rde;
. . .
assign Rde = Blt Wyl;
. . .
assign Rde = Kbl | Kip;
本例中, Rde 有两个驱动源,别离来自于两个接连赋值句子。因为它是线或线网, Rde 的有效值由运用驱动源的值(右边表达式的值)的线或 (wor) 表(拜见后面线或网的有关章节)决议。
1. wire 和 tri 线网
用于衔接单元的连线是最常见的线网类型。连线与三态线 (tri) 网语法和语义共同;三态线能够用于描绘多个驱动源驱动同一根线的线网类型;而且没有其他特别的含义。
wire Reset;
wire [3:2] Cla, Pla, Sla;
tri [ MSB - 1 : LSB +1] Art;
假如多个驱动源驱动一个连线(或三态线网),线网的有效值由下表决议。
wire ( 或 tri) 0 1 x z
0 0 x x 0
1 x 1 x 1
x x x x x
z 0 1 x z
下面是一个详细实例:
assign Cla = Pla Sla;
. . .
assign Cla = Pla ^ Sla;
在这个实例中, Cla 有两个驱动源。两个驱动源的值(右侧表达式的值)用于在上表中索引,以便决议 Cla 的有效值。因为 Cla 是一个向量,每位的计算是相关的。例如,假如第一个右侧表达式的值为 01x, 而且第二个右测表达式的值为 11z ,那么 Cla 的有效值是 x1x ( 第一位 0 和 1 在表中索引到 x, 第二位 1 和 1 在表中索引到 1 ,第三位 x 和 z 在表中索引到 x) 。
2. wor 和 trior 线网
线或指假如某个驱动源为 1 ,那么线网的值也为 1 。线或和三态线或 (trior) 在语法和功能上是共同的。
wor [MSB:LSB] Art;
trior [MAX - 1: MIN - 1] Rdx, Sdx, Bdx;
假如多个驱动源驱动这类网,网的有效值由下表决议。
wor ( 或 trior) 0 1 x z
0 0 1 x 0
1 1 1 1 1
x x 1 x x
z 0 1 x z
3. wand 和 triand 线网
线与 (wand) 网指假如某个驱动源为 0 ,那么线网的值为 0 。线与和三态线与 (triand) 网在语法和功能上是共同的。
wand [-7 : 0] Dbus;
triand Reset, Clk;
假如这类线网存在多个驱动源,线网的有效值由下表决议。
wand ( 或 triand) 0 1 x z
0 0 0 0 0
1 0 1 x 1
x 0 x x x
z 0 1 x z
4. trireg 线网
此线网存储数值(类似于寄存器),而且用于电容节点的建模。当三态寄存器 (trireg) 的一切驱动源都处于高阻态,也就是说,值为 z 时,三态寄存器线网保存效果在线网上的最终一个值。此外,三态寄存器线网的缺省初始值为 x 。
trireg [1:8] Dbus, Abus;
5. tri0 和 tri1 线网
这类线网可用于线逻辑的建模,即线网有多于一个驱动源。 tri0 ( tri1 )线网的特征是,若无驱动源驱动,它的值为 0 ( tri1 的值为 1 )。
tri0 [ - 3:3] GndBus;
tri1 [0: - 5] OtBus, ItBus;
下表显现在多个驱动源状况下 tri0 或 tri1 网的有效值。
tri0 (tri1) 0 1 x z
0 0 x x 0
1 x 1 x 1
x x x x x
z 0 1 x 0(1)
6. supply0 和 supply1 线网
supply0 用于对 “ 地 ” 建模,即低电平 0 ; supply1 网用于对电源建模,即高电平 1 ;例如 :
supply0 Gnd, ClkGnd;
supply1 [2:0] Vcc;
未阐明的线网
在 Verilog HDL 中,有或许不用声明某种线网类型。在这样的状况下,缺省线网类型为 1 位线网。
能够运用 `default_nettype 编译器指令改动这一隐式线网阐明办法。运用办法如下:
`default_nettype net_kind
例如,带有下列编译器指令:
`default_nettype wand
任何未被阐明的网缺省为 1 位线与网。
向量和标量线网
在界说向量线网时可选用关键词 scalared 或 vectored 。假如一个线网界说时运用了关键词 vectored, 那么就不答应位挑选和部分挑选该线网。换句话说,有必要对线网全体赋值(位挑选和部分挑选鄙人一章中解说)。例如 :
wire vectored [3:1] Grb;
// 不答应位挑选 Grb[2] 和部分挑选 Grb [3:2]
wor scalared [4:0] Best;
// 与 wor [4:0] Best 相同,答应位挑选 Best [2] 和部分挑选 Best [3:1] 。
假如没有界说关键词,缺省值为标量。
寄存器类型
有 5 种不同的寄存器类型。
* reg
* integer
* time
* real
* realtime
1. reg 寄存器类型
寄存器数据类型 reg 是最常见的数据类型。 reg 类型运用保留字 reg 加以阐明,办法如下:
reg [ msb: lsb] reg1, reg2, . . . regN;
msb 和 lsb 界说了规模,而且均为常数值表达式。规模界说是可选的;假如没有界说规模,缺省值为 1 位寄存器。例如:
reg [3:0] Sat; //Sat 为 4 位寄存器。
reg Cnt; //1 位寄存器。
reg [1:32] Kisp, Pisp, Lisp;
寄存器能够取恣意长度。寄存器中的值通常被解释为无符号数 , 例如:
reg [1:4] Comb;
. . .
Comb = - 2; //Comb 的值为 14 ( 1110 ), 1110 是 2 的补码。
Comb = 5; //Comb 的值为 15 ( 0101 )。
2. 存储器
存储器是一个寄存器数组。存储器运用如下办法阐明:
reg [ msb: 1sb] memory1 [ upper1: lower1],
memory2 [upper2: lower2],. . . ;
例如:
reg [0:3 ] MyMem [0:63]
//MyMem 为 64 个 4 位寄存器的数组。
reg Bog [1:5]
//Bog 为 5 个 1 位寄存器的数组。
MyMem 和 Bog 都是存储器。数组的维数不能大于 2 。留意存储器归于寄存器数组类型。线网数据类型没有相应的存储器类型。
单个寄存器阐明既能够用于阐明寄存器类型,也能够用于阐明存储器类型。
parameter ADDR_SIZE = 16 , WORD_SIZE = 8;
reg [1: WORD_SIZE] RamPar [ ADDR_SIZE - 1 : 0], DataReg;
RamPar 是存储器,是 16 个 8 位寄存器数组,而 DataReg 是 8 位寄存器。
在赋值句子中需求留意如下差异:存储器赋值不能在一条赋值句子中完结,可是寄存器能够。因此在存储器被赋值时,需求界说一个索引。下例阐明它们之间的不同。
reg [1:5] Dig; //Dig 为 5 位寄存器。
. . .
Dig = 5’b11011;
上述赋值都是正确的 , 但下述赋值不正确:
reg BOg[1:5]; //Bog 为 5 个 1 位寄存器的存储器。
. . .
Bog = 5’b11011;
有一种存储器赋值的办法是别离对存储器中的每个字赋值。例如:
reg [0:3] Xrom [1:4]
. . .
Xrom[1] = 4’hA;
Xrom[2] = 4’h8;
Xrom[3] = 4’hF;
Xrom[4] = 4’h2;
为存储器赋值的另一种办法是运用体系使命:
1) $readmemb (加载二进制值)
2) $readmemb (加载十六进制值)
这些体系使命从指定的文本文件中读取数据并加载到存储器。文本文件有必要包括相应的二进制或许十六进制数。例如:
reg [1:4] RomB [7:1] ;
$ readmemb (ram.patt, RomB);
Romb 是存储器。文件 “ram.patt” 有必要包括二进制值。文件也能够包括空白空间和注释。下面是文件中或许内容的实例。
1101
1110
1000
0111
0000
1001
0011
体系使命 $readmemb 促进从索引 7 即 Romb 最左面的字索引,开端读取值。假如只加载存储器的一部分,值域能够在 $readmemb 办法中显式界说。例如:
$readmemb (ram.patt, RomB, 5, 3);
在这种状况下只要 Romb[5],Romb[4] 和 Romb[3] 这些字从文件头开端被读取。被读取的值为 1101 、 1100 和 1000 。
文件能够包括显式的地址办法。
@hex_address value
如下实例:
@5 11001
@2 11010
在这种状况下,值被读入存储器指定的地址。
当只界说开端值时,接连读取直至抵达存储器右端索引鸿沟。例如:
$readmemb (rom.patt, RomB, 6);
// 从地址 6 开端,而且继续到 1 。
$readmemb ( rom.patt, RomB, 6, 4);
// 从地址 6 读到地址 4 。
3. Integer 寄存器类型
整数寄存器包括整数值。整数寄存器能够作为一般寄存器运用,典型应用为高层次行为建模。运用整数型阐明办法如下:
integer integer1, integer2,. . . intergerN [msb:1sb] ;
msb 和 lsb 是界说整数数组边界的常量表达式,数组边界的界说是可选的。留意容许无位边界的状况。一个整数最少包容 32 位。可是详细完结可供给更多的位。下面是整数阐明的实例。
integer A, B, C; // 三个整数型寄存器。
integer Hist [3:6]; // 一组四个寄存器。
一个整数型寄存器可存储有符号数,而且算术操作符供给 2 的补码运算成果。
整数不能作为位向量拜访。例如,关于上面的整数 B 的阐明, B[6] 和 B[20:10] 是不合法的。一种截取位值的办法是将整数赋值给一般的 reg 类型变量,然后从中选取相应的位,如下所示:
reg [31:0] Breg;
integer Bint;
. . .
//Bint[6] 和 Bint[20:10] 是不答应的。
. . .
Breg = Bint;
/* 现在, Breg[6] 和 Breg[20:10] 是答应的,而且从整数 Bint 获取相应的位值。 */
上例阐明了怎么经过简略的赋值将整数转化为位向量。类型转化主动完结,不用运用特定的函数。从位向量到整数的转化也能够经过赋值完结。例如 :
integer J;
reg [3:0] Bcq;
J = 6; //J 的值为 32’b0000…00110 。
Bcq = J; // Bcq 的值为 4’b0110 。
Bcq = 4’b0101.
J = Bcq; //J 的值为 32’b0000…00101 。
J = - 6; //J 的值为 32’b1111…11010 。
Bcq = J; //Bcq 的值为 4’b1010 。
留意赋值总是从最右端的位向最左面的位进行;任何剩余的位被切断。假如你能够回忆起整数是作为 2 的补码位向量标明的,就很简单了解类型转化。
4. time 类型
time 类型的寄存器用于存储和处理时刻。 time 类型的寄存器运用下述办法加以阐明。
time time_id1, time_id2, . . . ,time_idN [ msb:1sb];
msb 和 lsb 是标明规模边界的常量表达式。假如未界说边界,每个标识符存储一个至少 64 位的时刻值。时刻类型的寄存器只存储无符号数。例如 :
time Events [0:31]; // 时刻值数组。
time CurrTime; //CurrTime 存储一个时刻值。
5. real 和 realtime 类型
实数寄存器(或实数时刻寄存器)运用如下办法阐明:
// 实数阐明:
real real_reg1, real_reg2, . . ., real_regN;
// 实数时刻阐明:
realtime realtime_reg1, realtime_reg2, . . . ,realtime_regN;
realtime 与 real 类型完全相同。例如 :
real Swing, Top;
realtime CurrTime;
real 阐明的变量的缺省值为 0 。不答应对 real 声明值域、位边界或字节边界。
当将值 x 和 z 赋予 real 类型寄存器时,这些值作 0 处理。
real RamCnt;
. . .
RamCnt = ‘b01x1Z;
RamCnt 在赋值后的值为 ‘b01010 。
3.8 参数
参数是一个常量。参数常常用于界说时延和变量的宽度。运用参数阐明的参数只被赋值一次。参数阐明办法如下:
parameter param1 = const_expr1, param2 = const_expr2, . . . ,
paramN = const_exprN;
下面为详细实例:
parameter LINELENGTH = 132, ALL_X_S = 16’bx;
parameter BIT = 1, BYTE = 8, PI = 3.14;
parameter STROBE_DELAY = ( BYTE + BIT) / 2;
parameter TQ_FILE = /home/bhasker/TEST/add.tq;
参数值也能够在编译时被改动。改动参数值能够运用参数界说句子或经过在模块初始化句子中界说参数值.