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?
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.
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
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.