Introduction aux Tableaux Compacts en SystemVerilog
SystemVerilog introduit deux catégories principales d'agencements de données sous forme de tableaux : les tableaux compacts (packed arrays) et les tableaux non compacts (unpacked arrays). La distinction majeure réside dans la manière dont leurs dimensions sont déclarées par rapport au nom de la variable, ce qui influence leur représentation physique et leur manipulation.
Un tableau compact est caractérisé par la déclaration de ses dimensions avent le nom de la variable. Il garantit une allocation contiguë des bits en mémoire, formant une séquence ininterrompue de bits. Ces tableaux sont spécifiquement conçus pour contenir des types de données unitaires comme bit, logic, reg, ou d'autres tableaux compacts récursifs.
Voici un exemple pour illustrer la syntaxe :
logic [7:0] octet_compact; // Tableau compact (Packed array), également appelé vecteur
int liste_numeros[10]; // Tableau non compact (Unpacked array)
Tableaux Compacts Unidimensionnels (Vecteurs)
Un tableau compact à une seule dimension est souvent désigné sous le terme de "vecteur". Il représente une séquence de bits où chaque bit est directement accessible par son indice.
Exemple de Vecteur SystemVerilog
Cet exemple illustre la déclaration d'un vecteur de 8 bits, son assignation, puis l'itération à travers chacun de ses bits pour afficher leur valeur.
module test_vecteur;
logic [7:0] signal_donnees; // Un vecteur de 8 bits
initial begin
// 1. Assignation d'une valeur au vecteur
signal_donnees = 8'hC3; // Assigne la valeur binaire 1100_0011
$display("Valeur complète du vecteur : 0x%h (%b)", signal_donnees, signal_donnees);
// 2. Itération sur chaque bit du vecteur
for (int i = 0; i <= $right(signal_donnees); i++) begin // Itère de l'indice 0 au 7
$display("signal_donnees[%0d] = %b", i, signal_donnees[i]);
end
end
endmodule
L'exécution de ce code produirait une sortie similaire à :
ncsim> run
Valeur complète du vecteur : 0xc3 (11000011)
signal_donnees[0] = 1
signal_donnees[1] = 1
signal_donnees[2] = 0
signal_donnees[3] = 0
signal_donnees[4] = 0
signal_donnees[5] = 0
signal_donnees[6] = 1
signal_donnees[7] = 1
ncsim: *W,RNQUIE: Simulation is complete.
Tableaux Compacts Multidimensionnels
Les tableaux compacts peuvent également avoir plusieurs dimensions. Bien qu'ils soient structurés en groupes plus petits, ils conservent toujours la propriété fondamentale d'être une séquence continue de bits. L'ordre des dimensions dans la déclaration détermine comment ces bits sont regroupés et adressés.
Exemple 1 : Tableau Compact 2D
Considérons un tableau compact bidimensionnel. Par exemple, un tableau de 4 éléments, où chaque élément est lui-même un vecteur de 8 bits. Ceci représente un total de 32 bits, ou 4 octets.
module test_tableau_2d;
bit [3:0][7:0] memoire_simulee; // Un tableau 2D, 4 segments de 8 bits = 32 bits
initial begin
// 1. Assignation d'une valeur globale au tableau
memoire_simulee = 32'hFEED_BEEF; // Valeur 0xFEED BEEF
$display("Valeur totale : 0x%0h", memoire_simulee);
// 2. Itération sur chaque segment de 8 bits
for (int idx = $left(memoire_simulee); idx >= $right(memoire_simulee); idx--) begin
$display("memoire_simulee[%0d] = 0x%0h (%b)", idx, memoire_simulee[idx], memoire_simulee[idx]);
end
end
endmodule
La sortie de simulation met en évidence l'accès aux segments (octets) dans l'ordre de la déclaration de la dimension la plus significative à la moins significative :
ncsim> run
Valeur totale : 0xfeedbeef
memoire_simulee[3] = 0xfe (11111110)
memoire_simulee[2] = 0xed (11101101)
memoire_simulee[1] = 0xbe (10111110)
memoire_simulee[0] = 0xef (11101111)
ncsim: *W,RNQUIE: Simulation is complete.
Exemple 2 : Tableau Compact 3D
Un tableau compact tridimensionnel étend ce concept. Ici, nous déclarons un tableau de 2 "blocs", où chaque bloc contient 4 "lignes", et chaque ligne est un vecteur de 8 bits. Cela représente un total de 2 * 4 * 8 = 64 bits.
module test_tableau_3d;
logic [1:0][3:0][7:0] structure_data; // Un tableau 3D, 2*4*8 = 64 bits
initial begin
// 1. Assignation d'une valeur globale à la structure 3D
structure_data = 64'h11223344AABBCCDD; // Assignation d'un seul bloc de 64 bits
$display("Valeur globale de structure_data : 0x%0h", structure_data);
// 2. Itération à travers les dimensions pour afficher les valeurs
foreach (structure_data[i]) begin
$display("structure_data[%0d] = 0x%0h", i, structure_data[i]); // Accès aux blocs (32 bits)
foreach (structure_data[i][j]) begin
$display(" structure_data[%0d][%0d] = 0x%0h", i, j, structure_data[i][j]); // Accès aux lignes (8 bits)
end
end
end
endmodule
Les boucles imbriquées foreach en SystemVerilog sont utiles pour naviguer dans de tels agencements. Notez l'ordre d'itération (de l'indice le plus élevé au plus bas pour chaque dimension) et l'accès aux "tranches" de données :
ncsim> run
Valeur globale de structure_data : 0x11223344aabbccdd
structure_data[1] = 0x11223344
structure_data[1][3] = 0x11
structure_data[1][2] = 0x22
structure_data[1][1] = 0x33
structure_data[1][0] = 0x44
structure_data[0] = 0xaabbccdd
structure_data[0][3] = 0xaa
structure_data[0][2] = 0xbb
structure_data[0][1] = 0xcc
structure_data[0][0] = 0xdd
ncsim: *W,RNQUIE: Simulation is complete.