What is the difference between Verilog ! and ~?

2019-01-25 07:50发布

问题:

So it ended up that the bug that had kept me on for days, was a section of code that should have evaluated to False evaluating to True. My initial code went something like:

if(~x && ~y) begin
    //do stuff
end

i.e. If x is NOT ONE and y is NOT ONE then do stuff. Stepping through the debugger, I realized even though x was 1 the expression in the if-statement still resulted into TRUE and the subsequent code was executed.

However, when I changed the statement to:

if(x == 0 && y == 0) begin
//do stuff
end

and also tried:

if(!x && !y) begin
//do stuff
end 

the code within the if-statement was not evaluated which was the expected behaviour. I understand that ~ is a bitwise negation and ! a logical negation, but shouldn't (~x && ~y) and (!x && !y) evaluate to the same thing? I'm afraid the codebase is too large, so I can't paste it here, but this was the only alteration I made to make the code to work as I intended. Thanks.


In response, to one of the comments below, I have created a test-case to test this behaviour:

`timescale 10ns/1ns

module 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

And strangely enough, "First case executed" is printed to confirm the original behaviour I observed.

回答1:

The ! symbol represents boolean or logical negation. For any value of x other than zero, !x evaluates to zero or false, and when x is zero, !x evaluates to one, or true.

The ~ symbol represents bitwise negation. Each bit in the value is toggled, so for a 16-bit x == 0xA5A5, ~x would evaluate to 0x5A5A.

The if() conditional expects an expression that evaluates to true or false, where anything nonzero (positive or negative) is true, and zero is false.

The && is a logical AND. It takes two expressions, evaluating to one or true if and only if both of the expressions are true. Again, "true" here means nonzero, positive or negative.

Given all this, we can see that the only time ~x and !x evaluate to the same value is when x == -1, or, if x is unsigned, when x == MAX_UNSIGNED.



回答2:

I see. The variable "x" in the above code was a Verilog integer (integer x;). However, an integer variable is represented by Verilog as a 32-bit integer number. So even though x was "1" as I had observed, ~x will not result in "0" but in "11111111111111111111111111111110"! And so it's no surprise that the First Case was executed. My fault. Thanks for all the answers.



回答3:

~ is a bit-wise operator and returns the invert of the argument.

! is a logical operator and returns a single bit.

Example:

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

For your example:

if(~x && ~y) begin
    //do stuff
end

Is effectively the same as:

if(x!='1 && y!='1) begin // '1 means the with of x all 1s and the with of y all 1s
    //do stuff
end

Generally the best coding style is to use logical operators inside if statements. Only use bit-wise operators with data assignment manipulations.