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;而算数右移时,左边高位会补充符号位,保证数据缩小后值的正确性