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 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 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
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
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
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 [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
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
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 [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
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
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
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
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 [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
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
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'échappement | Caractère affiché |
|---|---|
| \n | Nouvelle ligne |
| \t | Onglet |
| %% | % |
| \ | \ |
| \" | " |
| \ooo | 1 à 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.