Verilogからある従来の比較演算(==,!=)とSystemVerilogで新たに加わったExact Match(===, !===)とWildcard Match(==?, !=?)について動作の違いについて調べてみたのでメモ。
テストベンチ
module tb;
logic [3:0] aaa, bbb;
initial begin
$display( "Conventional Match");
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'bxxxx; $display( " (%b == %b) --> %b " , aaa, bbb, aaa == bbb );
#10 aaa = '1; bbb = 'bxxxx; $display( " (%b == %b) --> %b " , aaa, bbb, aaa == bbb );
#10 aaa = 'x; bbb = 'bxxxx; $display( " (%b == %b) --> %b " , aaa, bbb, aaa == bbb );
#10 aaa = 'z; bbb = 'bxxxx; $display( " (%b == %b) --> %b " , aaa, bbb, aaa == bbb );
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'b00xx; $display( " (%b == %b) --> %b " , aaa, bbb, aaa == bbb );
#10 aaa = '1; bbb = 'b00xx; $display( " (%b == %b) --> %b " , aaa, bbb, aaa == bbb );
#10 aaa = 'x; bbb = 'b00xx; $display( " (%b == %b) --> %b " , aaa, bbb, aaa == bbb );
#10 aaa = 'z; bbb = 'b00xx; $display( " (%b == %b) --> %b " , aaa, bbb, aaa == bbb );
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'bxxxx; $display( " (%b != %b) --> %b " , aaa, bbb, aaa != bbb );
#10 aaa = '1; bbb = 'bxxxx; $display( " (%b != %b) --> %b " , aaa, bbb, aaa != bbb );
#10 aaa = 'x; bbb = 'bxxxx; $display( " (%b != %b) --> %b " , aaa, bbb, aaa != bbb );
#10 aaa = 'z; bbb = 'bxxxx; $display( " (%b != %b) --> %b " , aaa, bbb, aaa != bbb );
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'b00xx; $display( " (%b != %b) --> %b " , aaa, bbb, aaa != bbb );
#10 aaa = '1; bbb = 'b00xx; $display( " (%b != %b) --> %b " , aaa, bbb, aaa != bbb );
#10 aaa = 'x; bbb = 'b00xx; $display( " (%b != %b) --> %b " , aaa, bbb, aaa != bbb );
#10 aaa = 'z; bbb = 'b00xx; $display( " (%b != %b) --> %b " , aaa, bbb, aaa != bbb );
$display( " ----------------------------- ");
$display( " ");
$display( "Exact Match");
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'bxxxx; $display( " (%b === %b) --> %b " , aaa, bbb, aaa === bbb );
#10 aaa = '1; bbb = 'bxxxx; $display( " (%b === %b) --> %b " , aaa, bbb, aaa === bbb );
#10 aaa = 'x; bbb = 'bxxxx; $display( " (%b === %b) --> %b " , aaa, bbb, aaa === bbb );
#10 aaa = 'z; bbb = 'bxxxx; $display( " (%b === %b) --> %b " , aaa, bbb, aaa === bbb );
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'b00xx; $display( " (%b === %b) --> %b " , aaa, bbb, aaa === bbb );
#10 aaa = '1; bbb = 'b00xx; $display( " (%b === %b) --> %b " , aaa, bbb, aaa === bbb );
#10 aaa = 'x; bbb = 'b00xx; $display( " (%b === %b) --> %b " , aaa, bbb, aaa === bbb );
#10 aaa = 'z; bbb = 'b00xx; $display( " (%b === %b) --> %b " , aaa, bbb, aaa === bbb );
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'bxxxx; $display( " (%b !== %b) --> %b " , aaa, bbb, aaa !== bbb );
#10 aaa = '1; bbb = 'bxxxx; $display( " (%b !== %b) --> %b " , aaa, bbb, aaa !== bbb );
#10 aaa = 'x; bbb = 'bxxxx; $display( " (%b !== %b) --> %b " , aaa, bbb, aaa !== bbb );
#10 aaa = 'z; bbb = 'bxxxx; $display( " (%b !== %b) --> %b " , aaa, bbb, aaa !== bbb );
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'b00xx; $display( " (%b !== %b) --> %b " , aaa, bbb, aaa !== bbb );
#10 aaa = '1; bbb = 'b00xx; $display( " (%b !== %b) --> %b " , aaa, bbb, aaa !== bbb );
#10 aaa = 'x; bbb = 'b00xx; $display( " (%b !== %b) --> %b " , aaa, bbb, aaa !== bbb );
#10 aaa = 'z; bbb = 'b00xx; $display( " (%b !== %b) --> %b " , aaa, bbb, aaa !== bbb );
$display( " ----------------------------- ");
$display( " ");
$display( "Wildcard Match");
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'bxxxx; $display( " (%b ==? %b) --> %b " , aaa, bbb, aaa ==? bbb );
#10 aaa = '1; bbb = 'bxxxx; $display( " (%b ==? %b) --> %b " , aaa, bbb, aaa ==? bbb );
#10 aaa = 'x; bbb = 'bxxxx; $display( " (%b ==? %b) --> %b " , aaa, bbb, aaa ==? bbb );
#10 aaa = 'z; bbb = 'bxxxx; $display( " (%b ==? %b) --> %b " , aaa, bbb, aaa ==? bbb );
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'b00xx; $display( " (%b ==? %b) --> %b " , aaa, bbb, aaa ==? bbb );
#10 aaa = '1; bbb = 'b00xx; $display( " (%b ==? %b) --> %b " , aaa, bbb, aaa ==? bbb );
#10 aaa = 'x; bbb = 'b00xx; $display( " (%b ==? %b) --> %b " , aaa, bbb, aaa ==? bbb );
#10 aaa = 'z; bbb = 'b00xx; $display( " (%b ==? %b) --> %b " , aaa, bbb, aaa ==? bbb );
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'bxxxx; $display( " (%b !=? %b) --> %b " , aaa, bbb, aaa !=? bbb );
#10 aaa = '1; bbb = 'bxxxx; $display( " (%b !=? %b) --> %b " , aaa, bbb, aaa !=? bbb );
#10 aaa = 'x; bbb = 'bxxxx; $display( " (%b !=? %b) --> %b " , aaa, bbb, aaa !=? bbb );
#10 aaa = 'z; bbb = 'bxxxx; $display( " (%b !=? %b) --> %b " , aaa, bbb, aaa !=? bbb );
$display( " ----------------------------- ");
#10 aaa = '0; bbb = 'b00xx; $display( " (%b !=? %b) --> %b " , aaa, bbb, aaa !=? bbb );
#10 aaa = '1; bbb = 'b00xx; $display( " (%b !=? %b) --> %b " , aaa, bbb, aaa !=? bbb );
#10 aaa = 'x; bbb = 'b00xx; $display( " (%b !=? %b) --> %b " , aaa, bbb, aaa !=? bbb );
#10 aaa = 'z; bbb = 'b00xx; $display( " (%b !=? %b) --> %b " , aaa, bbb, aaa !=? bbb );
$display( " ----------------------------- ");
$finish();
end
endmodule
結果
Conventional Match
-----------------------------
(0000 == xxxx) --> x
(1111 == xxxx) --> x
(xxxx == xxxx) --> x
(zzzz == xxxx) --> x
-----------------------------
(0000 == 00xx) --> x
(1111 == 00xx) --> 0
(xxxx == 00xx) --> x
(zzzz == 00xx) --> x
-----------------------------
(0000 != xxxx) --> x
(1111 != xxxx) --> x
(xxxx != xxxx) --> x
(zzzz != xxxx) --> x
-----------------------------
(0000 != 00xx) --> x
(1111 != 00xx) --> 1
(xxxx != 00xx) --> x
(zzzz != 00xx) --> x
-----------------------------
Exact Match
-----------------------------
(0000 === xxxx) --> 0
(1111 === xxxx) --> 0
(xxxx === xxxx) --> 1
(zzzz === xxxx) --> 0
-----------------------------
(0000 === 00xx) --> 0
(1111 === 00xx) --> 0
(xxxx === 00xx) --> 0
(zzzz === 00xx) --> 0
-----------------------------
(0000 !== xxxx) --> 1
(1111 !== xxxx) --> 1
(xxxx !== xxxx) --> 0
(zzzz !== xxxx) --> 1
-----------------------------
(0000 !== 00xx) --> 1
(1111 !== 00xx) --> 1
(xxxx !== 00xx) --> 1
(zzzz !== 00xx) --> 1
-----------------------------
Wildcard Match
-----------------------------
(0000 ==? xxxx) --> 1
(1111 ==? xxxx) --> 1
(xxxx ==? xxxx) --> 1
(zzzz ==? xxxx) --> 1
-----------------------------
(0000 ==? 00xx) --> 1
(1111 ==? 00xx) --> 0
(xxxx ==? 00xx) --> x
(zzzz ==? 00xx) --> x
-----------------------------
(0000 !=? xxxx) --> 0
(1111 !=? xxxx) --> 0
(xxxx !=? xxxx) --> 0
(zzzz !=? xxxx) --> 0
-----------------------------
(0000 !=? 00xx) --> 0
(1111 !=? 00xx) --> 1
(xxxx !=? 00xx) --> x
(zzzz !=? 00xx) --> x
-----------------------------
まとめ
-
従来の比較演算(==,!=)
左右のどちらかの比較ビットにxが含まれると比較結果を判断できず結果はx。
ただし一部ビットがxでなく確実に不一致を判定できれば==では0,!=では1。
逆に一部ビットが一致のみでは確実に一致/不一致を判断できないので==と!=の両方ともx。 -
Exact Match(===,!==)
x,zを含めてぴったり一致/不一致を判定。xとzは別物。
結果は0か1のみでxはない。 -
Wildcard Match(==?,!=?)
右辺と左辺でxの意味が違う。右辺はWildcard。
!=?は不一致を検出なので右辺が全部xだと結果は0。
Exact Matchではないので結果がxになりうる。
右辺のwildcardビットでない位置の左辺のビット位置にx,zが入ると結果はx。
使用シミュレータ
Icarus Verilog version 11.0 (stable) (v11_0-132-gb2f2414f4)