Les 2 types de données les plus couramment utilisés en Verilog sont net (wire) et register (reg). Les autres types peuvent être compris comme des extensions ou des versions auxiliaires de ces deux types de données.

[3:0] = 4'hF, où la largeur peut être omise ;

Le type wire représente des connexions physiques entre unités matérielles, pilotées en permanence par les bornes de sortie des dispositifs qui y sont connectés. Si aucun élément de pilotage n'est connecté à une variable wire, la valeur par défaut est généralement « Z ». Un exemple est le suivant :

Exemple

wire   interrupt ;
wire   flag1, flag2 ;
wire   gnd = 1'b0 ;  

Il existe d'autres types de données net, notamment wand, wor, wri, triand, trior, trireg, etc. Ces types de données ne sont pas très fréquemment utilisés, ils ne sont donc pas présentés ici.

Registre (reg)

Le registre (reg) est utilisé pour représenter des éléments de stockage. Il conserve la valeur d'origine des données jusqu'à ce qu'elle soit réécrite. Un exemple de déclaration est le suivant :

Exemple

reg    clk_temp;
reg    flag1, flag2 ;

Par exemple, dans un bloc always, un registre peut être synthétisé en une bascule déclenchée sur front, et en logique combinatoire, il peut être synthétisé en une variable de type wire. Les registres ne nécessitent pas de source de pilotage et n'ont pas nécessairement besoin d'un signal d'horloge. Pendant la simulation, la valeur d'un registre peut être modifiée à tout moment par des opérations d'affectation. Par exemple :

Exemple

reg rstn ;
initial begin
    rstn = 1'b0 ;
    #100 ;
    rstn = 1'b1 ;
end

Vecteur

Lorsque la largeur de bits est supérieure à 1, wire ou reg peuvent être déclarés sous forme vectorielle. Par exemple :

Exemple

reg [3:0]      counter ;    //Déclare un registre compteur de 4 bits de large
wire [32-1:0]  gpio_data;   //Déclare une variable wire gpio_data de 32 bits de large
wire [8:2]     addr ;       //Déclare une variable wire addr de 7 bits de large, avec une plage de largeur de bits 8:2
reg [0:31]     data ;       //Déclare une variable de registre data de 32 bits de large, avec le bit de poids fort à 0

Pour les vecteurs ci-dessus, nous pouvons spécifier un bit particulier ou plusieurs bits adjacents à utiliser dans une autre logique. Par exemple :

Exemple

wire [9:0]     data_low = data[0:9] ;
addr_temp[3:2] = addr[8:7] + 1'b1 ;

Verilog prend en charge la sélection de partie de vecteur variable. Par exemple :

Exemple

reg [31:0]     data1 ;
reg [7:0]      byte1 [3:0];
entier j ;
always@* begin
    for (j=0; j<=3;j=j+1) begin
        byte1[j] = data1[(j+1)*8-1 : j*8];
        //Affecter data1[7:0]…data1[31:24] à byte1
    end
end

Verilog prend également en charge l'accès par sélection partielle de vecteur à largeur fixe après avoir spécifié une position de bit.

  • [bit+: width]+: Incrémente à partir de la position de bit de départ, avec une largeur de bit de width.
  • [bit-: width]-: Décrémente à partir de la position de bit de départ, avec une largeur de bit de width.

Exemple

//Les 2 affectations suivantes sont équivalentes
A = data1[31-: 8] ;
A = data1[31:24] ;

//Les 2 affectations suivantes sont équivalentes
B = data1[0+ : 8] ;
B = data1[0:7] ;

Lors de la recombinaison de signaux dans un nouveau vecteur, des accolades sont nécessaires. Par exemple :

Exemple

wire [31:0]    temp1, temp2 ;
assign temp1 = {byte1[0][7:0], data1[31:8]};  //Concaténation de données
assign temp2 = {32{1'b0}};  //Affecter une valeur 32 bits 0

Variables de registre de type Integer, Real et Time

Les types de données tels que integer, real et time appartiennent en fait aussi au type registre.

Integer

Le type integer est déclaré avec le mot-clé integer. Il n'est pas nécessaire de spécifier la largeur de bits lors de la déclaration ; la largeur de bits dépend du compilateur et est généralement de 32 bits. Les variables reg sont non signées, tandis que les variables integer sont signées. Par exemple :

Exemple

reg [31:0]      data1 ;
reg [7:0]       byte1 [3:0]; //Variable de tableau, présentée ultérieurement
integer j ;  //Variable de type integer, utilisée pour aider à générer des circuits numériques
always@* begin
    for (j=0; j<=3;j=j+1) begin
        byte1[j] = data1[(j+1)*8-1 : j*8];
        //Affecter data1[7:0]…data1[31:24] à byte1
        end
end

Dans cet exemple, le signal integer j est utilisé comme signal auxiliaire pour affecter les données de data1 au tableau byte1 en séquence. Après synthèse, le signal j n'existe pas réellement dans le circuit ; j aide seulement à générer le circuit matériel correspondant.

Real

Les nombres réels sont déclarés avec le mot-clé real et peuvent être exprimés en notation décimale ou scientifique. Les déclarations real ne peuvent pas avoir de plage, et la valeur par défaut est 0. Si un nombre réel est affecté à une variable integer, seule la partie entière du nombre réel est affectée à la variable integer. Par exemple :

Exemple

real        data1 ;
integer     temp ;
initial begin
    data1 = 2e3 ;
    data1 = 3.75 ;
end
 
initial begin
    temp = data1 ; //La valeur de temp est 3
end

Temps

Verilog utilise une variable de registre de temps spéciale de type time pour stocker le temps de simulation. Sa largeur est généralement de 64 bits. Le temps de simulation actuel est obtenu en appelant la fonction système $time. Par exemple :

Exemple

time       current_time ;
initial begin
       #100 ;
       current_time = $time ; //La valeur de current_time est 100
end

Tableau

En Verilog, les tableaux de reg, wire, integer, time, real et de leurs types vectoriels sont autorisés.

Il n'y a aucune limite quant au nombre de dimensions d'un tableau. Les tableaux de nets peuvent également être utilisés pour connecter les ports de modules instanciés. Chaque élément d'un tableau peut être utilisé comme un scalaire ou un vecteur de la même manière, sous la forme :<array_name>[<index>]. Pour les tableaux multidimensionnels, l'utilisateur doit spécifier l'indice pour chaque dimension. Par exemple :

Exemple

integer          flag [7:0] ; //Un tableau composé de 8 entiers
reg  [3:0]       counter [3:0] ; //Un tableau composé de 4 compteurs de 4 bits
wire [7:0]       addr_bus [3:0] ; //Un tableau composé de 4 variables wire de 8 bits
wire             data_bit[7:0][5:0] ; //Déclare un tableau bidimensionnel de variables wire de 1 bit
reg [31:0]       data_4d[11:0][3:0][3:0][255:0] ; //Déclare un tableau à 4 dimensions de variables de données de 32 bits

Ce qui suit montre les opérations d'affectation sur les éléments du tableau :

Exemple

flag [1]   = 32'd0 ; //Affecte au deuxième élément du tableau flag une valeur de 0 sur 32 bits
counter[3] = 4'hF ;  //Affecte la valeur du 4e élément du tableau counter à un nombre hexadécimal F de 4 bits, équivalent à counter
assign addr_bus[0]        = 8'b0 ; //Affecte la valeur du premier élément du tableau addr_bus à 0
assign data_bit[0][1]     = 1'b1;  //Affecter la valeur 1 à l'élément de la ligne 1, colonne 2 du tableau data_bit. Ici, le deuxième indice d'accès ne peut pas être omis ; c'est-à-dire assign data_bit
data_4d[0][0][0][0][15:0] = 15'd3 ;  //Affecter les bits 15~0 de l'élément de registre étiqueté

Bien que les tableaux et les vecteurs soient accédés d'une manière quelque peu similaire, ne confondez pas les vecteurs avec les tableaux. Un vecteur est un élément unique d'une largeur de bit de n ; un tableau est composé de plusieurs éléments, chacun ayant une largeur de bit de n ou 1. Ils diffèrent par leur définition structurelle.

Mémoire

Une variable mémoire est un type de tableau de registres qui peut être utilisé pour décrire le comportement de la RAM ou de la ROM. Par exemple :

Exemple

reg               membit[0:255] ;  //mémoire de 256 cellules de 1 bit
reg  [7:0]        mem[0:1023] ;    //mémoire de 1Kbyte d'une largeur de 8 bits
mem[511] = 8'b0 ;                  //Définir la valeur de la 512e cellule mémoire de 8 bits à 0

Paramètre

Les paramètres sont utilisés pour représenter des constantes, déclarés avec le mot-clé parameter, et ne peuvent être affectés qu'une seule fois. Par exemple :

Exemple

parameter      data_width = 10'd32 ;
paramètre      i=1, j=2, k=3 ;
parameter      mem_size = data_width * 10 ;

Cependant, la valeur d'un paramètre dans un module peut être modifiée via l'instanciation. Cela sera présenté plus tard.

Les paramètres locaux sont déclarés avec localparam. Leur fonction et leur utilisation sont les mêmes que celles de parameter, sauf que leur valeur ne peut pas être modifiée. Par conséquent, lorsqu'un paramètre est utilisé uniquement dans le module courant, localparam peut être utilisé pour le déclarer.

String

Les chaînes de caractères sont stockées dans des variables de type reg, chaque caractère occupant un octet (8 bits). Par conséquent, la largeur de la variable de registre doit être suffisamment grande pour éviter un débordement.

Les chaînes de caractères ne peuvent pas être écrites sur plusieurs lignes ; c'est-à-dire qu'une chaîne ne peut pas contenir de caractères de retour chariot. Si la largeur de la variable de registre est supérieure à la taille de la chaîne, des 0 sont utilisés pour remplir les bits restants à gauche ; si la largeur de la variable de registre est inférieure à la taille de la chaîne, les données excédentaires à gauche de la chaîne sont tronquées. Par exemple, pour stocker la chaîne "run.example.com", 14*8 bits de stockage sont nécessaires :

Exemple

reg [0: 14*8-1]       str ;
initial begin
    str = "run.example.com";
end  

Certains caractères spéciaux ont une signification particulière dans les chaînes d'affichage, tels que le saut de ligne, la tabulation, etc. Si vous devez afficher ces caractères spéciaux dans une chaîne, vous devez les faire précéder d'un caractère d'échappement\. Par exemple, comme indiqué dans le tableau suivant :

Caractère d'échappementCaractère affiché
\nNouvelle ligne
\tOnglet
%%%
\\
\""
\ooo1 à 3 chiffres octaux

En fait, dans SystemVerilog (un langage de programmation principalement utilisé pour la simulation Verilog), le mot-clé string peut déjà être utilisé directement pour représenter le type de variable chaîne, ce qui apporte une grande commodité à la simulation Verilog. Les personnes intéressées peuvent apprendre brièvement SystemVerilog.