2013-05-07 68 views
10

Quindi è finito che il bug che mi aveva tenuto acceso per giorni, era una sezione di codice che avrebbe dovuto valutare False valutando True. Il mio codice iniziale andato qualcosa di simile:Qual è la differenza tra Verilog! e ~?

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

vale a dire se x non è uno e Y non è uno poi fare cose. Passando attraverso il debugger, mi sono reso conto anche se x era 1 l'espressione nell'istruzione if risultava ancora in TRUE e il codice successivo veniva eseguito.

Tuttavia, quando ho cambiato la dichiarazione:

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

e anche provato:

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

il codice all'interno del se-dichiarazione non è stato valutato che è stato il comportamento previsto. Capisco che ~ è una negazione per bit e! una negazione logica, ma non dovrebbe (~ x & & ~ y) e (! x & &! y) valutare la stessa cosa? Temo che il codebase sia troppo grande, quindi non posso incollarlo qui, ma questa è stata l'unica modifica che ho apportato per far funzionare il codice come volevo. Grazie.


In risposta, ad uno dei commenti qui sotto, ho creato un test-case per verificare questo comportamento:

`scala cronologica 10ns/1ns

modulo 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 

e stranamente, "Primo caso eseguito" viene stampato per confermare il comportamento originale ho osservato.

+0

indovinando, ma la negazione bit a bit non sarebbe qualcosa come '~ 0xAA = 0x55', v.s. '! 0xAA' è l'equivalente di" 0xAA non è zero, quindi valuta true ". –

+0

@Marc B Sì, questa è una differenza importante. Tuttavia, in questo caso, sia x che y sono lunghi 1 bit. Se x è "1", mi aspetterei che una negazione bit per bit ~ x sia "0" .. – iab

+0

Un po 'lungo? Che strano. Puoi fare un progetto di prova per visualizzare i valori di 'x','! X', '~ x',' y', '! Y',' ~ y', e '(~ x && ~ y)' e '(! x &&! y)'? –

risposta

13

Il simbolo ! rappresenta la negazione booleana o logica. Per qualsiasi valore di x diverso da zero, !x viene valutato su zero o falso e quando x è zero, !x viene valutato su uno o su true.

Il simbolo ~ rappresenta la negazione bit a bit. Ogni bit del valore viene commutato, quindi per un x == 0xA5A5 a 16 bit, ~x valuterà a 0x5A5A.

Il condizionale if() prevede un'espressione che restituisce true o false, dove qualsiasi valore diverso da zero (positivo o negativo) è true e zero è false.

Il && è un AND logico. Richiede due espressioni, valutando una o una vera se e solo se entrambe le espressioni sono vere. Di nuovo, "vero" qui significa diverso da zero, positivo o negativo.

Dato tutto questo, possiamo vedere che l'unica volta che ~x e !x valutare allo stesso valore è quando x == -1, oppure, se non è firmato x, quando x == MAX_UNSIGNED.

+0

Ho aggiunto un progetto di test al post originale. Lo stesso comportamento è osservato! – iab

+0

Quanti bit di larghezza è il numero intero predefinito? ~ 1 == 0xFFFE e ~ 0 == 0xFFFF, quindi l'esempio ha senso. –

+1

Purtroppo è molto più complicato di questo (vedo che qualcuno ha appena cliccato sulla tua risposta). La tua spiegazione di '!' Non è corretta - il risultato è 3-state ('1',' 0', 'x'), e'! X' è anche 'x'. Nel paragrafo 2, è spesso difficile decidere quanto sia ampia una variabile, il che può portare a sorprese. Per il paragrafo 3, devi prendere in considerazione 'x'. Per il paragrafo 4, la tua definizione di 'true' non è corretta - deve essere diversa da zero e nota. E così via. – EML

2

~ è un operatore bit-saggio e restituisce l'inverso dell'argomento.

! è un operatore logico e restituisce un singolo bit.

Esempio:

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 

Per esempio:

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

è effettivamente la stessa:

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

Generalmente il migliore stile di codifica è quello di utilizzare gli operatori logici all'interno if . Utilizzare solo operatori bit-bit con manipolazioni di assegnazione dati.

+0

FYI - La sintassi ''1' non è valida sintassi Verilog. Questo costrutto è stato introdotto in SystemVerilog. – dwikle

+0

Non conoscendo le larghezze di 'x' e' y', ho deciso di usare la sintassi di SystemVeilog e ho messo una nota per spiegare a cosa serve "1". Dal rilascio di IEEE Std 1800-2009, Verilog e SystemVerilog sono la stessa . (Menzionato in astratto, forse qualcun altro può trovare una citazione migliore.) – Greg

+0

L'uso di ~ nell'istruzione if non è molto chiaro. Userei sempre ~ con un confronto. Anche il mio simulatore non pensa che Verilog e SystemVerilog siano la stessa cosa. Verilog è spesso usato per riferirsi alle specifiche del 1995 o del 2001 prima di SystemVerilog, fa una grande differenza per chi usa strumenti precedenti. – Morgan

4

Vedo. La variabile "x" nel codice precedente era un intero Verilog (integer x;). Tuttavia, una variabile numero intero è rappresentata da Verilog come numero intero a 32 bit. Quindi anche se x era "1" come avevo osservato, ~ x non produrrà "0" ma in "111111111111111111111111111111111110"! E quindi non sorprende che sia stato eseguito il primo caso. Colpa mia. Grazie per tutte le risposte.

+0

Buona domanda, e sei riuscito a ottenere la risposta giusta da solo. – EML

+0

Felice che tu l'abbia elaborato. La lezione è di usare i tipi 'reg' e' wire' nel classico Verilog, o i tipi 'bit' e' logic' nel moderno Verilog e dimensionare opportunamente i segnali. (Attenzione, questi tipi non sono equivalenti) –

Problemi correlati