常用数据类型
Verilog HDL中总共有19种数据类型,数据类型是用来表明数字电路硬件中的数据贮存和传送元素的。在本书中,咱们先只介绍4个最根本的数据类型,它们别离是:reg型,wire型,integer型和parameter型。
其他数据类型在后面的章节里逐渐介绍,读者也能够查阅附录中Verilog HDL语法参考书的有关章节逐渐把握。其他的类型如下:large型、medium型、scalared型、time型、small型、tri型、trio型、tri1型、triand型、trior型、trireg型、vectored型、wand型和wor型。
这些数据类型除time型外都与根本逻辑单元建库有关,与体系规划没有很大的联系。在一般电路规划主动化的环境下,仿真用的根本部件库是由半导体厂家和EDA东西厂家一起供给的。体系规划工程师不用过多地关心门级和开关级的Verilog HDL语法现象。Verilog HDL言语中也有常量和变量之分,它们别离归于以上这些类型。下面临最常用的几种进行介绍。
常量
常量是在程序运转进程中其值不能被改动的量。下面首要对在Verilog HDL言语中运用的数字及其表明方法进行介绍。
1.数字
(1)整数。
在Verilog HDL中,整型常量有以下4种进制表明方法。
① 二进制整数(b或B)。
② 十进制整数(d或D)。
③ 十六进制整数(h或H)。
④ 八进制整数(o或O)。
数字表达方法有以下3种。
① 位宽>进制>数字>,这是一种全面的描绘方法。
② 进制>数字>,在这种描绘方法中,数字的位宽选用缺省位宽(这由具体的机器体系决议,但至少32位)。
③ 数字>,在这种描绘方法中,选用缺省进制十进制。
在表达式中,位宽指明晰数字的准确位数。例如:一个4位二进制数数字的位宽为4,一个4位十六进制数数字的位宽为16(因为每单个十六进制数要用4位二进制数来表明),如下例所示:
8b10101100 //位宽为8的数的二进制表明,b表明二进制
8ha2 //位宽为8的数的十六进制,h表明十六进制。
(2)x和z值。
在数字电路中,x代表不定值,z代表高阻值。一个x能够用来界说十六/八/二进制数的四/三/一位二进制数的状况。z的表明方法同x类似。z还有一种表达方法是能够写作?。在运用case表达式时主张运用这种写法,以进步程序的可读性,如下例所示:
4b10x0 //位宽为4的二进制数从低位数起第二位为不定值
4b101z //位宽为4的二进制数从低位数起第一位为高阻值
12dz //位宽为12的十进制数其值为高阻值(第一种表达方法)
12d? //位宽为12的十进制数其值为高阻值(第二种表达方法)
8h4x //位宽为8的十六进制数其低四位值为不定值
(3)负数。
一个数字能够被界说为负数,只需在位宽表达式前加一个减号,并且减号有必要写在数字界说表达式的最前面。留意减号不能够放在位宽和进制之间,也不能够放在进制和具体的数之间,如下例所示:
-8d5 //这个表达式代表5的补数(用8位二进制数表明)
8d-5 //不合法格局
(4)下划线(underscore_)。
下划线能够用来分隔数字的表达以进步程序可读性。但不能够用在位宽和进制处,只能用在具体的数字之间,例如:
16b1010_1011_1111_1010 //合法格局
8b_0011_1010 //不合法格局
当常量不声明位数时,默许值是32位,每个字母用8位的ASCII值表明,例如:
10=32d10=32b1010 //十进制和二进制
1=32d1=32b1 //十进制和二进制
-1=-32d1=32hFFFFFFFF //十进制和十六进制
BX=32BX=32BXXXXXXX…X //默许声明为32位
AB=16B01000001_01000010 //每个字母用8位表明
2.参数(Parameter)
在Verilog HDL顶用parameter来界说常量,即用parameter来界说一个标识符代表一个常量,称为符号常量,即标识符方法的常量。选用标识符代表一个常量可进步程序的可读性和可维护性。parameter型数据是一种常数型的数据,其阐明格局如下:
Parameter 参数名1=表达式,参数名2=表达式, …, 参数名n=表达式;
parameter是参数型数据的承认符,承认符后跟着一个用逗号分离隔的赋值句子表。在每一个赋值句子的右边有必要是一个常数表达式。也便是说,该表达式只能包含数字或从前已界说过的参数,例如:
parameter msb=7; //界说参数msb为常量7
parameter e=25, f=29; //界说两个常数参数
parameter r=5.7; //声明r为一个实型参数
parameter byte_size=8, byte_msb=byte_size-1; //用常数表达式赋值
parameter average_delay = (r+f)/2; //用常数表达式赋值
参数型常数常常用于界说延迟时间和变量宽度。在模块或实例引证时可经过参数传递改动在被引证模块或实例中已界说的参数。下面将经过一个比如进一步阐明在层次调用的电路中改动参数常用的一些用法。
module Decode(A,F); //模块声明
parameter Width=1, Polarity=1; //参数声明
……………
endmodule
module Top;
wire[3:0] A4; //连线资源声明
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)
endmodule
在引证Decode实例时,D1和D2的Width将选用不同的值,别离为4和5,且D1的Polarity将为0。可用比如中所用的方法来改动参数,即用“#(4,0)”向D1中传递“Width=4,Polarity=0”,用“#(5)”向D2中传递“Width=5,Polarit=1”。
变量
变量是在程序运转进程中,其值能够改动的量。在Verilog HDL中变量类型有很多种,这儿只对常用的几种变量进行介绍。
1.网络类型变量
网络类型表明结构实体(例如门)之间的物理衔接。网络类型的变量不能贮存值,并且它必需遭到驱动器(例如门或接连赋值句子,assign)的驱动。假如没有驱动器衔接到网络类型的变量上,则该变量便是高阻的,即其值为z。
常用的网络类型变量包含wire型和tri型。这两种变量都是用于衔接器材单元,它们具有相同的语法格局和功用。之所以供给这两种姓名来表达相同的概念是为了与模型中所运用的变量的实际情况相一致。
wire型变量一般是用来表明单个门驱动或接连赋值句子驱动的网络型数据,tri型变量则用来表明多驱动器驱动的网络型数据。假如wire型或tri型变量没有界说逻辑强度(logic strength),在多驱动源的情况下,逻辑值会发生冲突,然后发生不确定值。
表1所示为在平等驱动强度下,两个驱动源驱动的wire型和tri型变量的真值表。
表1 wire/tri型变量真值表
wire/tri型变量双驱动源运算成果 |
||||
驱动源1 驱动源2 |
0 |
1 |
x |
z |
0 |
0 |
x |
x |
0 |
1 |
|
1 |
x |
1 |
x |
x |
x |
x |
x |
z |
0 |
1 |
x |
z |
wire型变量常用来表明用于以assign关键字指定的组合逻辑信号。Verilog程序模块中输入/输出信号类型缺省时主动界说为wire型。wire型变量能够用作任何方程式的输入,也能够用作“assign”句子或实例元件的输出。wire型变量的声明格局如下:
wire [n-1:0] 变量名1,变量名2,…,变量名i; //共有i条总线,每条总线内有n条线路
也能够如下表明:
wire [n:1] 变量名1,变量名2,…,变量名i; //共有i条总线,每条总线内有n条线路
其间,wire是wire型变量的承认符,[n-1:0]和[n:1]代表该变量的位宽,即该变量有几位,最终跟着的是变量的姓名。假如一次界说多个变量,变量名之间用逗号离隔。声明句子的最终要用分号表明句子完毕。如下所示:
wire a; //界说了一个一位的wire型变量
wire [7:0] b; //界说了一个八位的wire型变量
wire [4:1] c, d; //界说了两个四位的wire型变量
2.寄存器型变量
寄存器是数据贮存单元的笼统。寄存器型变量的关键字是reg。经过赋值句子能够改动寄存器贮存的值,其效果与改动触发器贮存的值适当。
Verilog HDL言语供给了功用强大的结构句子使规划者能有效地操控是否履行这些赋值句子。这些操控结构用来描绘硬件触发条件,例如时钟的上升沿和多路器的选通信号。reg类型变量的缺省初始值为不定值,即x。
reg型变量常用来表明用于“always”模块内的指定信号,常代表触发器。一般,在规划中要由“always”块经过运用行为描绘句子来表达逻辑联系。在“always”块内被赋值的每一个信号都有必要界说成reg型。和wire型变量类似,reg型变量的声明格局如下:
reg [n-1:0] 变量名1,变量名2,…,变量名i; //共有i条总线,每条总线内有n条线路
也能够如下表明:
reg [n:1] 变量名1,变量名2,…,变量名i; //共有i条总线,每条总线内有n条线路
其间,reg是reg型变量的承认标识符,[n-1:0]和[n:1]代表该变量的位宽,即该变量有几位(bit),最终跟着的是变量的姓名。假如一次界说多个变量,变量名之间用逗号离隔。声明句子的最终要用分号表明句子完毕。如下所示:
reg rega; //界说了一个一位的名为rega的reg型变量
reg [3:0] regb; //界说了一个四位的名为regb的reg型变量
reg [4:1] regc, regd; //界说了两个四位的名为regc和regd的reg型变量
reg型变量能够赋正值,也能够赋负值。但当一个reg型变量是一个表达式中的操作数时,它的值将被当作是无符号值,即正值。例如:当一个四位的寄存器用作表达式中的操作数时,假如开端寄存器被赋以值-1,则在表达式中进行运算时,其值被认为是+15。
3.存储器型变量
Verilog HDL经过对reg型变量树立数组来对存储器建模,用于描绘RAM型存储器、ROM存储器和reg文件。数组中的每一个单元经过一个数组索引进行寻址。因为在Verilog言语中没有多维数组存在,因而memory型数据是经过扩展reg型数据的地址规模来生成的。其格局如下:
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。需求留意的是,对存储器进行地址索引的表达式有必要是常数表达式。
别的,在同一个数据类型声明句子里,能够一起界说存储器型数据和reg型数据。 例如:
parameter wordsize=16, memsize=256; //界说两个参数
reg [wordsize-1:0] mem[memsize-1:0],writereg, readreg; //运用可变参数来界说存储器
虽然memory型数据和reg型数据的界说格局很类似,但要留意其不同之处。如一个由n个1位寄存器构成的存储器组是不同于一个n位的寄存器的,如下所示:
reg [n-1:0] rega; //一个n位的寄存器
reg mema [n-1:0]; //一个由n个1位寄存器构成的存储器组
一个n位的寄存器能够在一条赋值句子里进行赋值,而一个完好的存储器则不可,例如:
rega =0; //合法赋值句子
mema =0; //不合法赋值句子
假如想对memory中的存储单元进行读写操作,有必要指定该单元在存储器中的地址。下面的写法是正确的。
mema[3]=0; //给memory中的第3个存储单元赋值为0。
进行寻址的地址索引能够是表达式,这样就能够对存储器中的不同单元进行操作。表达式的值能够取决于电路中其他的寄存器的值。例如能够用一个加法计数器来做RAM的地址索引。
常用运算符
Verilog HDL言语的运算符规模很广,其运算符按其功用可分为以下几类。
- 算术运算符:(+,-,×,/,%)。
- 赋值运算符:(=,=)。
- 联系运算符:(>,,>=,=)。
- 逻辑运算符:(,||,!)。
- 条件运算符:(?:)。
- 位运算符:(~,|,^,,^~)。
- 移位运算符:(,>>)。
- 拼接运算符:({ })。
- 其他
在Verilog HDL言语中运算符所带的操作数是不同的,按其所带操作数的个数运算符可分为以下3种。
单目运算符(unary operator):能够带一个操作数,操作数放在运算符的右边。
二目运算符(binary operator):能够带两个操作数,操作数放在运算符的两头。
三目运算符(ternary operator):能够带三个操作数,这三个操作数用三目运算符分离隔。
例如:
clock = ~clock; // ~ 是一个单目取反运算符,clock是操作数。
c = a | b; // | 是一个二目按位或运算符,a 和 b是操作数。
r = s ? t : u; // ?: 是一个三目条件运算符,s,t,u是操作数。
下面临常用的几种运算符进行介绍。
1.根本的算术运算符
在Verilog HDL言语中,算术运算符又称为二进制运算符,共有下面几种。
- +:(加法运算符或正值运算符,如ega+regb、+3)。
- −:(减法运算符或负值运算符,如rega−3、−3)。
- ´:(乘法运算符,如rega´3)。
- /:(除法运算符,如5/3)。
- % :(模运算符或求余运算符,要求%两边均为整型数据,如7%3的值为1)。
在进行整数除法运算时,成果值要省略小数部分,只取整数部分。而进行取模运算时,成果值的符号位选用模运算式里第一个操作数的符号位,例如:
10%3 1 //余数为1
11%3 2 //余数为2
12%3 0 //余数为0,即无余数
-10%3 -1 //成果取第一个操作数的符号位,所以余数为-1
11%3 2 //成果取第一个操作数的符号位,所以余数为2.
留意 |
在进行算术运算操作时,假如某一个操作数有不确定的值x,则整个成果也为不定值x。 |
2.位运算符
Verilog HDL作为一种硬件描绘言语是针对硬件电路而言的。在硬件电路中信号有4种状况值1、0、x和z。在电路中信号进行与或非时,反映在Verilog HDL中则是相应的操作数的位运算。Verilog HDL供给了以下5种位运算符。
- ~ :(取反)
- :(按位与)
- | :(按位或)
- ^ :(按位异或)
- ^~:(按位同或(异或非))
阐明:
- 位运算符中除了~是单目运算符以外,均为二目运算符,即要求运算符两边各有一个操作数。
- 位运算符中的二目运算符要求对两个操作数的相应位进行运算操作。
下面临各运算符别离进行介绍。
“取反”运算符~
~是一个单目运算符,用来对一个操作数进行按位取反运算。如表2所示为单目运算符~的运算规矩表。
表2 ~ 运算规矩表
~运算 |
|
操 作 数 |
结 果 |
1 |
0 |
0 |
1 |
x |
x |
举例阐明:
rega=b1010; //rega的初值为b1010
rega=~rega; //rega的值进行取反运算后变为b0101
“按位与”运算符
按位与运算便是将两个操作数的相应位进行与运算,其运算规矩如表3所示。
表3 运算规矩表
运算 |
|||
操作数1 操作数2 |
0 |
1 |
x |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
x |
x |
0 |
x |
x |
“按位或”运算符 |
按位或运算便是将两个操作数的相应位进行或运算,其运算规矩如表4所示。
表4 | 运算规矩表
| 运算 |
|||
操作数1 操作数2 |
0 |
1 |
x |
0 |
0 |
1 |
x |
1 |
1 |
1 |
1 |
x |
x |
1 |
x |
“按位异或”运算符^(也称之为XOR运算符)
按位异或运算便是将两个操作数的相应位进行异或运算,其运算规矩如表5所示。
表5 ^ 运算规矩表
^ 运算 |
|||
操作数1 操作数2 |
0 |
1 |
x |
0 |
0 |
1 |
x |
1 |
1 |
0 |
x |
x |
x |
x |
x |
“按位同或”运算符^~
按位同或运算便是将两个操作数的相应位先进行异或运算再进行非运算,其运算规矩如表6所示。
表6 ^~ 运算规矩表
^~ 运算 |
|||
操作数1 操作数2 |
0 |
1 |
x |
0 |
1 |
0 |
x |
1 |
0 |
1 |
x |
x |
x |
x |
x |
不同长度的数据进行位运算
两个长度不同的数据进行位运算时,体系会主动将两者按右端对齐。位数少的操作数会在相应的高位用0填满,以使两个操作数按位进行操作。
3.逻辑运算符
在Verilog HDL言语中存在3种逻辑运算符。
- :(逻辑与)
- ||:(逻辑或)
- ! :(逻辑非)
“”和“||”是二目运算符,它要求有两个操作数,如(a>b)(b>c),(ab)||(bc)。“!”是单目运算符,只要求一个操作数,如!(a>b)。如表7所示为逻辑运算的真值表。它表明当a和b的值为不同的组合时,各种逻辑运算所得到的值。
表7 逻辑运算真值表
操 作 数 |
逻辑运算及成果 |
||||
a |
b |
!a |
!b |
ab |
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.联系运算符
联系运算符共有以下4种。
- a b:(a小于b)
- a > b:(a大于b)
- a = b:(a小于或等于b)
- a >= b:(a大于或等于b)
在进行联系运算时,假如声明的联系是假的(flase),则回来值是0;假如声明的联系是真的(true),则回来值是1;假如某个操作数的值不定,则联系是含糊的,回来值是不定值。
一切的联系运算符有着相同的优先等级。联系运算符的优先等级低于算术运算符的优先等级,例如。
a size-1 //这种表达方法等同于下面一行的表达方法
a (size-1)
size – (1 a) //这种表达方法不等同于下面一行的表达方法
size – 1 a
从上面的比如能够看出这两种不同运算符的优先等级。当表达式size -(1a)进行运算时,联系表达式先被运算,然后回来成果值0或1被size减去。而当表达式 size -1a 进行运算时,size先被减去1,然后再同a比较。
5.等式运算符
在Verilog HDL言语中存在4种等式运算符。
- = =:(等于)
- != :(不等于)
- = = =:(等于)
- != =:(不等于)
这4个运算符都是二目运算符,它要求有两个操作数。“= =”和“!=”又称为逻辑等式运算符,其成果由两个操作数的值决议。因为操作数中某些位可能是不定值x和高阻值z,成果可能为不定值x。
“= = =”和“!= =”运算符则不同,它在对操作数进行比较时,对某些位的不定值x和高阻值z也进行比较。两个操作数必需完全一致,其成果才是1,否则为0。“= = =”和“!= =”运算符常用于case表达式的判别,所以又称为“case等式运算符”。
这4个等式运算符的优先等级是相同的。下面画出“= =”与“= = =”的真值表,协助了解两者间的差异。
表8 等式运算符真值表
= = = 运算 |
||||
操作数1 操作数2 |
0 |
1 |
x |
z |
0 |
1 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
0 |
x |
0 |
0 |
1 |
0 |
z |
0 |
0 |
0 |
1 |
= = 运算 |
||||
操作数1 操作数2 |
0 |
1 |
x |
z |
0 |
1 |
0 |
x |
x |
1 |
0 |
1 |
x |
x |
x |
x |
x |
x |
x |
z |
x |
x |
x |
x |
下面举一个比如阐明“= =”与“= = =”的差异。
if(A==1’bx) $display( AisX ); //当A等于X时,这个句子不履行
if(A===1’bx) $display( AisX ); //当A等于X时,这个句子履行
6.移位运算符
在Verilog HDL中有两种移位运算符。
:(左移位运算符)
>>:(右移位运算符)
其运用方法如下:
a >> n;
a n;
a代表要进行移位的操作数,n代表要移几位。这两种移位运算都用0来添补移出的空位。下面举例阐明:
module shift;
reg [3:0] start, result;
initial begin
start = 1; //start在初始时间设为值0001
result = (start2); //移位后,start的值0100,然后赋给result
end
endmodule
从上面的比如能够看出,start在移过两位今后,用0来添补空出的位。进行移位运算时应留意移位前后变量的位数,下面举例阐明。
4’b10011 = 5’b10010; //左移1位后用0添补低位
4’b10012 = 6’b100100; //左移2位后用00添补低位
16 = 32’b1000000; //左移6位后用000000添补低位
4’b1001>>1 = 4’b0100; //右移1位后,低1位丢掉,高1位用0添补
4’b1001>>4 = 4’b0000; //右移4位后,低4位丢掉,高4位用0添补
7.位拼接运算符(Concatation)
在Verilog HDL言语有一个特别的运算符:位拼接运算符{}。用这个运算符能够把两个或多个信号的某些位拼接起来进行运算操作。其运用方法如下:
{信号1的某几位,信号2的某几位,..,..,信号n的某几位}
即把某些信号的某些位具体地列出来,中心用逗号分隔,最终用大括号括起来表明一个全体信号,例如:
{a,b[3:0],w,3’b101}
也能够写成为:
{a,b[3],b[2],b[1],b[0],w,1’b1,1’b0,1’b1}
在位拼接表达式中不允许存在没有指明位数的信号。这是因为在核算拼接信号的位宽的巨细时必需知道其间每个信号的位宽。
位拼接也能够用重复法来简化表达式,如下所示:
{4{w}} //等同于{w,w,w,w}
位拼接还能够用嵌套的方法来表达,如下所示:
{b,{3{a,b}}} //等同于{b,a,b,a,b,a,b}
用于表明重复的表达式有必要是常数表达式,如上例中的4和3。
8.减缩运算符(reduction operator)
减缩运算符是单目运算符,也有与、或、非运算。其与、或、非运算规矩类似于位运算符的与、或、非运算规矩,但其运算进程不同。位运算是对操作数的相应位进行与、或、非运算,操作数是几位数,则运算成果也是几位数。而减缩运算则不同,减缩运算是对单个操作数进行与、或、非递推运算,最终的运算成果是一位的二进制数。
减缩运算的具体运算进程如下。
(1)先将操作数的第一位与第二位进行与、或、非运算。
(2)将运算成果与第三位进行与、或、非运算,顺次类推,直至最终一位。
例如:
reg [3:0] B;
reg C;
C = B;
适当于:
C =( ( B[0]B[1] ) B[2] ) B[3];
因为减缩运算的与、或、非运算规矩类似于位运算符与、或、非运算规矩,这儿不再具体叙述,可参照位运算符的运算规矩介绍。
9.优先等级
各种运算符的优先等级联系如表9所示。
表9 运算符优先等级表
运 算 符 |
优 先 级 别 |
! ~ * / % + - >> = > >= == != === !==
^ ^~ |
|| ? : |
高
低 |