web-dev-qa-db-fra.com

Comment Verilog se comporte-t-il avec les nombres négatifs?

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?

12
wonton

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.

12
Morgan

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
6
user597225

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.

1
Steve K