2012-09-13 8 views
9

Zum Beispiel sagen, ich habe ein reg [7:0] myReg ich es den Wert -8'D69Wie verhält sich Verilog mit negativen Zahlen?

Ich weiß, Verilog speichert sie als 2-Komplement zuweisen, so dass es als

10111011 

Die Frage, die ich jetzt gespeichert werden soll, wenn ich Würde eine Operation darauf ausführen, sagen myReg/2

Würde es zu -34 bewerten? Oder würde es 10111011 nehmen und es in 187 verwandeln, dann die Division durchführen und 93?

+1

Sie sollten auch signierte Nummern als solche deklarieren. 'reg signed [7: 0] my_reg' – Morgan

+0

Sie könnten >>> 1 verwenden, um eine Vorzeichenerweiterung um 2 auszuführen (wenn es als signierter Typ deklariert ist). – Morgan

Antwort

10

Sie müssen daran denken, dass -8d69 nur ein Bitmuster ist. reg ist ein Typ, der Bitmuster enthält. Es ist der Variablentyp, der / anweist, vorzeichenbehaftete oder vorzeichenlose Arithmetik auszuführen.

Wenn dies für die Synthese im Hinterkopf ist, dass Sie versuchen, Teiler zu vermeiden, möchten Sie wirklich versuchen, signierte Teiler zu vermeiden. Es wird Synthese wahrscheinlich kleiner mit >>> 1

reg [7:0] a; 
reg signed [7:0] b; 
reg [7:0] c; 
reg signed [7:0] d; 

initial begin 
    a = -8'd69 ; 
    b = -8'd69 ; 
    c = -8'd69 ; 
    d = -8'd69 ; 
    #10ns; 
    a = a/2  ; 
    b = b/2  ; 
    #10ns; 
    $display("a  : %8b, %d", a, a); 
    $display("b  : %8b, %d", b, b); 
    $display("c >>>1 : %8b, %d", c>>>1, c>>>1); 
    $display("d >>>1 : %8b, %d", d>>>1, d>>>1); 
end 

Gibt:

a  : 01011101, 93 
b  : 11011110, -34 
c >>>1 : 01011101, 93 
d >>>1 : 11011101, -35 

>> x Shifts rechts von x Orte, >>> x Shifts rechts x Plätze, aber Zeichen erstreckt für signierte Typen.

Hinweis: Die /2 wird auch in meinen Beispielen aufgerundet, >>> wird abgerundet/abgeschnitten.

5

Zum Beispiel sagen, dass ich eine reg haben [7: 0] myReg I weisen Sie den Wert -8'D69

Dies ist eigentlich nicht eine signierte Zahl ist, sondern ein Ausdruck, der aus eine unäre Negation, die auf eine positive Konstante angewendet wird. Wenn der Ausdruck -8'd130 wäre, würde das Ergebnis überlaufen. Vorzeichenbehaftete Konstanten werden als 8'sd69 oder nur 69 deklariert.

Die Frage, die ich jetzt habe, ist, wenn ich es, eine Operation auszuführen waren, sagen myReg/2

myReg nicht signiert ist, so der Ausdruck Ergebnis auch ohne Vorzeichen * sein wird. Wenn Sie das Ergebnis als signieren müssen, müssen alle Operanden signiert sein. Es gibt ein paar Möglichkeiten, dies zu erreichen:

//Declare the reg as signed and divide by a signed value 
reg signed [7:0] myReg; 
assign result = myReg/2; 

//Use system functions 
assign result = $signed(myReg)/2; 

* Die vollständigen Regeln für Ausdrucksauswertung sind viel komplexer, aber im Grunde ist das Ergebnis eines Ausdrucks ist nicht signiert, es sei denn, alle Operanden signiert sind.

reg signed [7:0] a; 
reg [7:0] b; 

initial 
begin 
result = a;   //Signed 
result = a * a;  //Signed 
result = a * 10;  //Signed 
result = $unsigned(a); //Unsigned 
result = a[0];   //Unsigned 
result = a[7:0];  //Unsigned 
result = {a,a};  //Unsigned 
result = 10{a};  //Unsigned 
result = a + b;  //Unsigned 
result = a * b;  //Unsigned 
end 
1

Ich werde hinzufügen, dass 1. Datentypen Bit und Ausrichtung sind nicht signiert, standardmäßig aktiviert. 2. Die Datentypen int, integer, longint, shortint und byte sind standardmäßig signiert. 3. Für alle diese Datentypen kann ein Vorzeichen mit oder ohne Vorzeichen verwendet werden, um den Standardwert zu ändern.

Also die Zuordnung von -8'D69 zu myReg führt eine implizite Konvertierung zu 187. Dann ist myReg/2 = 187/2 = 93, unsigned. Es ist wichtig zu verstehen, wann und wie SystemVerilog implizite Typkonvertierungen in Ausdrücken und Zuweisungen durchführt.