Bootstrap

Verilog数据类型

作者:anekin

原作网址:http://blog.sina.com.cn/s/blog_615047920100ih0k.html

Verilog HDL有下列四种基本的值:
1)0:逻辑0或“假”状态;
2)1:逻辑1或“真”状态;
3)x(X):未知状态,对大小写不敏感;
4)z(Z):高阻状态,对大小写不敏感。
注意这四种值的解释都内置于语言中。如一个为z的值总是意味着高阻抗,一个为0的值通常是指逻辑0。
在门的输入或一个表达式中的为“z”的值通常解释成“x”。此外,x值和z值都是不分大小写的,也就是说,值0x1z与值0X1Z相同。Verilog HDL中的常量是由以上这四类基本值组成的。

3.5.1网络和变量

在Verilog HDL中,根据赋值和对值的保持方式不同,可将数据类型主要分为两大类:网络(net)型和变量(Variable)型。这两类数据也代表了不同的硬件结构。

3.5.1.1 net(网络)型

net表示器件之间的物理连接,需要门和模块的驱动。网络数据类型是指输出始终根据输入的变化而更新其值的变量,它一般指的是硬件电路中的各种物理连接。 例如:网络型变量L的值由与门的驱动信号a和b所决定,即L=a&b。a、b的值发生变化,L的值会立即跟着变化。
没有声明的net的默认类型为1位(标量)wire类型。Verilog HDL禁止对已经声明过的网络、变量或参数再次声明。下面给出net声明的语法格式:
<net_type> [range] [delay] <net_name>[,net_name];
其中:
net_type:表示网络型数据数据的类型。
range:用来指定数据为标量或矢量。若该项默认,表示数据类型为1位的标量;反之,由该项指定数据的矢量形式。
delay:指定仿真延迟时间。
net_name:net名称,一次可定义多个net,用逗号分开。

【例3.15】网络的声明
wand w; // 一个标量wand类型net
tri [15: 0] bus; // 16位三态总线
wire [0: 31] w1, w2; // 两个32位wire,MSB为bit0
net类型包括多种不同的种类,表3.2给出了这些常用的不同类型的功能及其可综合性。



如果没有显示声明,那么在以下情况中,一个默认net型数据类型就被指定。
 在一个端口表达式的声明中,如果没有对端口的数据类型进行显式说明,那么默认的端口数据类型就为wire型,且默认的wire型矢量的位宽与矢量型端口声明的位宽相同。

 在基本元件例化。模块例化的端口列表中,如果先前没有对端口的数据类型进行显式说明,那么默认的端口数据类型为网络型标量。

 如果一个标识符出现在连续赋值语句的左侧,而该标识符先前未曾被声明,那么该标识符的数据类型就被隐式声明为网络型标量。
网络数据类型包含多种不同种类的网络子类型:wire型,tri型,wor型,trior型,wand型,triand型,trireg型,tri1型,tri0型,supply0型,supply1型。
简单的网络类型说明语法为:
net_kind[msb:lsb]net1,net2, . . . , netN;
其中:net_kind是上述网络类型的一种。msb和lsb是用于定义网络范围的常量表达式;范围定义是可选的;如果没有定义范围,默认的网络类型为1位。

网络型数据的默认初始化值为Z。带有驱动的网络型数据应当为它们的驱动输出指定默认值。trireg网络型数据时一个例外。它的默认初始值为x,而且在声明语句中应当为其指定电荷量强度。

在一个网络型数据类型声明中,可以指定两类强度:电荷量强度(charge strength)和驱动强度(drive strength)。电荷量强度只有trireg网络类型的声明中,才可以使用该强度;驱动强度只有在一个网络型数据的声明语句中对数据对象进行了连续赋 值,才可以使用该强度。门级元件的声明只能制定驱动强度。下面简要说明以下这两种强度的含义及其功能:

1)电荷量强度(charge strength)
一个trireg网络型数据用于模拟电荷存储。电荷量强度可由下面的关键字来制定电容量
的相对大小:small、medium、large。默认的电荷强度为medium。
一个trireg网络型数据能够模拟一个电荷存储节点,该节点的电荷量将随时间而逐渐衰减。对于一个trireg网络型数据在仿真时,其电荷衰减时间应当制定为延迟时间。

2)驱动强度(drive strength)
在一个网络型数据的声明语句中如果对数据对象进行了连续赋值,就可以为生命的数据对象指定驱动强度。

1.wire和tri网络类型
用于连接单元的连线是最常见的网络类型。连线与三态线(tri)网语法和语义一致;三态线可以用于描述多个驱动源驱动同一根线的网络类型;并且没有其他特殊的意义。如果多个驱动源驱动一个连线(或三态网络),网络的有效值由表3.3确定。

 

 
常用的网络类型由关键词wire定义。wire型变量的定义格式如下:
wire [n-1:0] <name1>,<name2>,…<namen>;
其中name1,…,namen表示wire型名字。

【例3.16】wire型变量的说明
wire L; //将上述电路的输出信号L声明为网络型变量
wire [7:0] data bus; //声明一个8bit宽的网络型总线变量

2.wor和trior网络类型
wor和trior用于连线型逻辑结构建模。当有多个驱动源驱动wor和trior型数据时,将产生线或结构。如果驱动源中任一个为1,那么网络型数据的 值也为1。线或和三态线或(trior)在语法和功能上是一致的。如果多个驱动源驱动这类网,网的有效值由表3.4决定。

 
3.wand和triand网络类型
线与(wand)网指如果某个驱动源为0,那么网络的值为0。当有多个驱动源驱动wand和triand型数据时,将产生线与结构。线与和三态线与(triand)网在语法和功能上是一致的。如果这类网络存在多个驱动源,网络的有效值由表3.5决定。


4.Trireg网络类型

此网络存储数值(类似于寄存器),并且用于电容节点的建模。当三态寄存器(trireg)的所有驱动源都处于高阻态,也就是说,值为z时,三态寄存器网络 保存作用在网络上的最后一个值。此外,三态寄存器网络的默认初始值为x。一个trireg网络型数据可以处于驱动和电容性两种状态之一:

1)驱动状态:当至少被一个驱动源驱动时,trireg网型数据有一个值(1、0、x)。判
决值被导入trireg型数据,也就是trireg型网络的驱动值。
2)电容性状态:如果所有驱动源都处于高阻状态(z),trireg网络型数据则保持它最
后的驱动值。高阻值不会从驱动源导入trireg网络型数据。
根据trireg网型数据声明语句中的指定,trireg网型数据处于电容性状态时其电荷量强度
可以是small、medium或large。同样,trireg网型数据处于驱动状态时,根据驱动源的强度,其驱动强度可以是supply、strong、pull或weak。

5.tri0和tri1网络类型
这类网络类型可用于线逻辑的建模,即网络有多于一个驱动源。tri0(tri1)网络的特征是,若无驱动源驱动,它的值为0(tri1的值为1)。网络值 的驱动强度都为pull。tri0相当于这样一个wire型网络:有一个强度为pull的0值连续驱动该wire。同样,tri1相当于这样一个wire 型网络:有一个强度为pull的1值连续驱动该wire。表3.6给出在多个驱动源情况下tri0或tri1网的有效值。

 

 
6.supply0和supply1网络类型
supply0用于对“地”建模,即低电平0;supply1网用于对电源建模,即高电平1。

【例3.17】supply0和supply1网络类型描述
supply0 Gnd,ClkGnd;
supply1 [2:0] Vcc;

7.未说明的网络
在Verilog HDL中,有可能不必声明某种网络类型。在这样的情况下,网络类型为1位网络。可以使用`default_nettype编译器指令改变这一隐式网络说明方式。使用方法如下:
`default_nettypenet_kind
例如,带有下列编译器指令:
`default_nettype wand
任何未被说明的网默认为1位线与网。

3.5.1.2变量数据类型

变量时数据存储元件的抽象。从一次赋值到下一次赋值之前,变量应当保持一个值不变。程序中的赋值语句将触发存储在数据元件中的值改变。对于 reg,time和integer这些变量型数据类型,它们的初始值应当是未知(x)。对于real和realtime变量型数据类型,默认的初始值是 0.0。如果使用变量声明赋值语句,那么变量将采用这个声明赋值语句所赋的值作为初值,这与initial结构中对变量的赋值等效。注意,在变量数据类型 中,只有reg和integer变量型数据类型是可综合的,其它是不可综合的。

1.整型变量声明
整型变量常用于对循环控制变量的说明,在算术运算中被视为二进制补码形式的有符号数。整型数据与32位的寄存器型数据在实际意义上相同,只是寄存器型数据被当做无符号数来处理。

【例3.18】整数变量的声明
integer i,j;
integer[31:0] D;
需要注意的是虽然interger有位宽度的声明,但是integer型变量不能作为位向量访问。D[6]和D[16:0]的声明都是非法的。在综合时,integer型变量的初始值是x。

2.实数型变量声明
实数型数据在机器码表示法中是浮点型数值,可用于对延迟时间的计算。实数型变量是不可综合的。

3.时间型变量声明
时间型变量与整型变量类似,只是它是64位的无符号数。时间型变量主要用于对仿真时间的存储与计算处理,常与系统函数$time一起使用。

4.寄存器型变量声明
寄存器型变量对应的是具有状态保持作用的硬件电路,如触发器。锁存器等。寄存器型变量与网络络数据的区别主要在于:寄存器型变量保持最后一次的赋值,而 wire型数据需要有连续的驱动。寄存器型变量只能在initial或always内部被赋值。寄存器型变量声明的格式如下:

<reg_type> [range] <reg_name>[, reg_name];
其中:
reg_type为寄存器类型;range为矢量范围,[MSB:LSB]格式,只对reg类型有效; reg_name为reg型变量的名字,一次可定义多个reg型变量,使用逗号分开。

【例3.19】寄存器型变量的声明及使用
module mult(clk, rst, A_IN, B_OUT);
input clk,rst,A_IN;
output B_OUT;
reg arb_onebit = 1'b0;
always @(posedge clk or posedge rst)
begin
if (rst)
arb_onebit <= 1'b1;
else
arb_onebit <= A_IN;
end
end
B_OUT <= arb_onebit;
endmodule

3.5.2 参数

Verilog HDL中的参数(parameter)既不属于变量类型也不属于网络类型范畴。参数不是变量,而是常量。用参数声明一个可变常量,常用于定义延时及宽度等参数。参数定义的格式:
parameter par_name1=expression1,…….,par_namen=expression;
其中:
par_name1,....par_namen为参数的名字;expression1,....,expression为表达式。

【例3.20】参数的声明及使用
parameter BUS_WIDTH=8;
reg [BUS_WIDTH-1:0] my_reg;
可一次定义多个参数,用逗号隔开。参数的定义是局部的,只在当前模块中有效。参数定义可使用以前定义的整数和实数参数。
参数值也可以在编译时被改变。改变参数值可以使用参数定义语句或通过在模块初始化语句中定义参数值。

【例3.21】参数的声明及使用
module lpm_reg (out, in, en, reset, clk);
parameter SIZE=1;
input in, en, reset, clk;
output out;
wire [SIZE-1:0] in;
reg [SIZE-1:0] out;
always @(posedge clk or negedge reset)
begin
if (!reset) out<=1’b0;
else
if(en) out<=in;
else out <= out;
end
endmodule

3.5.3向量

在一个net或reg型声明中,如果没有指定范围,就被看做是1比特位宽,也就是通常所说的标量。通过指定范围来声明多位的net或reg型数据,则成为矢量。

1.向量说明
向量范围由常量表达式来说明(也就是通常所说的数组)。msb_constant_expression_r(最高位常量表达式)代表范围的左侧 值,lsb_constant_expression_r(最低位常量表达式)代表范围的右侧值。右侧表达式的值可以大于、等于、小于左侧表达式的值。

net和reg型向量遵循以2为模(2n)的乘幂算术运算法则,此处的n值是向量的位宽。net和reg型向量如果没有被声明为有符号量或者链接到一个已声明为有符号的数据端口,那么该向量被隐含当做无符号的量。
向量可以将已声明过类型的元素组合成多维的数据对象。向量声明时,应当在声明的数据标识符后面指定元素的地址范围。每一个维度代表一个地址范围。数组可以 是一维向量(一个地址范围)也可以是多维向量(多重地址范围)。向量的索引表达式应当是常量表达式,该常量表达式的值应当是整数。一个数组元素可以通过一 条单独的赋值语句被赋值,但是整个向量或向量的一部分也不能为一个表达式赋值。要给一个向量元素赋值,需要为该向量元素指定索引。向量索引可以是一个表达 式,这就为向量元素的选择提供了一种机制,即依靠对该向量索引表达式中其他的网络数据或变量值的运算结果来定位向量元素。

【例3.22】多维向量的声明实例1
wire [7:0] array2 [0:255][0:15]
该声明表示一个256ⅹ16的wire型数据,其中的每个数据是8位的宽度。只能在结构化描述的Verilog HDL中分配。

【例3.23】多维向量的声明实例2
reg [63:0] regarray2 [255:0][7:0]
该声明表示一个256x8的reg型数据,其中的每个数据是64位宽度。只能在行为化描述的Verilog HDL中分配。

【例3.24】多维向量的声明实例3
wire [7:0] array3 [0:15][0:255][0:15]
该声明表示一个三维的向量,表示16个256x16的wire型数据,每个数据8位宽度。只能在结构化描述的Verilog HDL中分配。

2.向量网络型数据的可访问性
vectored和scalared是矢量网络型或矢量寄存器型数据声明中的可选择关键字。如果这些关键字被使用,那么矢量的某些操作就会受约束。如果使 用关键字vectored,那么矢量的位选择或部分位选择以及强度指定就被禁止,而PLI就会认为数据对象未被展开。如果使用关键字scalared,那 么矢量的位或部分位选择就被允许,PLI认为数据对象将被展开。下例是使用关键字vectored和scalared的例子。

【例3.25】关键字vectored和scalared
tri scalared[63:0] bus64; //一个将被展开的数据总线
tri vectored[31:0] data; //一个未被展开的数据总线

3.存储器
如果一个向量的元素类型为reg型,那么这样的一维向量也称为存储器。存储器只用于ROM(只读存储器)、RAM(随机存取存储器)和寄存器组建模。向量 中的每一个寄存器也叫做元素或字,并且是通过单一的索引来寻址的。一个n位的寄存器可以通过一条单独的赋值语句被赋值,但是整个存储器不能通过这样的一条 语句被赋值。为了对存储器的某个字赋值,需要为该字指定数组索引。该索引可以是一个表达式,该表达式中含有其他的变量或网络数据,通过对该表达式的运算, 得到一个结果值,从而定位存储器的字。

【例3.26】存储器型的声明
reg[7:0] mymemory[1023:0];
上述声明定义了一个1024个存储单元的存储器变量mymemory,每个存储单元的字长为8位。在表达式中可以用下面的语句来使用存储器。
mymemory[7]=75; //存储器mymemory的第7个字被赋值75



;