Comprendre les scalaires et vecteurs Verilog : Bits, registres et types de nets
Verilog doit représenter bits individuels et groupes de bits. Par exemple, un élément séquentiel 1-bit est une bascule. Un élément séquentiel 16-bit est un registre stockant 16 bits. Pour cela, Verilog a des scalaires et vecteurs pour nets et variables.
Scalaire et Vecteur
Une déclaration de net ou reg sans spécification de plage est 1-bit (scalaire). Si une plage est spécifiée, c'est une entité multi-bit (vecteur).

wire o_nor; // net scalaire 1-bit
wire [7:0] o_flop; // net vecteur 8-bit
reg parity; // variable scalaire 1-bit
reg [31:0] addr; // variable vecteur 32-bit pour adresse
La plage permet d'adresser des bits individuels dans un vecteur. Le bit de poids fort (MSB) est la valeur gauche, le bit de poids faible (LSB) la valeur droite.
wire [msb:lsb] name;
integer my_msb;
wire [15:0] priority; // msb=15, lsb=0
wire [my_msb: 2] prior; // illégal
Un net 16-bit "priority" est créé. MSB et LSB doivent être des expressions constantes, pas des variables. Mais peuvent être tout entier (positif, négatif, zéro) ; LSB peut être >, =, ou < MSB.
Sélection de bit (Bit-selects)
Tout bit dans une variable vectorielle peut être sélectionné et assigné individuellement : bit-select. Si hors limites ou bit-select est x ou z, la valeur retournée est x.

reg [7:0] addr; // 8-bit reg [7,6,5,4,3,2,1,0]
addr[0] = 1; // assigner 1 au bit 0
addr[3] = 0; // assigner 0 au bit 3
addr[8] = 1; // illégal : bit 8 n'existe pas
Sélection de partie (Part-selects)

Une plage de bits contigus peut être sélectionnée : part-select. Deux types : part-select constant et indexé.
reg [31:0] addr;
addr[23:16] = 8'h23; // bits 23 à 16 remplacés par 0x23 -> constant part-select
Un part-select variable permet utilisation efficace dans boucles. Le bit de départ peut varier, mais la largeur doit être constante.
[ +: ] // part-select incrémente depuis start-bit
[ -: ] // part-select décrémente depuis start-bit
module des;
reg [31:0] data;
int i;
initial begin
data = 32'hFACE_CAFE;
for (i = 0; i < 4; i++) begin
$display ("data[8*%0d +: 8] = 0x%0h", i, data[8*i +: 8]);
end
$display ("data[7:0] = 0x%0h", data[7:0]);
$display ("data[15:8] = 0x%0h", data[15:8]);
$display ("data[23:16] = 0x%0h", data[23:16]);
$display ("data[31:24] = 0x%0h", data[31:24]);
end
endmodule
Simulation Log :
ncsim> run data[8*0 +: 8] = 0xfe data[8*1 +: 8] = 0xca data[8*2 +: 8] = 0xce data[8*3 +: 8] = 0xfa data[7:0] = 0xfe data[15:8] = 0xca data[23:16] = 0xce data[31:24] = 0xfa ncsim: *W,RNQUIE: Simulation is complete.
Erreurs courantes
module tb;
reg [15:0] data;
initial begin
$display ("data[0:9] = 0x%0h", data[0:9]); // Erreur : ordre d'index inversé
end
endmodule
Verilog
- Maîtriser Verilog : Tutoriel complet pour la conception de circuits numériques
- Maîtriser la concaténation Verilog : Guide pratique
- Comprendre les affectations Verilog : Types, Syntaxe et Bonnes Pratiques
- Verilog Blocking vs Non-Blocking : Différences Clés Expliquées
- Maîtriser les Fonctions Verilog pour une Conception RTL Efficace
- Comprendre les Tasks Verilog : Fonctions vs Tasks, Syntaxe et Utilisation
- Comprendre les Délais Inter- et Intra-Affectation en Verilog
- Générateur d'Horloge Verilog : Guide de Conception et d'Implémentation
- Maîtriser les Fonctions Mathématiques Verilog pour une Conception Matérielle Efficace