そのため、何日も私を悩ませていたバグは、Falseと評価されてTrueと評価されるべきだったコードのセクションだったのです。私の最初のコードは次のようなものでした:
if(~x && ~y) begin //do stuff end
つまり、xが1ではなく、yが1でない場合は、何かを行います。デバッガーをステップ実行すると、xが1であっても、ifステートメントの式がまだTRUEになり、後続のコードが実行されていることに気付きました。
ただし、ステートメントを次のように変更した場合:
if(x == 0 && y == 0) begin
//do stuff
end
そしてまた試しました:
if(!x && !y) begin
//do stuff
end
if-statement内のコードは評価されませんでしたが、これは予想される動作でした。 〜はビット単位の否定であり、!論理否定ですが、(〜x &&〜y)と(!x &&!y)は同じものに評価すべきではありませんか?コードベースが大きすぎるため、ここに貼り付けることはできませんが、意図したとおりにコードを機能させるために行った唯一の変更でした。ありがとう。
以下のコメントの1つに応えて、この動作をテストするためのテストケースを作成しました。
`タイムスケール10ns/1ns
モジュールtest_negation();
integer x, y; initial begin x = 1; y = 0; if(~x && ~y) begin $display("%s", "First case executed"); end if(!x && !y) begin $display("%s", "Second case executed"); end if(x == 0 && y == 0) begin $display("%s", "Third case executed"); end end endmodule
そして奇妙なことに、私が観察した元の動作を確認するために、「最初のケースが実行されました」が出力されます。
_!
_記号は、ブールまたは論理否定を表します。ゼロ以外のx
の値の場合、_!x
_はゼロまたはfalseと評価され、x
がゼロの場合、_!x
_は1またはtrueと評価されます。
_~
_記号はビット単位の否定を表します。値の各ビットはトグルされるため、16ビットの_x == 0xA5A5
_の場合、_~x
_は_0x5A5A
_と評価されます。
if()
条件式は、trueまたはfalseに評価される式を期待します。0以外(正または負)はtrue、0はfalseです。
_&&
_は論理ANDです。 2つの式が必要で、両方の式がtrueの場合にのみ、1つまたはtrueに評価されます。繰り返しますが、ここで「真」とは、ゼロ以外、正または負を意味します。
これらすべてが与えられると、_~x
_と_!x
_が同じ値に評価されるのは、_x == -1
_のときか、x
が署名されていない場合は_x == MAX_UNSIGNED
_。
そうですか。上記のコードの変数「x」は、Verilog整数(integer x;
)。ただし、整数変数は、Verilogでは32ビット整数として表されます。したがって、xが「1」であったとしても、〜xは「0」ではなく「11111111111111111111111111111110」になります。したがって、First Caseが実行されたのは当然のことです。私のせい。すべての回答をありがとう。
~
はビット単位の演算子であり、引数の反転を返します。
!
は論理演算子であり、単一ビットを返します。
例:
reg [7:0] bit_wise, logic_op;
initial begin
bit_wise = ~8'hA1; // bit_wise == 8'h6E
logic_op = !8'hA1; // logic_op == 8'b00
$display("bit_wise:%h logic_op:%h", bit_wise, logic_op); // bit_wise:5e logic_op:00
end
あなたの例のために:
if(~x && ~y) begin
//do stuff
end
実質的に同じです:
if(x!='1 && y!='1) begin // '1 means the with of x all 1s and the with of y all 1s
//do stuff
end
一般的に、最良のコーディングスタイルは、ifステートメント内で論理演算子を使用することです。データ割り当て操作ではビット単位の演算子のみを使用してください。