В чем разница между Verilog! и ~?

Итак, это закончилось тем, что ошибка, которая удерживала меня в течение нескольких дней, была частью кода, который должен был быть оценен как False, оценивая True. Мой исходный код выглядел примерно так:

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

то есть. Если x НЕ ОДИН, а y НЕ ОДИН, тогда делайте что-нибудь. Пройдя через отладчик, я понял, что хотя x равно 1, выражение в if-statement все еще приводило к TRUE, и последующий код выполнялся.

Однако, когда я сменил оператор на:

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

а также попытался:

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

код внутри оператора if не был оценен, что было ожидаемым поведением. Я понимаю, что ~ - поразрядное отрицание и! логическое отрицание, но не должно (~ x & ~ y) и (! x & &! y) оценивать одно и то же? Я боюсь, что кодовая база слишком велика, поэтому я не могу вставить ее здесь, но это было единственное изменение, которое я сделал, чтобы заставить код работать так, как я предполагал. Спасибо.


В ответ на один из комментариев ниже я создал тестовый пример для проверки этого поведения:

`timescale 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

И как ни странно, "первый случай выполнен" печатается, чтобы подтвердить первоначальное поведение, которое я наблюдал.

Ответ 1

Символ ! представляет логическое или логическое отрицание. Для любого значения x, отличного от нуля, !x оценивается как ноль или ложь, а когда x равно нулю, !x оценивается как один или истинный.

Символ ~ представляет побитовое отрицание. Каждый бит в значении переключается, поэтому для 16-разрядного x == 0xA5A5, ~x будет оцениваться до 0x5A5A.

Условие if() ожидает выражения, которое вычисляется как true или false, где любое ненулевое (положительное или отрицательное) значение true, а ноль - false.

&& является логическим И. Он принимает два выражения, оценивая один или истинный, если и только если оба выражения истинны. Опять же, "истина" здесь означает ненулевой, положительный или отрицательный.

Учитывая все это, мы можем видеть, что единственное время ~x и !x оценивается с тем же значением, когда x == -1 или, если x без знака, когда x == MAX_UNSIGNED.

Ответ 2

Я вижу. Переменная "x" в приведенном выше коде была целым числом Verilog (integer x;). Однако целочисленная переменная представлена ​​Verilog как 32-разрядное целое число. Поэтому, хотя x был "1", как я заметил, ~ x не приведет к "0", а в "11111111111111111111111111111110"! И поэтому неудивительно, что первый случай был выполнен. Моя вина. Спасибо за все ответы.

Ответ 3

~ - бит-мудрый оператор и возвращает инвертирование аргумента.

! является логическим оператором и возвращает один бит.

Пример:

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. Используйте только битовые операторы с манипуляциями с присваиванием данных.