其他数据类型在后面的章节里逐步介绍,读者也可以查阅附录中VerilogHDL语法参考书的有关章节逐步掌握。其他的类型如下:large型、medium型、scalared型、time型、small型、tri型、trio型、tri1型、triand型、trior型、trireg型、vectored型、wand型和wor型。
常量是在程序运行过程中其值不能被改变的量。下面首先对在VerilogHDL语言中使用的数字及其表示方式进行介绍。
(1)整数。
在VerilogHDL中,整型常量有以下4种进制表示形式。
①二进制整数(b或B)。
②十进制整数(d或D)。
③十六进制整数(h或H)。
④八进制整数(o或O)。
数字表达方式有以下3种。
①<位宽><进制><数字>,这是一种全面的描述方式。
②<进制><数字>,在这种描述方式中,数字的位宽采用缺省位宽(这由具体的机器系统决定,但至少32位)。
③<数字>,在这种描述方式中,采用缺省进制十进制。
在表达式中,位宽指明了数字的精确位数。例如:一个4位二进制数数字的位宽为4,一个4位十六进制数数字的位宽为16(因为每单个十六进制数要用4位二进制数来表示),如下例所示:
(2)x和z值。
在数字电路中,x代表不定值,z代表高阻值。一个x可以用来定义十六/八/二进制数的四/三/一位二进制数的状态。z的表示方式同x类似。z还有一种表达方式是可以写作。在使用case表达式时建议使用这种写法,以提高程序的可读性,如下例所示:
(3)负数。
一个数字可以被定义为负数,只需在位宽表达式前加一个减号,并且减号必须写在数字定义表达式的最前面。注意减号不可以放在位宽和进制之间,也不可以放在进制和具体的数之间,如下例所示:
(4)下划线(underscore_)。
下划线可以用来分隔数字的表达以提高程序可读性。但不可以用在位宽和进制处,只能用在具体的数字之间,例如:
在VerilogHDL中用parameter来定义常量,即用parameter来定义一个标识符代表一个常量,称为符号常量,即标识符形式的常量。采用标识符代表一个常量可提高程序的可读性和可维护性。parameter型数据是一种常数型的数据,其说明格式如下:
Parameter参数名1=表达式,参数名2=表达式,…,参数名n=表达式;
parameter是参数型数据的确认符,确认符后跟着一个用逗号分隔开的赋值语句表。在每一个赋值语句的右边必须是一个常数表达式。也就是说,该表达式只能包含数字或先前已定义过的参数,例如:
parametermsb=7;//定义参数msb为常量7
parametere=25,f=29;//定义两个常数参数
parameterbyte_size=8,byte_msb=byte_size-1;//用常数表达式赋值
parameteraverage_delay=(r+f)/2;//用常数表达式赋值
……………
endmodule
moduleTop;
wire[4:0]A5;
wire[15:0]F16;
wire[31:0]F32;
Decode#(4,0)D1(A4,F16);//模块引用,并传递参数(4,0)
Decode#(5)D2(A5,F32);//模块引用,并传递参数(5)
在引用Decode实例时,D1和D2的Width将采用不同的值,分别为4和5,且D1的Polarity将为0。可用例子中所用的方法来改变参数,即用“#(4,0)”向D1中传递“Width=4,Polarity=0”,用“#(5)”向D2中传递“Width=5,Polarit=1”。
变量是在程序运行过程中,其值可以改变的量。在VerilogHDL中变量类型有很多种,这里只对常用的几种变量进行介绍。
wire型变量通常是用来表示单个门驱动或连续赋值语句驱动的网络型数据,tri型变量则用来表示多驱动器驱动的网络型数据。如果wire型或tri型变量没有定义逻辑强度(logicstrength),在多驱动源的情况下,逻辑值会发生冲突,从而产生不确定值。
表1所示为在同等驱动强度下,两个驱动源驱动的wire型和tri型变量的真值表。
表1wire/tri型变量真值表
wire/tri型变量双驱动源运算结果
驱动源1
驱动源2
0
1
x
z
也可以如下表示:
wire[n:1]变量名1,变量名2,…,变量名i;//共有i条总线,每条总线内有n条线路
wirea;//定义了一个一位的wire型变量
wire[7:0]b;//定义了一个八位的wire型变量
wire[4:1]c,d;//定义了两个四位的wire型变量
reg[n-1:0]变量名1,变量名2,…,变量名i;//共有i条总线,每条总线内有n条线路
reg[n:1]变量名1,变量名2,…,变量名i;//共有i条总线,每条总线内有n条线路
regrega;//定义了一个一位的名为rega的reg型变量
reg[3:0]regb;//定义了一个四位的名为regb的reg型变量
reg[4:1]regc,regd;//定义了两个四位的名为regc和regd的reg型变量
reg型变量可以赋正值,也可以赋负值。但当一个reg型变量是一个表达式中的操作数时,它的值将被当作是无符号值,即正值。例如:当一个四位的寄存器用作表达式中的操作数时,如果开始寄存器被赋以值-1,则在表达式中进行运算时,其值被认为是+15。
reg[n-1:0]存储器名[m-1:0];
或:
reg[n-1:0]存储器名[m:1];
在这里,reg[n-1:0]定义了存储器中每一个存储单元的大小,即该存储单元是一个n位的寄存器。存储器名后的[m-1:0]或[m:1]则定义了该存储器中有多少个这样的寄存器。最后用分号结束定义语句。下面举例说明:
reg[7:0]mema[255:0];//定义一个名为mema的256×8的存储器
这个例子定义了一个名为mema的存储器,该存储器有256个8位的存储器。该存储器的地址范围是0~255。需要注意的是,对存储器进行地址索引的表达式必须是常数表达式。
parameterwordsize=16,memsize=256;//定义两个参数
reg[wordsize-1:0]mem[memsize-1:0],writereg,readreg;//使用可变参数来定义存储器
尽管memory型数据和reg型数据的定义格式很相似,但要注意其不同之处。如一个由n个1位寄存器构成的存储器组是不同于一个n位的寄存器的,如下所示:
reg[n-1:0]rega;//一个n位的寄存器
regmema[n-1:0];//一个由n个1位寄存器构成的存储器组
一个n位的寄存器可以在一条赋值语句里进行赋值,而一个完整的存储器则不行,例如:
rega=0;//合法赋值语句
mema=0;//非法赋值语句
如果想对memory中的存储单元进行读写操作,必须指定该单元在存储器中的地址。下面的写法是正确的。
mema[3]=0;//给memory中的第3个存储单元赋值为0。
VerilogHDL语言的运算符范围很广,其运算符按其功能可分为以下几类。
在VerilogHDL语言中运算符所带的操作数是不同的,按其所带操作数的个数运算符可分为以下3种。
单目运算符(unaryoperator):可以带一个操作数,操作数放在运算符的右边。
二目运算符(binaryoperator):可以带两个操作数,操作数放在运算符的两边。
三目运算符(ternaryoperator):可以带三个操作数,这三个操作数用三目运算符分隔开。
例如:
clock=~clock;//~是一个单目取反运算符,clock是操作数。
c=a|b;//|是一个二目按位或运算符,a和b是操作数。
r=st:u;//:是一个三目条件运算符,s,t,u是操作数。
下面对常用的几种运算符进行介绍。
在VerilogHDL语言中,算术运算符又称为二进制运算符,共有下面几种。
在进行整数除法运算时,结果值要略去小数部分,只取整数部分。而进行取模运算时,结果值的符号位采用模运算式里第一个操作数的符号位,例如:
10%31//余数为1
11%32//余数为2
12%30//余数为0,即无余数
-10%3-1//结果取第一个操作数的符号位,所以余数为-1
11%32//结果取第一个操作数的符号位,所以余数为2.
注意
在进行算术运算操作时,如果某一个操作数有不确定的值x,则整个结果也为不定值x。
VerilogHDL作为一种硬件描述语言是针对硬件电路而言的。在硬件电路中信号有4种状态值1、0、x和z。在电路中信号进行与或非时,反映在VerilogHDL中则是相应的操作数的位运算。VerilogHDL提供了以下5种位运算符。
说明:
下面对各运算符分别进行介绍。
“取反”运算符~
~是一个单目运算符,用来对一个操作数进行按位取反运算。如表2所示为单目运算符~的运算规则表。
表2~运算规则表
~运算
操作数
结果
举例说明:
“按位与”运算符&
按位与运算就是将两个操作数的相应位进行与运算,其运算规则如表3所示。
表3&运算规则表
&运算
操作数1
操作数2
“按位或”运算符|
按位或运算就是将两个操作数的相应位进行或运算,其运算规则如表4所示。
表4|运算规则表
|运算
“按位异或”运算符^(也称之为XOR运算符)
按位异或运算就是将两个操作数的相应位进行异或运算,其运算规则如表5所示。
表5^运算规则表
^运算
“按位同或”运算符^~
按位同或运算就是将两个操作数的相应位先进行异或运算再进行非运算,其运算规则如表6所示。
表6^~运算规则表
^~运算
不同长度的数据进行位运算
两个长度不同的数据进行位运算时,系统会自动将两者按右端对齐。位数少的操作数会在相应的高位用0填满,以使两个操作数按位进行操作。
在VerilogHDL语言中存在3种逻辑运算符。
“&&”和“||”是二目运算符,它要求有两个操作数,如(a>b)&&(b>c),(ab)。如表7所示为逻辑运算的真值表。它表示当a和b的值为不同的组合时,各种逻辑运算所得到的值。
表7逻辑运算真值表
逻辑运算及结果
a
b
!a
!b
a&&b
a||b
真
假
逻辑运算符中“&&”和“||”的优先级别低于关系运算符,“!”的优先级别高于算术运算符,例如。
(a>b)&&(x>y)可写成:a>b&&x>y
(a==b)||(x==y)可写成:a==b||x==y
(!a)||(a>b)可写成:!a||a>b
为了提高程序的可读性,明确表达各运算符间的优先关系,建议使用括号。
关系运算符共有以下4种。
所有的关系运算符有着相同的优先级别。关系运算符的优先级别低于算术运算符的优先级别,例如。
a a<(size-1) size-(1