Par exemple, disons que j'ai un reg [7:0] myReg
Je lui attribue la valeur -8'D69
Je sais que Verilog le stocke en tant que complément à 2, il devrait donc être stocké sous
10111011
La question que je me pose maintenant est de savoir si je devais effectuer une opération, disons myReg/2
Serait-il évaluer à -34? Ou faudrait-il 10111011 et le transformer en 187 puis effectuer la division, en retournant 93?
Vous devez vous rappeler que -8d69
est juste un motif de bits. reg est un type qui contient des modèles de bits. C'est le type de variable qui indique à /
d'effectuer une arithmétique signée ou non signée.
Si ceci est une synthèse, gardez à l'esprit que vous voulez essayer d'éviter les séparateurs, vous voulez vraiment essayer d'éviter les séparateurs signés. La synthèse sera probablement plus petite avec >>> 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
Donne:
a : 01011101, 93
b : 11011110, -34
c >>>1 : 01011101, 93
d >>>1 : 11011101, -35
>> x
Décale vers la droite x places, >>> x
Décale la droite x places mais le signe s'étend pour les types signés.
NB: le /2
est également arrondi dans mes exemples, >>>
arrondira/tronquera.
Par exemple, disons que j'ai un reg [7: 0] myReg, je lui attribue la valeur -8'D69
En réalité, ce n'est pas un nombre signé, mais une expression consistant en une négation unaire appliquée à une constante positive. Si l'expression était -8'd130
, le résultat déborderait. Les constantes signées sont déclarées en tant que 8'sd69
ou simplement 69
.
La question que je me pose maintenant est de savoir si je devais effectuer une opération dessus. dire myReg/2
myReg
étant non signé, le résultat de l'expression sera également non signé *. Si vous souhaitez que le résultat soit signé, alors que tous les opérandes doivent être signés. Il y a plusieurs façons d'y parvenir:
//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;
* Les règles complètes concernant l'évaluation des expressions sont beaucoup plus complexes, mais le résultat de toute expression est non signé, sauf si tous les opérandes sont signés.
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
Je vais ajouter que 1. Les types de données bit et reg sont non signés, par défaut . 2. Les types de données int, integer, longint, shortint et byte sont signés, par défaut . 3. Tous ces types de données peuvent prendre un qualificatif signé ou non signé pour changer la valeur par défaut.
Ainsi, l'attribution de -8'D69 à myReg effectue une conversion implicite en 187. Ensuite, myReg/2 = 187/2 = 93, non signé. Il est important de comprendre quand et comment SystemVerilog effectue des conversions de types implicites dans des expressions et des assignations.