L'anatomie d'un littéral dimensionné
Un littéral Verilog a jusqu'à trois parties :
8'b1010_1100
│ │ │
│ │ └─ chiffres dans la base choisie
│ └─── spécificateur de base : b (binaire), h (hex), d (décimal), o (octal)
└────── largeur en bits (décimal)
Lecture gauche à droite : « une valeur 8 bits, écrite en binaire, avec les chiffres 10101100 ». C'est 172 en décimal, 0xAC en hex, les mêmes bits quelle que soit l'écriture. La largeur dit au compilateur exactement combien de bits allouer ; la base lui dit comment interpréter les chiffres.
Les underscores sont des séparateurs visuels. 32'b1010_1100_0011_0101 est la même chose que 32'b1010110000110101. Utilise-les.
Les quatre bases
Hex (h) est le standard pour tout ce qui est plus large que 4 bits. Binaire (b) est le standard quand tu veux lire les motifs de bits directement. Décimal (d) sert aux comptes lisibles par les humains. Octal (o) existe mais tu ne le verras presque jamais.
Les chiffres hex sont insensibles à la casse : 8'hAB et 8'hab sont identiques.
Que se passe-t-il quand la valeur ne rentre pas ?
Si tes chiffres ne remplissent pas la largeur déclarée, Verilog zéro-étend à gauche :
8'b101 // équivalent à 8'b00000101 (= 5)
8'hF // équivalent à 8'h0F (= 15)
Si tes chiffres dépassent la largeur déclarée, Verilog tronque les bits hauts avec un warning :
4'hFF // tronque à 4'hF, le simulateur warne
4'b10000 // tronque à 4'b0000
Le warning est ton ami. Ne le masque pas.
Dimensionné vs non dimensionné
Un littéral sans largeur :
'd10 // non dimensionné, prend la taille par défaut (≥32 bits)
10 // également non dimensionné - pas de base veut dire décimal
Les littéraux non dimensionnés prennent par défaut 32 bits dans la plupart des outils. C'est la source d'une classe entière de bugs :
reg [7:0] count;
if (count == -1) ... // -1 est non dimensionné 32 bits ; la comparaison devient bizarre
La correction est d'écrire 8'hFF au lieu de -1, ou 8'd255, ou {8{1'b1}}. Dimensionne toujours les littéraux quand ils sont utilisés dans des expressions à largeur spécifique.
Le seul endroit où les littéraux non dimensionnés sont OK, ce sont les compteurs entiers dans les boucles for de testbench, où l'entier est assez large pour que rien de surprenant n'arrive.
Littéraux signés
Par défaut, les littéraux dimensionnés sont non signés :
8'd255 // 255 non signé
8'b1111_1111 // 255 non signé - même motif de bits, juste écrit différemment
Si tu veux que le littéral soit interprété comme signé, ajoute s après l'apostrophe :
8'sd10 // signé 10
8'sb1111_1111 // signé -1 (complément à deux)
Le flag s compte pour :
- Les opérateurs
<<<et>>>(shifts arithmétiques) - ils sign-étendent les opérandes signés. - Les opérateurs de comparaison sur des expressions mixtes signées.
- Les casts
$signed/$unsigned.
Pour la plupart de l'arithmétique ordinaire sur des signaux de bus, tu laisseras le s de côté.
Littéraux numériques avec X et Z
Un chiffre littéral peut être x (inconnu) ou z (haute impédance) :
8'bx est un raccourci pour « tous les 8 bits inconnus » - la valeur est propagée pour remplir la largeur déclarée. Les chiffres x sont courants dans les cas default des machines à états et dans l'initialisation. On couvre la sémantique dans Valeurs X et Z.
Où les littéraux dimensionnés apparaissent en pratique
Une fois que tu commences à écrire de vrais modules, les littéraux dimensionnés apparaissent partout :
// Largeurs de bus
input wire [31:0] addr;
wire [31:0] zero = 32'h0;
wire [31:0] all_ones = 32'hFFFF_FFFF;
// Encodages d'état
localparam IDLE = 3'd0;
localparam BUSY = 3'd1;
localparam DONE = 3'd2;
// Masques
wire is_msb_set = data & 32'h8000_0000;
// Comparaisons
if (counter == 8'd255) ...
// Valeurs de reset
always @(posedge clk) begin
if (reset) data_out <= 8'd0;
else data_out <= data_in;
end
Le motif est constant : écrire la largeur, écrire la base, écrire les chiffres. Chaque littéral que tu utilises a la même forme.
Un essai
Tu as maintenant tout ce qu'il te faut pour écrire n'importe quelle constante qu'un module Verilog pourrait vouloir. La dernière pièce de l'histoire des types de données, c'est ce qui se passe quand un signal n'est pas un 0 ou 1 propre - les valeurs x et z.
Questions fréquentes
Que veut dire 8'b1010 en Verilog ?
C'est un littéral binaire dimensionné : une valeur 8 bits dont la représentation binaire est 00001010. Le nombre avant l'apostrophe est la largeur en bits ; la lettre après l'apostrophe est la base (b binaire, h hex, d décimal, o octal) ; les chiffres après sont la valeur. Le littéral est zero-paddé à gauche si les chiffres ne remplissent pas la largeur.
Quelle est la différence entre nombres dimensionnés et non dimensionnés en Verilog ?
Un littéral dimensionné comme 8'd10 fait exactement 8 bits. Un littéral non dimensionné comme 'd10 ou juste 10 prend par défaut 32 bits, ce qui est généralement trop. Mélanger des littéraux non dimensionnés dans des expressions à largeur spécifique cause des bugs subtils - préfère les littéraux dimensionnés partout sauf dans le code de test jetable.
Comment écrire un nombre hex en Verilog ?
Utilise le spécificateur de base 'h : 8'hFF est une valeur 8 bits de 255. Les chiffres hex sont insensibles à la casse ; 8'hff et 8'hFF sont identiques. Tu peux grouper les chiffres avec des underscores pour la lisibilité : 32'hDEAD_BEEF. Les underscores sont ignorés par le parser.
Comment fonctionnent les underscores dans les nombres Verilog ?
Les underscores sont des séparateurs visuels que le parser ignore. 32'b1010_1100_0011_0101 est exactement la même valeur que 32'b1010110000110101 mais beaucoup plus lisible. Le premier caractère après le préfixe de base ne peut pas être un underscore, mais tu peux en mettre n'importe où ailleurs dans la chaîne de chiffres.
Comment écrire un nombre signé en Verilog ?
Ajoute s après l'apostrophe : 8'sd10 est un décimal 8 bits signé 10, et 8'sb1111_1111 est signé -1. Par défaut, les littéraux dimensionnés sont non signés ; le modificateur s inverse ça. La plupart de l'arithmétique utilise des opérandes non signés - n'utilise le signé que quand tu as vraiment besoin que les valeurs négatives se propagent à travers <, >>> et opérateurs similaires.