Verilog 表达式

表达式

由操作符和操作数构成,目的是根据操作符的意义得到1个计算结果。表达式可以出现在数值的任何方式使用。如:

a^b; //a b异或
address[9:0] + 10'b1; //地址累加
flag1 && flag2; //逻辑与操作

操作数

操作数可以是任意的数据类型,只是某些特定的语法结构要求使用特定类型的操作数。 操作数可以为常熟,整数,实数,线网,寄存器,时间,位选,域选,存储器及函数调用。

module test;
//实数
real a,b,c;
c = a+b;
//寄存器
reg [3:0] cprmu_1,cprmu_2;
always @(posedge clk) begin
	cprmu_2 = cprmu_1^cprmu_2;
end
//函数
reg flag1;
flag = calculate_result(A,B);
//非法操作数
reg [3:0] res;
wire [3:0] temp;
always@ (*) begin
	res = cprmu_2-cprmu_1;
	temp = cprmu_2-cprmu_1; //不合法,always里面赋值对象不能是`wire`型
end
endmodule

操作符

Verilog 提供了约9种操作符,分别是算术、关系、等价、逻辑、按位、归约、移位、拼接、条件操作符。 大部分操作符与C语言种类似:

算数操作符

包含单目和双目操作符,对2个操作数进行算数运算,包含乘、除、加、减、求幂(**)、取模(%)

reg [3:0] a,b;
reg [4:0] c;
a = 4'b1001;
b = 4'b1001;
c = a+b;
c = a/b;

如果操作数某一位为X,则计算结果会全部出现X

b = 4'b100x;
c = a+b; //c = 4'bxxxx

对变量进行声明时,要根据变量的操作符对变量的位宽进行合理的声明,不能让结果溢出

reg [3:0] mula;
reg [1:0] mulb;
reg [5:0] res;
mula = 4'he;
mulb = 2'h3;
res = mula*mulb;

+和-也可以作为单目运算符来使用,表示操作数的正负。此类操作符优先级最高。

-4;
+3;

负数表示时,可以直接在十进制数字前加一个-,也可以指定位宽。负数使用2进制补码来表示,不指定位宽表示负数时,编译器在转换时,会自动分配位宽,从而导致意想不到的结果,如:

mula = -4'd4;
mulb = 2;
res = mula*mulb;
res = mula*(-'d4);//Error!!!

这里的'd4没有指定位宽,则默认是32bit的无符号数,前面的-只是给1给无符号数取反罢了,所以结果出错。

关系运算符

结果为1或0,若是操作数种出现了x或者Z则关系表达式的结果是x

A = 4;
B = 3;
X = 3'b1xx;
A>B
A<=B
A>=Z //x

等价运算符

等价操作符包括(==),(!=),(===),(!===),分别表示逻辑全等,逻辑不等,全等,非全等。 逻辑相等/不等操作符不能比较x或z,当1个操作数包含1个x或z,则结果为不确定值。 全等比较时,若按位比较有相同的x或者z,返回结果也可以为1,所以全等比较的结果不一定包含x.

A = 4;
B = 8'h04;
C = 4'bxxxx;
D = 4'hx;
A == B;
A == (B+1);
A === C;
C === D;

逻辑操作符

逻辑操作符主要有3个:&&、||、! 结果是1``0``x

A = 3;
B = 0;
C = 2'b1x;

A&&B;
A||B;
!A;
!B;
A&&C;
A||C;
(A==2)&&(!B)

按位操作符

按位操作符包括:~、&、|、^、~^ 对于2个操作数的每1位进行操作,若是2个操作数位宽不相等,则用0向左拓展补充较短的操作数。 取反操作符对于操作数的每1位进行取反:

A = 4'b0101;
B = 4'b1001;
C = 4'bx010;

~A;
A & B;
A | B;
A^B;
A ~^B;
B|C;
B&C;

归约操作符

归约与&、归约或|、归约与非~&、归约或非~|、归约异或^、归约同或~^ 只有1个操作数,对这个操作数逐位进行操作,最终产生1个1bit结果。

A = 4'b1010;
&A;
~|A;
^A;

移位运算符

<<、>>、<<<、>>>。 移位操作符是双目操作符,2个操作数分别表示要进行移位的向量信号与移动的位数。 算数左移和逻辑左移时,右边低位会补0. 逻辑右移时,左边高位会补0;而算数右移时,左边高位会补充符号位,保证数据缩小后值的正确性