webentwicklung-frage-antwort-db.com.de

Wie verhält sich Verilog mit negativen Zahlen?

Angenommen, ich habe einen reg [7:0] myReg Ich weise den Wert -8'D69 zu.

Ich weiß, dass Verilog es als Zweierkomplement speichert

10111011

Die Frage, die ich jetzt habe, ist, ob ich eine Operation ausführen soll, sagen Sie myReg/2

Würde es bis -34 auswerten? Oder würde es 10111011 dauern und es in 187 verwandeln, dann die Division durchführen und 93 zurückgeben?

12
wonton

Sie müssen sich daran erinnern, dass -8d69 nur ein kleines Muster ist. reg ist ein Typ, der Bitmuster enthält. Dies ist der Variablentyp, der / anweist, signierte oder vorzeichenlose Arithmetik auszuführen.

Wenn dies zur Synthese gedacht ist und Sie versuchen sollten, Teiler zu vermeiden, möchten Sie wirklich signierte Teiler vermeiden. Mit >>> 1 wird die Synthese wahrscheinlich kleiner. 

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 Verschiebt sich um x Stellen nach rechts, >>> x Verschiebt sich um x Stellen, das Vorzeichen verlängert sich jedoch bei signierten Typen. 

NB: Der /2 wird auch in meinen Beispielen aufgerundet. >>> wird abgerundet/abgeschnitten.

12
Morgan

Angenommen, ich habe ein reg [7: 0] myReg. Ich weise ihm den Wert .__ zu. -8'D69

Dies ist eigentlich keine vorzeichenbehaftete Zahl, sondern ein Ausdruck, der aus einer unären Negation besteht, die auf eine positive Konstante angewendet wird. Wenn der Ausdruck -8'd130 war, würde das Ergebnis überlaufen. Signierte Konstanten werden als 8'sd69 oder einfach als 69 deklariert.

Die Frage, die ich jetzt habe, ist, ob ich eine Operation daran ausführen soll. sag myReg/2

myReg ist nicht vorzeichenbehaftet, daher wird das Ergebnis des Ausdrucks auch vorzeichenlos *. Wenn das Ergebnis signiert werden soll, müssen alle -Operanden signiert werden. Dafür gibt es mehrere Möglichkeiten:

//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 die Auswertung von Ausdrücken sind viel komplexer, aber im Grunde ist das Ergebnis eines Ausdrucks unsigniert, sofern nicht 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
6
user597225

Ich werde das hinzufügen. 1. Die Datentypen bit und reg sind standardmäßig vorzeichenlos . 2. Die Datentypen int, integer, longint, shortint und byte sind standardmäßig signiert . 3. Für alle diese Datentypen kann ein vorzeichenbehaftetes oder nicht signiertes Qualifikationsmerkmal verwendet werden, um die Standardeinstellung zu ändern.

Durch Zuweisen von -8'D69 zu myReg wird eine implizite Konvertierung in 187 vorgenommen. Dann ist myReg/2 = 187/2 = 93, ohne Vorzeichen. Es ist wichtig zu verstehen, wann und wie SystemVerilog implizite Typkonvertierungen in Ausdrücken und Zuweisungen durchführt.

1
Steve K