表达式由操作数和操作符组成。表达式能够在呈现数值的任何地方运用。
操作数
操作数能够是以下类型中的一种:
1) 常数
2) 参数
3) 线网
4) 寄存器
5) 位挑选
6) 部分挑选
7) 存储器单元
8) 函数调用
1.1 常数
下面是一些实例。
256,7 //非定长的十进制数。
4’b10_11, 8’h0A //定长的整型常量。
‘b1, ‘hFBA //非定长的整数常量。
90.00006 //实数型常量。
BOND //串常量;每个字符作为8位ASCII值存储。
表达式中的整数值可被解说为有符号数或无符号数。假如表达式中是十进制整数,例如,12被解说为有符号数。假如整数是基数型整数(定长或非定长),那么该整数作为无符号数对待。下面举例阐明。
12是01100的5位向量方式(有符号)
-12是10100的5位向量方式(有符号)
5’b01100是十进制数12(无符号)
5’b10100是十进制数20(无符号)
4’d12是十进制数12(无符号)
更为重要的是对基数标明或非基数标明的负整数处理方式不同。非基数标明方式的负整数作为有符号数处理,而基数标明方式的负整数值作为无符号数。因而-44和-6’o54 (十进制的44等于八进制的54)鄙人例中处理不同。
integer Cone;
. . .
Cone = -44/4
Cone = -6’o54/ 4;
留意-44和-6’o54以相同的位方式求值;可是-44作为有符号数处理,而-6’o54作为无符号数处理。因而榜首个字符中Cone的值为-11,而在第二个赋值中Cone的值为1073741813。
1.2 参数
参数类似于常量,而且运用参数声明进行阐明。下面是参数阐明实例。
parameter LOAD = 4’d12, STORE = 4’d10;
LOAD 和STORE为参数的比如,值分别被声明为12和10。
1.3 线网
可在表达式中运用标量线网(1位)和向量线网(多位)。下面是线网阐明实例。
wire [0:3] Prt; //Prt 为4位向量线网。
wire Bdq; //Bbq 是标量线网。
线网中的值被解说为无符号数。在接连赋值句子中,
assign Prt = -3;
Prt被赋于位向量1101,实际上为十进制的13。鄙人面的接连赋值中,
assign Prt = 4’HA;
Prt被赋于位向量1010,即为十进制的10。
1.4 寄存器
标量和向量寄存器可在表达式中运用。寄存器变量运用寄存器声明进行阐明。例如:
integer TemA, TemB;
reg [1:5] State;
time Que [1:5];
整型寄存器中的值被解说为有符号的二进制补码数,而reg寄存器或时刻寄存器中的值被解说为无符号数。实数和实数时刻类型寄存器中的值被解说为有符号浮点数。
TemA = -10; //TemA值为位向量10110,是10的二进制补码。
TemA = ‘b1011; //TemA值为十进制数11。
State = -10; //State值为位向量10110,即十进制数22。
State = ‘b1011; //State值为位向量01011,是十进制值11。
1.5 位挑选
位挑选从向量中抽取特定的位。方式如下:
net_or_reg_vector [bit_select_expr]
下面是表达式中运用位挑选的比如。
State [1] State [4] //寄存器位挑选。
Prt [0] | Bbq //线网位挑选。
假如挑选表达式的值为x、z,或越界,则位挑选的值为x。例如State [x]值为x。
1.6 部分挑选
在部分挑选中,向量的接连序列被挑选。方式如下:
net_or_reg_vector [msb_const_expr:1sb_const_expr]
其间规模表达式有必要为常数表达式。例如。
State [1:4] //寄存器部分挑选。
Prt [1:3] //线网部分挑选。
挑选规模越界或为x、z时,部分挑选的值为x。
1.7 存储器单元
存储器单元从存储器中挑选一个字。方式如下:
memory [word_address]
例如:
reg [1:8] Ack, Dram [0:63];
. . .
Ack = Dram [60]; //存储器的第60个单元。
不允许对存储器变量值部分挑选或位挑选。例如,
Dram [60] [2] 不允许。
Dram [60] [2:4] 也不允许。
在存储器中读取一个位或部分挑选一个字的办法如下:将存储器单元赋值给寄存器变量,然后对该寄存器变量选用部分挑选或位挑选操作。例如,Ack [2] 和Ack [2:4]是合法的表达式。
1.8 函数调用
表达式中可运用函数调用。函数调用能够是体系函数调用(以$字符开端)或用户界说的函数调用。例如:
$time + SumOfEvents (A, B)
/*$time是体系函数,而且SumOfEvents是在别处界说的用户自界说函数。*/
操作符
Verilog HDL中的操作符能够分为下述类型:
1) 算术操作符
2) 联系操作符
3) 持平操作符
4) 逻辑操作符
5) 按位操作符
6) 归约操作符
7) 移位操作符
8) 条件操作符
9) 衔接和仿制操作符
下表显现了一切操作符的优先级和称号。操作符从最高优先级(顶行)到最低优先级(底行)摆放。同一行中的操作符优先级相同。
除条件操作符从右向左相关外,其他一切操作符自左向右相关。下面的表达式:
A + B – C
等价于:
(A + B ) – C //自左向右
而表达式:
A ? B : C ? D : F
等价于:
A ? B : (C ? D : F) //从右向左
圆扩号能够用于改动优先级的次序,如以下表达式:
(A ? B : C) ? D : F
2.1 算术操作符
算术操作符有:
* +(一元加和二元加)
* -(一元减和二元减)
* *(乘)
* /(除)
* %(取模)
整数除法切断任何小数部分。例如:
7/4 成果为 1
取模操作符求出与榜首个操作符符号相同的余数。
7%4 成果为 3
而:
– 7%4 成果为 -3
假如算术操作符中的恣意操作数是X或Z,那么整个成果为X。例如:
‘b10x1 + ‘b01111 成果为不确认数’bxxxxx
1. 算术操作成果的长度
算术表达式成果的长度由最长的操作数决议。在赋值句子下,算术操作成果的长度由操作符左端方针长度决议。考虑如下实例:
reg [0:3] Arc, Bar, Crt;
reg [0:5] Frx;
. . .
Arc = Bar + Crt;
Frx = Bar + Crt;
榜首个加的成果长度由Bar,Crt和Arc长度决议,长度为4位。第二个加法操作的长度相同由Frx的长度决议(Frx、Bat和Crt中的最长长度),长度为6位。在榜首个赋值中,加法操作的溢出部分被丢掉;而在第二个赋值中,任何溢出的位存储在成果位Frx[1]中。
在较大的表达式中,中心成果的长度怎么确认?在Verilog HDL中界说了如下规矩:表达式中的一切中心成果应取最大操作数的长度(赋值时,此规矩也包括左端方针)。考虑另一个实例:
wire [4:1] Box, Drt;
wire [1:5] Cfg;
wire [1:6] Peg;
wire [1:8] Adt;
. . .
assign Adt = (Box + Cfg) + (Drt + Peg);
表达式左端的操作数最长为6,可是将左端包括在内时,最大长度为8。所以一切的加操作运用8位进行。例如:Box和Cfg相加的成果长度为8位。
2. 无符号数和有符号数
履行算术操作和赋值时,留意哪些操作数为无符号数、哪些操作数为有符号数非常重要。无符号数存储在:
* 线网
* 一般寄存器
* 基数格局标明方式的整数
有符号数存储在:
* 整数寄存器
* 十进制方式的整数
下面是一些赋值句子的实例:
reg [0:5] Bar;
integer Tab;
. . .
Bar = -4’d12; //寄存器变量Bar的十进制数为52,向量值为110100。
Tab = -4’d12; //整数Tab的十进制数为-12,位方式为110100。
-4’d12 / 4 //成果是1073741821。
-12 / 4 //成果是-3
因为Bar是一般寄存器类型变量,只存储无符号数。右端表达式的值为’b110100(12的二进制补码)。因而在赋值后,Bar存储十进制值52。在第二个赋值中,右端表达式相同,值为’b110100,但此刻被赋值为存储有符号数的整数寄存器。Tab存储十进制值-12(位向量为110100)。留意在两种状况下,位向量存储内容都相同;可是在榜首种状况下,向量被解说为无符号数,而在第二种状况下,向量被解说为有符号数。
下面为详细实例:
Bar = – 4’d12/4;
Tab = – 4’d12 /4;
Bar = – 12/4
Tab = – 12/4
在榜首次赋值中,Bar被赋于十进制值61(位向量为111101)。而在第二个赋值中,Tab被赋于与十进制1073741821(位值为0011…11101)。Bar在第三个赋值中赋于与榜首个赋值相同的值。这是因为Bar只存储无符号数。在第四个赋值中,Bar被赋于十进制值-3。
下面是另一些比如:
Bar = 4 – 6;
Tab = 4 – 6;
Bar被赋于十进制值62(-2的二进制补码),而Tab被赋于十进制值-2(位向量为111110)。
下面为另一个实例:
Bar = -2 + (-4);
Tab = -2 + (-4);
Bar被赋于十进制值58(位向量为111010),而Tab被赋于十进制值-6(位向量为111010)。
2.2 联系操作符
联系操作符有:
* >(大于)
* (小于)
* >=(不小于)
* =(不大于)
联系操作符的成果为真(1)或假(0)。假如操作数中有一位为X或Z,那么成果为X。例如:
23 > 45
成果为假(0),而:
52 8’hxFF
成果为x。假如操作数长度不同,长度较短的操作数在最重要的位方向(左方)添0补齐。例如:
‘b1000 > = ‘b01110
等价于:
‘b01000 > = ‘b01110
成果为假(0)。
2.3 持平联系操作符
持平联系操作符有:
* = =(逻辑持平)
* !=(逻辑不等)
* = = =(全等)
* != =(非全等)
假如比较成果为假,则成果为0;不然成果为1。在全等比较中,值x和z严厉按位比较。也就是说,不进行解说,而且成果必定可知。而在逻辑比较中,值x和z具有一般的含义,且成果能够不为x。也就是说,在逻辑比较中,假如两个操作数之一包括x或z,成果为不知道的值(x)。
如下例,假定:
Data = ‘b11x0;
Addr = ‘b11x0;
那么:
Data = = Addr
不定,也就是说值为x,但:
Data = = = Addr
为真,也就是说值为1。
假如操作数的长度不持平,长度较小的操作数在左边添0补位,例如:
2’b10 = = 4’b0010
与下面的表达式相同:
4’b0010 = = 4’b0010
成果为真(1)。
2.4 逻辑操作符
逻辑操作符有:
* (逻辑与)
* || (逻辑或)
* !(逻辑非)
这些操作符在逻辑值0或1上操作。逻辑操作的结构为0或1。例如, 假定:
Crd = ‘b0; //0为假
Dgs = ‘b1; //1为真
那么:
Crd Dgs 成果为0 (假)
Crd || Dgs 成果为1 (真)
! Dgs 成果为0 (假)
关于向量操作, 非0向量作为1处理。例如,假定:
A_Bus = ‘b0110;
B_Bus = ‘b0100;
那么:
A_Bus || B_Bus 成果为1
A_Bus B_Bus 成果为 1
而且:
! A_Bus 与! B_Bus的成果相同。
成果为0。
假如恣意一个操作数包括x,成果也为x。
!x 成果为x
2.5 按位操作符
按位操作符有:
* ~(一元非)
* (二元与)
* |(二元或)
* ^(二元异或)
* ~^, ^~(二元异或非)
这些操作符在输入操作数的对应位上按位操作,并发生向量成果。下表显现关于不同操作符按步操作的成果。
例如,假定,
A = ‘b0110;
B = ‘b0100;
那么:
A | B 成果为0110
A B 成果为0100
假如操作数长度不持平, 长度较小的操作数在最左边添0补位。例如,
‘b0110 ^ ‘b10000
与如下式的操作相同:
‘b00110 ^ ‘b10000
成果为’b10110。
2.6 归约操作符
归约操作符在单一操作数的一切位上操作,并发生1位成果。归约操作符有:
* (归约与)
假如存在位值为0, 那么成果为0;若假如存在位值为x或z,成果为x;不然成果为1。
* ~ (归约与非)
与归约操作符相反。
* | (归约或)
假如存在位值为1,那么成果为1;假如存在位x或z,成果为x;不然成果为0。
* ~| (归约或非)
与归约操作符|相反。
* ^ (归约异或)
假如存在位值为x或z,那么成果为x;不然假如操作数中有偶数个1, 成果为0;不然成果为1。
* ~^ (归约异或非)
与归约操作符^正好相反。
如下所示。假定,
A = ‘b0110;
B = ‘b0100;
那么:
|B 成果为1
B 成果为0
~ A 成果为1
归约异或操作符用于决议向量中是否有位为x。假定,
MyReg = 4’b01x0;
那么:
^MyReg 成果为x
上述功用运用如下的if句子检测:
if (^MyReg = = = 1’bx)
$ display (There is an unknown in the vector MyReg !)
留意逻辑持平(==)操作符不能用于比较;逻辑持平操作符比较将只会发生成果x。全等操作符希望的成果为值1。
2.7 移位操作符
移位操作符有:
* (左移)
* >> (右移)
移位操作符左边操作数移动右侧操作数标明的次数,它是一个逻辑移位。闲暇位添0补位。假如右侧操作数的值为x或z, 移位操作的成果为x。假定:
reg [0:7] Qreg;
. . .
Qreg = 4’b0111;
那么:
Qreg >> 2 是 8’b0000_0001
Verilog HDL中没有指数操作符。可是,移位操作符可用于支撑部分指数操作。例如,假如要核算ZNumBits的值,能够运用移位操作完成,例如:
32’b1 NumBits //NumBits有必要小于32。
同理,可运用移位操作为2-4解码器建模,如
wire [0:3] DecodeOut = 4’b1 Address [0:1];
Address[0:1] 可取值0,1,2和3。与之相应,DecodeOut能够取值4’b0001、4’b0010、4’b0100和4’b1000,从而为解码器建模。
2.8 条件操作符
条件操作符依据条件表达式的值挑选表达式,方式如下:
cond_expr ? expr1 : expr2
假如cond_expr 为真(即值为1),挑选expr1;假如cond_expr为假(值为0),挑选expr2。 假如cond_expr 为x或z,成果将是按以下逻辑expr1和expr2按位操作的值: 0与0得0,1与1得1,其他状况为x。
如下所示:
wire [0:2] Student = Marks > 18 ? Grade_A : Grade_C;
核算表达式Marks > 18; 假如真, Grade_A 赋值为Student; 假如Marks =18, Grade_C 赋值为Student。下面为另一实例:
always
#5 Ctr = (Ctr != 25) ? (Ctr + 1) : 5;
进程赋值中的表达式标明假如Ctr不等于25, 则加1;不然假如Ctr值为25时, 将Ctr值从头置为5。
2.9 衔接和仿制操作
衔接操作是将小表达式兼并形成大表达式的操作。方式如下:
{expr1, expr2, . . .,exprN}
实例如下所示:
wire [7:0] Dbus;
wire [11:0] Abus;
assign Dbus [7:4] = {Dbus [0], Dbus [1], Dbus[2], Dbus[3]};
//以回转的次序将低端4位赋给高端4位。
assign Dbus = {Dbus [3:0], Dbus [7:4]};
//高4位与低4位交流。
因为非定长常数的长度不知道, 不允许衔接非定长常数。例如, 下列式子不合法:
{Dbus,5} //不允许衔接操作非定长常数。
仿制经过指定重复次数来履行操作。方式如下:
{repetition_number {expr1, expr2, …,exprN}}
以下是一些实例:
Abus = {3{4’b1011}}; //位向量12’b1011_1011_1011)
Abus = {{4{Dbus[7]}}, Dbus}; /*符号扩展*/
{3{1’b1}} 成果为111
{3{Ack}} 成果与{Ack, Ack, Ack}相同。
表达式品种
常量表达式是在编译时就核算出常数值的表达式。一般,常量表达式可由下列要素构成:
1) 标明常量文字, 如’b10和326。
2) 参数名,如RED的参数标明:
parameter RED = 4’b1110;
标量表达式是核算成果为1位的表达式。