Verilog 操作運算符
算術運算符
+,-,*,/,**(加/減/乘/除/冪運算),乘法運算的結果的位寬是乘數和被乘數位寬的和。
在進行整數的除法運算時,結果要略去小數部分,只取整數部分;而進行取模運算時(%,亦稱作求余運算符)結果的符號位采用模運算符中第一個操作數的符號。
-10%3 =-1 11%-3 結果為2
注意:在進行算術運算時,如果某一個操作數有不確定的值x,則整個結果也為不確定值x。下面的代碼演示了算術運算符的操作,其結果為:
如果不指定reg signed類型,負數的運算會被當作無符號數運算,從而得到錯誤的結果。
Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11; Dec 28 09:33 2018
32 + 15 = 47
32 - 15 = 17
15 - 32 = -17
32 * 15 = 480
32 * -32 = -1024
32 / 15 = 2
-32 mod 15 = -2
32 mod -3 = 2
3 ** 2 = 9
32 + 15 = 47
32 - 15 = 17
15 - 32 = 4294967279
32 * 15 = 480
32 * 4294967264 = 4294966272
32 / 15 = 2
4294967264 mod 15 = 14
32 mod 4294967293 = 32
3 ** 2 = 9
V C S S i m u l a t i o n R e p o r t
`timescale 1ns/1ns module operator; reg signed [31:0] a = 32; reg signed [31:0] b = 15; reg signed [31:0] c = -32; reg signed [31:0] d = -3; reg signed [31:0] e = 3; reg signed [31:0] f = 2; reg signed [31:0] r = 1; reg [31:0] a1 = 32; reg [31:0] b1 = 15; reg [31:0] c1 = -32; reg [31:0] d1 = -3; reg [31:0] e1 = 3; reg [31:0] f1 = 2; reg [31:0] r1 = 1; initial begin r = a + b; $display("%d + %d = %d",a, b, r); r = a - b; $display("%d - %d = %d",a, b, r); r = b - a; $display("%d - %d = %d",b, a, r); r = a * b; $display("%d * %d = %d",a, b, r); r = a * c; $display("%d * %d = %d",a, c, r); r = a / b; $display("%d / %d = %d",a, b, r); r = c % b; $display("%d mod %d = %d",c, b, r); r = a % d; $display("%d mod %d = %d",a, d, r); r = e ** f; $display("%d ** %d = %d",e, f, r); r1 = a1 + b1; $display("%d + %d = %d",a1, b1, r1); r1 = a1 - b1; $display("%d - %d = %d",a1, b1, r1); r1 = b1 - a1; $display("%d - %d = %d",b1, a1, r1); r1 = a1 * b1; $display("%d * %d = %d",a1, b1, r1); r1 = a1 * c1; $display("%d * %d = %d",a1, c1, r1); r1 = a1 / b1; $display("%d / %d = %d",a1, b1, r1); r1 = c1 % b1; $display("%d mod %d = %d",c1, b1, r1); r1 = a1 % d1; $display("%d mod %d = %d",a1, d1, r1); r1 = e1 ** f1; $display("%d ** %d = %d",e1, f1, r1); end endmodule
位運算符
按位取反~ 、按位與 & 、按位或 | 、按位異或 ^ 、按位同或 ^~(~^),在不同長度的數據進行位運算時,系統會自動的將兩個數右端對齊,位數少的操作數會在相應的高位補0。
下面位運算符的代碼例子:
Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11; Dec 28 10:00 2018
0101010110101010 & 11111111 = 0000000010101010
0101010110101010 | 11111111 = 0101010111111111
~0101010110101010 1010101001010101
0101010110101010 ^ 11111111 = 0101010101010101
0101010110101010 ~^ 11111111 = 1010101010101010
0101010110101010 ^~ 11111111 = 1010101010101010
V C S S i m u l a t i o n R e p o r t
`timescale 1ns/1ns module operator; reg [15:0] a = 16'b0101010110101010; reg [7:0] b = 8'hff; reg [15:0] r = 1; initial begin r = a & b; $display("%b & %b = %b",a, b, r); r = a | b; $display("%b | %b = %b",a, b, r); r = ~a ; $display("~%b %b", a, r); r = a ^ b; $display("%b ^ %b = %b",a, b, r); r = a ~^ b; $display("%b ~^ %b = %b",a, b, r); r = a ^~ b; $display("%b ^~ %b = %b",a, b, r); end endmodule
邏輯運算符
邏輯運算符用來連接條件表達式,它的返回值是1位的。邏輯運算符包括邏輯與 &&、邏輯或 ||、邏輯非 !,其中&&和||是雙目運算符,其優先級別低於關系運算符,而 !高於算術運算符。
關系運算符
< 、 > 、 <= 、 >= 如果關系運算是假的,則返回值是0,如果聲明的關系是真的,則返回值是1。 關系運算符的優先級別低於算數運算符。關系運算返回值也是1位的。
邏輯運算符,關系運算符,包括下面的等式運算符,通常都是用來作條件判斷的,比如if語句的判斷條件。
下面的代碼演示了這三種運算的結果:
Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11; Dec 28 12:42 2018
(0 && 1) = 0
(0 || 1) = 1
(!0) = 1
(00010100 >= 01011010) = 0
(00010100 < 01011010) = 1
(00010100 == 01011010) = 0
(0 == x) = x
(0 === x) = 0
$finish called from file "operator2.v", line 35.
`timescale 1ns/1ns module operator; reg a = 1'b0; reg b = 1'b1; reg r = 1'b1; reg [7:0] c = 8'd20; reg [7:0] d = 8'd90; initial begin r = (a && b); $display("(%b && %b) = %b",a, b, r); #10 r = (a || b); $display("(%b || %b) = %b",a, b, r); #10 r = !a; $display("(!%b) = %b",a, r); #10 r = (c>=d); $display("(%b >= %b) = %b",c, d, r); #10 r = (c<d); $display("(%b < %b) = %b",c, d, r); #10 r = (c==d); $display("(%b == %b) = %b",c, d, r); #10 r = (a==1'bx); $display("(%b == x) = %b",a, r); #10 r = (a===1'bx); $display("(%b === x) = %b",a, r); #10 $finish; end endmodule
等式運算符
== 、!= 、===、!== 符號之間不能有空格。
“==”和“!=”稱作邏輯等式運算符,其結果由兩個操作數的值決定。由於操作數可能是x或z,其結果可能為x;
“===”和“!==”常用於case表達式的判別,又稱作case等式運算符。其結果只為0和1,如果操作數中存在x和z,那么操作數必須完全相同結果才為1,否則為0。
邏輯等式運算符和case等式運算符的區別
=== |
0 |
1 |
x |
z |
== |
0 |
1 |
x |
z |
|
0 |
1 |
0 |
0 |
0 |
0 |
1 |
0 |
x |
x |
|
1 |
0 |
1 |
0 |
0 |
1 |
0 |
1 |
x |
x |
|
x |
0 |
0 |
1 |
0 |
x |
x |
x |
x |
x |
|
z |
0 |
0 |
0 |
1 |
z |
x |
x |
x |
x |
移位運算符
邏輯移位運算符:<< 、 >> , a>>n其中a代表要進行移位的操作數,n代表要移幾位。這兩種移位運算都用0來填補移出的空位。算術移位運算符:<<<, >>>, <<<右邊補0,>>>左邊補MSB(最高有效位,僅對有符號數),若MSB是x或z,則填x。
Compiler version M-2017.03-SP2-11; Runtime version M-2017.03-SP2-11; Dec 28 13:17 2018
(10101001011100000001001000110100>>1) = 01010100101110000000100100011010
(10101001011100000001001000110100>>1) = 01010010111000000010010001101000
(10101001011100000001001000110100>>>1) = 01010100101110000000100100011010
(10101001011100000001001000110100<<<1) = 01010010111000000010010001101000
(10101001011100000001001000110100>>>5) = 11111101010010111000000010010001
(10101001011100000001001000110100>>5) = 00000101010010111000000010010001
$finish called from file "operator3.v", line 26.
`timescale 1ns/1ns module operator; reg [31:0] a = 32'ha9701234; reg signed [31:0] b = 32'ha9701234; reg [31:0] r = 32'b1; initial begin r = (a >> 1); $display("(%b>>1) = %b",a, r); #10 r = (a << 1); $display("(%b>>1) = %b",a, r); #10 r = (a >>> 1); $display("(%b>>>1) = %b",a, r); #10 r = (a <<< 1); $display("(%b<<<1) = %b",a, r); #10 r = (b >>> 5); $display("(%b>>>5) = %b",b, r); #10 r = (b >> 5); $display("(%b>>5) = %b",b, r); $finish; end endmodule
位拼接運算符
{信號1的某幾位,信號2的某幾位,......信號n的某幾位} 將某些信號的某些位列出來,中間用逗號分開,最后用大括號括起來表示一個整體的信號。
在位拼接的表達式中不允許存在沒有指明位數的信號。
{a,b[3:0],w,3'b101} //等同於 {a,b[3],b[2],b[1],b[0],w,1b'1,1'b0,1'b1}
{4{w}} //等同於{w,w,w,w}
{b,{3{a,b}}} //等同於{b,a,b,a,b,a,b} 這里面的3、4必須是常量表達式。
縮減運算符
這是單目運算符,也包括與、或、非運算。運算規則與位運算相似,不過是對單個運算符的每一位逐步運算,最后的運算結果是一位的二進制數。
c=&B; //意思同c=((B[0]&B[1]) &B[2] ) & B[3];
條件運算符
A?B:C, 如果表達式A為true(1),則結果為B,如果為false(0)結果為C。若A結果為模糊值(X或Z),則B,C都被執行,則是2驅動源,按下表輸出結果,如果B,C不同,或者B,C中有x,z,則輸出x。
?: |
0 |
1 |
x |
z |
0 |
0 |
x |
x |
x |
1 |
x |
1 |
x |
x |
x |
x |
x |
x |
x |
z |
x |
x |
x |
x |
運算符的優先級
小括號優先級最高,在不清楚其它運算符優先級的情況下,可以加小括號來保證想要的表達式執行順序。條件運算符是從右向左關聯的,其它運算符都是從左向右關聯的。
Verilog中運算符優先級如下表
優先級 |
運算符 |
操作數 |
備注 |
高 |
+, -, !, ~,&,~&,|,~|,^,~^,^~ |
一元 |
b=-a,b=+a,b=!a,b=~a; 紅色的都是縮減運算符 |
** |
冪運算符 |
||
*, /, % |
|||
+ - |
二元 |
加減運算 |
|
<<, >> ,<<<, >>> |
|||
< , <=, > , >= |
|||
==, !=,===,!== |
|||
& |
二元 |
||
^, ^~, ~^ |
二元 |
異或和同或 |
|
| |
二元 |
||
&& |
|||
|| |
|||
低 |
?: |
條件運算 |