1. 四值邏輯的邏輯運算
在對比SystemVerilog中的相等運算符之前,先來看一下三種最基本的邏輯運算符,下文中以·表示與運算,以+表示或運算,以'表示非運算。我們都知道在邏輯代數中,只有0和1,那么在SystemVerilog中,對於四值邏輯(0、1、z、x)的邏輯運算結果又會怎樣呢?
logic v[4] = '{1'b0, 1'b1, 1'bz, 1'bx};
initial begin
foreach(v[i])
foreach(v[j])
$display("%b & %b : %b", v[i], v[j], v[i] & v[j]);
end
我們通過簡單的代碼就可以打印出四值邏輯運算的真值表:
| 與運算(A·B) | 0 | 1 | z | x |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 1 | 0 | 1 | x | x |
| z | 0 | x | x | x |
| x | 0 | x | x | x |
| 或運算(A+B) | 0 | 1 | z | x |
|---|---|---|---|---|
| 0 | 0 | 1 | x | x |
| 1 | 1 | 1 | 1 | 1 |
| z | x | 1 | x | x |
| x | x | 1 | x | x |
| 非運算 | 0 | 1 | z | x |
|---|---|---|---|---|
| 輸出(A') | 1 | 0 | x | x |
由輸出結果可知,四值邏輯運算的結果只有0、1和x,並且與常量0和1運算時,仍然滿足邏輯代數的基本公式:0 · A = 0、1 · A = A、0 + A = A、1 + A = 1;以及滿足公式:A · A = A、A + A = A。
只不過輸出結果不包含z,z參與運算時,同x相同,如:1 · z = x、0 + z = x、z · x = x、z + x = x。
2. 相等運算符

依然打印出所有的輸出結果,如下所示:
| == | 0 | 1 | z | x |
|---|---|---|---|---|
| 0 | 1 | 0 | x | x |
| 1 | 0 | 1 | x | x |
| z | x | x | x | x |
| x | x | x | x | x |
| != | 0 | 1 | z | x |
|---|---|---|---|---|
| 0 | 0 | 1 | x | x |
| 1 | 1 | 0 | x | x |
| z | x | x | x | x |
| x | x | x | x | x |
| === | 0 | 1 | z | x |
|---|---|---|---|---|
| 0 | 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 0 | 0 |
| z | 0 | 0 | 1 | 0 |
| x | 0 | 0 | 0 | 1 |
| !== | 0 | 1 | z | x |
|---|---|---|---|---|
| 0 | 0 | 1 | 1 | 1 |
| 1 | 1 | 0 | 1 | 1 |
| z | 1 | 1 | 0 | 1 |
| x | 1 | 1 | 1 | 0 |
可以看到,===和!==的結果只有0和1,而==和!=的結果有0、1和x。以上結果都是針對單比特值的比較運算,那么對於多比特數據的相等比較運算,結果如何呢?
initial begin
$display("%b == %b : %b", 4'b1010, 4'b1011, 4'b1010 == 4'b1011); // 0
$display("%b != %b : %b", 4'b1010, 4'b1011, 4'b1010 != 4'b1011); // 1
$display("%b == %b : %b", 4'b1010, 4'b10x0, 4'b1010 == 4'b10x0); // x
$display("%b == %b : %b", 4'b1010, 4'b10x1, 4'b1010 == 4'b10x1); // 0
$display("%b != %b : %b", 4'b1010, 4'b10x0, 4'b1010 != 4'b10x0); // x
$display("%b != %b : %b", 4'b1010, 4'b10x1, 4'b1010 != 4'b10x1); // 1
$display("%b == %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 == 4'b1x10); // x
$display("%b == %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 == 4'b1x10); // x
$display("%b != %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 != 4'b1x10); // x
$display("%b != %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 != 4'b1x10); // x
$display("-----------------------------------------------------");
$display("%b === %b : %b", 4'b1010, 4'b1011, 4'b1010 === 4'b1011); // 0
$display("%b !== %b : %b", 4'b1010, 4'b1011, 4'b1010 !== 4'b1011); // 1
$display("%b === %b : %b", 4'b1010, 4'b10x0, 4'b1010 === 4'b10x0); // 0
$display("%b === %b : %b", 4'b1010, 4'b10x1, 4'b1010 === 4'b10x1); // 0
$display("%b !== %b : %b", 4'b1010, 4'b10x0, 4'b1010 !== 4'b10x0); // 1
$display("%b !== %b : %b", 4'b1010, 4'b10x1, 4'b1010 !== 4'b10x1); // 1
$display("%b === %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 === 4'b1x10); // 1
$display("%b === %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 === 4'b1x10); // 0
$display("%b !== %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 !== 4'b1x10); // 0
$display("%b !== %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 !== 4'b1x10); // 1
end
對於===和!==的輸出結果比較容易理解,只有0和1嘛;而對於==和!=的部分輸出結果,是否有些困惑呢?比如對比這幾個輸出:
# 1010 == 10x0 : x
# 1010 == 10x1 : 0
# 1x10 == 1x10 : x
不要被這些結果所迷惑,實際上,這四個相等運算符的規則很簡單,都是逐位比較操作數(bit for bit)。對於相等比較,對逐位比較的結果再進行與運算;而對於不相等比較,對逐位比較的結果再進行或運算。比如4'b1010 == 4'b10x0,則等價於(1'b1 == 1'b1) & (1'b0 == 1'b0) & (1'b1 == 1'bx) & (1'b0 == 1'b0),即1'b1 & 1'b1 & 1'bx & 1'b1,所以結果為1'bx;而對於4'b1010 === 4'b10x0,則等價於(1'b1 === 1'b1) & (1'b0 === 1'b0) & (1'b1 === 1'bx) & (1'b0 === 1'b0),即1'b1 & 1'b1 & 1'b0 & 1'b1,所以結果為1'b0;再比如4'b1010 != 4'b10x1,則等價於(1'b1 != 1'b1) | (1'b0 != 1'b0) | (1'b1 != 1'bx) | (1'b0 != 1'b1),即1'b0 | 1'b0 | 1'bx | 1'b1,所以結果為1'b1。
3. 關於數據的邏輯值
首先,上文中所涉及到的與或非運算,我所使用的都是按位與(&)、按位或(|)、按位非(~),因為對於單比特數據的運算,實際上其與邏輯與(&&)、邏輯或(||)、邏輯非(!)的運算結果相同,如1'b1 & 1'bx和1'b1 && 1'bx的結果都是1'bx。那么對於多比特的數據,其邏輯值怎么判斷呢?也就是說,比如代碼中有if (4'b10x0) begin "something" end,那something會不會運行呢,即4'b10x0的邏輯值是真是假呢?我這里使用兩個邏輯非(!)來得到邏輯值:!(!4'b10x0)。
initial begin
$display("4'b%b : %b", 4'b0000, !(!4'b0000)); // 0
$display("4'b%b : %b", 4'b1010, !(!4'b1010)); // 1
$display("4'b%b : %b", 4'b1x10, !(!4'b1x10)); // 1
$display("4'b%b : %b", 4'b1z10, !(!4'b1z10)); // 1
$display("4'b%b : %b", 4'bxxxx, !(!4'bxxxx)); // x
$display("4'b%b : %b", 4'bzzzz, !(!4'bzzzz)); // x
$display("4'b%b : %b", 4'bxx00, !(!4'bxx00)); // x
$display("4'b%b : %b", 4'bz0z0, !(!4'bz0z0)); // x
end
實際上,就是對數據的所有位進行或運算,就得到了該數據的邏輯值,所以if (4'b10x0) begin "something" end會執行something。這一部分,主要是想說明,對於四值數據,無論是與或非邏輯運算,還是==和!=相等比較運算,結果都可能出現x,且! 1'bx結果還是1'bx,所以下面三種寫法,if條件都不成立,最終都只會執行Do ELSE。即,當使用==和!=比較四值數據時,結果可能會得到x,並隨之出現我們預期之外的效果,這是我們不希望的,所以在驗證代碼中比較四值數據時,要使用===和!==。
initial begin
if ( 4'b1010 == 4'b10x0 )
$display("Do IF");
else
$display("Do ELSE");
if ( 4'b1010 != 4'b10x0 )
$display("Do IF");
else
$display("Do ELSE");
if ( !(4'b1010 == 4'b10x0) )
$display("Do IF");
else
$display("Do ELSE");
end
