Les Tableaux Compacts (Packed Arrays) en SystemVerilog

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.

Étiquettes: SystemVerilog Packed Array vecteur type de données HDL

Publié le 5 octobre à 17h30