2013-05-07 28 views
10

Tak więc skończyło się, że błąd, który utrzymywał mnie przez kilka dni, był fragmentem kodu, który powinien być oceniony jako Fałszywy, gdy oceniany jest jako Prawdziwy. Mój początkowy kod poszedł coś takiego:Jaka jest różnica między Verilog! i ~?

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

tj Jeśli x nie jest jeden, a Y nie jest jednym następnie zrobić rzeczy. Przechodząc przez debugger, zdałem sobie sprawę, mimo że x było 1, wyrażenie w instrukcji if nadal miało wartość TRUE, a kolejny kod został wykonany.

Jednak, kiedy zmienił oświadczenie:

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

a także próbowałem:

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

kod w if-oświadczenie nie zostało ocenione, co było oczekiwane zachowanie. Rozumiem, że ~ to bitowa negacja i! logiczna negacja, ale nie powinna (~ x& ~ y) i (! x & &! y) ocenić na to samo? Obawiam się, że baza kodów jest zbyt duża, więc nie mogę jej tutaj wkleić, ale była to jedyna zmiana, którą wprowadziłem, aby kod zadziałał zgodnie z zamierzeniami. Dzięki.


W odpowiedzi na jeden z poniższych uwag, jakie stworzył przypadek testowy, aby przetestować ten problem:

`10ns skali czasowej/1ns

moduł 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 

I o dziwo, „Pierwszy przypadek stracony” jest drukowany w celu potwierdzenia oryginalne zachowanie zaobserwowałem.

+0

zgadywanie, ale nie bitowa negacja byłaby podobna do '~ 0xAA = 0x55', v.s. '! 0xAA' będący odpowiednikiem" 0xAA nie jest równe zeru, więc sprawdź na true ". –

+0

@Marc B Tak, to ważna różnica. Jednak w tym przypadku zarówno x, jak i y są 1 bitowe. Jeśli x jest "1", spodziewałbym się, że bitowa negacja ~ x będzie "0" .. – iab

+0

Jeden trochę długo? Jakie dziwne. Czy możesz stworzyć projekt testowy wyświetlający wartości 'x','! X', '~ x',' y', '! Y',' ~ y' i '(~ x && ~ y)' oraz '(! x &&! y)'? –

Odpowiedz

13

Symbol ! oznacza negację logiczną lub logiczną. Dla dowolnej wartości wynoszącej x innej niż zero, !x jest wartością zerową lub fałszem, a gdy x ma wartość zero, !x ma wartość "jeden" lub "prawda".

Symbol ~ reprezentuje negację bitową. Każdy bit w wartości jest przełączany, więc dla 16-bitowego x == 0xA5A5, ~x zostanie oceniony na 0x5A5A.

Warunek warunkowy oczekuje wyrażenia, które zwraca wartość prawda lub fałsz, gdzie wszystko niezerowe (dodatnie lub ujemne) jest prawdziwe, a zero jest fałszywe.

Numer && jest logicznym AND. Wymaga dwóch wyrażeń, oceniających jeden lub prawdziwy, wtedy i tylko wtedy, gdy oba wyrażenia są prawdziwe. Ponownie, "prawda" oznacza tutaj niezerową, pozytywną lub negatywną.

Biorąc pod uwagę to wszystko, widzimy, że tylko czas ~x i !x ocenić na tę samą wartość, gdy jest x == -1, lub, jeśli x jest niepodpisany, gdy x == MAX_UNSIGNED.

+0

Dodałem projekt testowy do oryginalnego wpisu. To samo zachowanie obserwuje się! – iab

+0

Ile bitów jest domyślną liczbą całkowitą? ~ 1 == 0xFFFE i ~ 0 == 0xFFFF, więc ten przykład ma sens. –

+1

Jest to niestety znacznie bardziej skomplikowane (widzę, że ktoś właśnie kliknął odpowiedź). Wyjaśnienie "!" Jest niepoprawne - wynik to 3-stan ('1',' 0', 'x'), a'! X' to również 'x'. W ust. 2 często trudno jest zdecydować, jak szeroka jest zmienna, co może prowadzić do niespodzianek. W przypadku pkt 3 należy wziąć pod uwagę "x". Dla punktu 4 definicja "prawda" jest niepoprawna - musi być niezerowa i znana. I tak dalej. – EML

2

~ jest operatorem bitowym i zwraca odwrotność argumentu.

! jest operatorem logicznym i zwraca pojedynczy bit.

Przykład:

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 

Dla przykładu:

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

jest faktycznie taki sam jak:

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

Ogólnie najlepszy styl kodowania jest użycie operatorów logicznych wewnątrz if . Używaj tylko operatorów bitowych z manipulacjami przydziału danych.

+0

FYI - Składnia "1" nie jest poprawną składnią Verilog. Konstrukt ten został wprowadzony w SystemVerilog. – dwikle

+0

Nie znając szerokości 'x' i' y', zdecydowałem się użyć składni SystemVeilog i umieściłem notatkę wyjaśniającą, do czego służy '1'. Od czasu wydania IEEE Std 1800-2009, Verilog i SystemVerilog są jednym i tym samym . (Wspomniany w skrócie, może ktoś inny może znaleźć lepszy cytat.) – Greg

+0

To użycie ~ w instrukcji if nie jest zbyt jasne. Zawsze używałbym ~ z porównaniem. Również mój symulator nie uważa, że ​​Verilog i SystemVerilog to to samo. Verilog jest często używany w odniesieniu do specyfikacji 1995 lub 2001 przed SystemVerilog ma to duże znaczenie dla tych, którzy używają starszych narzędzi. – Morgan

4

Rozumiem. Zmienna "x" w powyższym kodzie była liczbą całkowitą Verilog (integer x;). Jednak zmienna integer jest reprezentowana przez Verilog jako 32-bitową liczbę całkowitą. Więc nawet jeśli x było "1", tak jak to zaobserwowałem, ~ x nie spowoduje "0", ale "11111111111111111111111111111110"! I nic dziwnego, że pierwszy przypadek został wykonany. Moja wina. Dzięki za wszystkie odpowiedzi.

+0

Dobre pytanie, a samemu udało się uzyskać właściwą odpowiedź. – EML

+0

Cieszę się, że to załatwiłeś. Lekcja polega na użyciu typów 'reg' i' wire' w klasycznym Verilogu lub 'bit' i' logice' w nowoczesnym Verilogu i odpowiedniego doboru sygnałów. (Ostrzegam, typy te nie są równoważne) –