verilog Tutoriel
Démarrer avec Verilog
Recherche…
Remarques
Verilog est un langage de description de matériel (HDL) utilisé pour concevoir, simuler et vérifier des circuits numériques à un niveau comportemental ou de transfert de registre. Il est à noter pour une raison qui le distingue des langages de programmation "traditionnels":
- Il existe deux types d’affectation, le blocage et le non-blocage, chacun avec ses propres utilisations et sémantique.
- Les variables doivent être déclarées comme étant à un seul bit ou avec une largeur explicite.
- Les conceptions sont hiérarchiques, avec la possibilité d'instancier des modules ayant un comportement souhaité.
- Dans la simulation (pas généralement en synthèse), les variables de
wire
peuvent être dans l'un des quatre états suivants: 0, 1, flottant (z
) et indéfini (x
).
Versions
Version | Date de sortie |
---|---|
Verilog IEEE-1364-1995 | 1995-01-01 |
Verilog IEEE-1364-2001 | 2001-09-28 |
Verilog IEEE-1364.1-2002 | 2002-12-18 |
Verilog IEEE-1364-2005 | 2006-04-07 |
SystemVerilog IEEE-1800-2009 | 2009-12-11 |
SystemVerilog IEEE-1800-2012 | 2013-02-21 |
Installation ou configuration
Les instructions détaillées sur la configuration ou l'installation de Verilog dépendent de l'outil que vous utilisez, car il existe de nombreux outils Verilog.
introduction
Verilog est un langage de description de matériel (HDL) utilisé pour modéliser des systèmes électroniques. Il décrit le plus souvent un système électronique au niveau du transfert de registre (RTL) de l'abstraction. Il est également utilisé dans la vérification des circuits analogiques et des circuits à signaux mixtes. Sa structure et ses principes fondamentaux (décrits ci-dessous) sont conçus pour décrire et mettre en œuvre avec succès un système électronique.
- Rigidité
Un circuit électronique est une entité physique ayant une structure fixe et Verilog est adapté pour cela. Les modules (module), les ports (input / output / inout), les connexions (fils), les blocs (@always), les registres (reg) sont tous fixés au moment de la compilation. Le nombre d'entités et d'interconnexions ne change pas de manière dynamique. Il y a toujours un "module" au niveau supérieur représentant la structure de la puce (pour la synthèse) et un au niveau du système pour la vérification. - Parallélisme
Les opérations simultanées inhérentes à la puce physique sont imitées dans le langage par des blocs toujours (la plupart du temps), initiaux et fork / join.
module top();
reg r1,r2,r3,r4; // 1-bit registers
initial
begin
r1 <= 0 ;
end
initial
begin
fork
r2 <= 0 ;
r3 <= 0 ;
join
end
always @(r4)
r4 <= 0 ;
endmodule
Toutes les déclarations ci-dessus sont exécutées en parallèle dans la même unité de temps.
Chronométrage et synchronisation
Verilog prend en charge diverses constructions pour décrire la nature temporelle des circuits. Les temporisations et les délais dans les circuits peuvent être implémentés dans Verilog, par exemple par #delay constructs. De même, Verilog prend également en charge des circuits et des composants synchrones et asynchrones tels que les flops, les verrous et la logique combinatoire en utilisant différentes constructions, par exemple des blocs "toujours". Un ensemble de blocs peut également être synchronisé via un signal d'horloge commun ou un bloc peut être déclenché en fonction d'un ensemble spécifique d'entrées.#10 ; // delay for 10 time units always @(posedge clk ) // synchronous always @(sig1 or sig2 ) // combinatorial logic @(posedge event1) // wait for post edge transition of event1 wait (signal == 1) // wait for signal to be 1
Incertitude
Verilog soutient certaines des incertitudes inhérentes aux circuits électroniques. "X" représente l'état inconnu du circuit. "Z" est utilisé pour représenter l'état non contrôlé du circuit.reg1 = 1'bx; reg2 = 1'bz;
Abstraction
Verilog prend en charge la conception à différents niveaux d'abstraction. Le niveau d'abstraction le plus élevé pour une conception est le niveau de transfert de résistance (RTL), le niveau suivant étant le niveau de la porte et le plus bas le niveau de la cellule (User Define Primitives). Verilog prend également en charge le niveau comportemental d'abstraction sans tenir compte de la réalisation structurelle de la conception, principalement utilisée pour la vérification.
// Example of a D flip flop at RTL abstraction
module dff (
clk , // Clock Input
reset , // Reset input
d , // Data Input
q // Q output
);
//-----------Input Ports---------------
input d, clk, reset ;
//-----------Output Ports---------------
output q;
reg q;
always @ ( posedge clk)
if (~reset) begin
q <= 1'b0;
end else begin
q <= d;
end
endmodule
// And gate model based at Gate level abstraction
module and(input x,input y,output o);
wire w;
// Two instantiations of the module NAND
nand U1(w,x, y);
nand U2(o, w, w);
endmodule
// Gate modeled at Cell-level Abstraction
primitive udp_and(
a, // declare three ports
b,
c
);
output a; // Outputs
input b,c; // Inputs
// UDP function code here
// A = B & C;
table
// B C : A
1 1 : 1;
0 1 : 0;
1 0 : 0;
0 0 : 0;
endtable
endprimitive
Il existe trois principaux cas d'utilisation pour Verilog. Ils déterminent la structure du code et son interprétation et déterminent également les ensembles d'outils utilisés. Les trois applications sont nécessaires à la mise en œuvre réussie de toute conception Verilog.
- Conception physique / back-end
Ici, Verilog est principalement utilisé pour voir la conception comme une matrice de portes d'interconnexion mettant en œuvre une conception logique. RTL / logic / Design passe de différentes étapes, de la synthèse -> placement -> à la construction de l’horloge -> au routage -> DRC -> LVS -> à la sortie de bande. Les étapes et les séquences précises varient en fonction de la nature exacte de la mise en œuvre. - Simulation
Dans ce cas d'utilisation, l'objectif principal est de générer des vecteurs de test pour valider la conception conformément à la spécification. Le code écrit dans ce cas d'utilisation n'a pas besoin d'être synthétisable et reste dans la sphère de vérification. Le code ici ressemble davantage à des structures logicielles génériques comme les boucles for / while / do, etc. - Conception
La conception implique la mise en œuvre de la spécification d'un circuit généralement au niveau d'abstraction RTL. Le code Verilog est alors donné pour la vérification et le code entièrement vérifié est donné pour l'implémentation physique. Le code est écrit en utilisant uniquement les constructions synthétisables de Verilog. Certains styles de codage RTL peuvent provoquer une non-concordance entre la simulation et la synthèse, et il faut veiller à les éviter.
Il existe deux principaux flux de mise en œuvre. Ils affecteront également la manière dont le code Verilog est écrit et implémenté. Certains styles de codage et certaines structures conviennent mieux dans un flux que dans l'autre.
- ASIC Flow (circuit intégré spécifique à l'application)
- Flux FPGA (matrice de portes programmable sur site) - inclut les FPGA et les CPLD
Bonjour le monde
Cet exemple utilise le compilateur icarus verilog.
Étape 1: Créez un fichier appelé hello.v
module myModule();
initial
begin
$display("Hello World!"); // This will display a message
$finish ; // This causes the simulation to end. Without, it would go on..and on.
end
endmodule
Étape 2. Nous compilons le fichier .v en utilisant icarus:
>iverilog -o hello.vvp hello.v
L'option -o attribue un nom au fichier d'objet de sortie. Sans ce commutateur, le fichier de sortie serait appelé a.out. Hello.v indique le fichier source à compiler. Il ne devrait y avoir pratiquement aucune sortie lorsque vous compilez ce code source, sauf s'il y a des erreurs.
Étape 3. Vous êtes prêt à simuler ce programme Hello World verilog. Pour ce faire, invoquer en tant que tel:
>vvp hello.vvp
Hello World!
>
Installation du compilateur Icarus Verilog pour Mac OSX Sierra
- Installez Xcode depuis l'App Store.
- Installer les outils de développement Xcode
> xcode-select --install
Cela fournira des outils de ligne de commande de base tels que gcc
et make
- Installer les ports Mac
https://www.macports.org/install.php
Le package d'installation OSX Sierra fournira une méthode open-source d'installation et de mise à niveau de logiciels supplémentaires sur la plate-forme Mac. Pensez yum
ou apt-get
pour le Mac.
- Installer icarus en utilisant les ports Mac
> sudo port install iverilog
- Vérifier l'installation à partir de la ligne de commande
$ iverilog
iverilog: no source files.
Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]
[-g1995|-g2001|-g2005] [-g<feature>]
[-D macro[=defn]] [-I includedir] [-M depfile] [-m module]
[-N file] [-o filename] [-p flag=value]
[-s topmodule] [-t target] [-T min|typ|max]
[-W class] [-y dir] [-Y suf] source_file(s)
See the man page for details.
$
Vous êtes maintenant prêt à compiler et à simuler votre premier fichier Verilog sur le Mac.
Installer GTKWave pour l'affichage graphique des données de simulation sur Mac OSx Sierra
GTKWave est un logiciel de visualisation graphique complet prenant en charge plusieurs normes de stockage de données graphiques, mais il prend également en charge le format VCD, qui est le format que vvp
affichera. Donc, pour ramasser GTKWave, vous avez quelques options
- Allez sur http://gtkwave.sourceforge.net/gtkwave.zip et téléchargez-le. Cette version est généralement la plus récente.
- Si vous avez installé MacPorts ( https://www.macports.org/ ), lancez simplement
sudo port install gtkwave
. Cela voudra probablement installer sur les dépendances à. Notez que cette méthode vous donnera généralement une version plus ancienne. Si vous ne disposez pas de MacPorts, il existe un exemple de configuration de l'installation pour ce faire sur cette page. Oui! Vous aurez besoin de tous les outils de développement xcode, car ces méthodes vous "construiront" une source GTKWave.
Une fois l'installation terminée, vous pouvez être invité à sélectionner une version python. J'avais déjà installé 2.7.10 et je n'ai donc jamais "sélectionné" un nouveau.
À ce stade, vous pouvez démarrer gtkwave depuis la ligne de commande avec gtkwave
. Au démarrage, vous pouvez être invité à installer ou mettre à jour XQuarts. Faites-le Dans mon cas, XQuarts 2.7.11 est installé.
Note: J'ai eu besoin de redémarrer pour obtenir XQuarts correctement, puis j'ai tapé à nouveau gtkwave
et l'application apparaît.
Dans l'exemple suivant, je créerai deux fichiers indépendants, un banc d'essai et un module à tester, et nous utiliserons gtkwave pour visualiser la conception.
Utiliser Icarus Verilog et GTKWaves pour simuler et visualiser graphiquement une conception
Cet exemple utilise Icarus et GTKWave. Les instructions d'installation de ces outils sur OSx sont fournies ailleurs sur cette page.
Commençons par la conception du module. Ce module est un affichage BCD vers 7 segments. J'ai codé le design de manière obtuse simplement pour nous donner quelque chose qui se casse facilement et nous pouvons passer quelque temps à réparer graphiquement. Nous avons donc une horloge, une réinitialisation, une entrée de 4 données représentant une valeur de BCD et une sortie de 7 bits représentant l’affichage à sept segments. Créez un fichier nommé bcd_to_7seg.v et placez-y la source ci-dessous.
module bcd_to_7seg (
input clk,
input reset,
input [3:0] bcd,
output [6:0] seven_seg_display
);
parameter TP = 1;
reg seg_a;
reg seg_b;
reg seg_c;
reg seg_d;
reg seg_e;
reg seg_f;
reg seg_g;
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
seg_a <= #TP 1'b0;
seg_b <= #TP 1'b0;
seg_c <= #TP 1'b0;
seg_d <= #TP 1'b0;
seg_e <= #TP 1'b0;
seg_f <= #TP 1'b0;
seg_g <= #TP 1'b0;
end
else
begin
seg_a <= #TP ~(bcd == 4'h1 || bcd == 4'h4);
seg_b <= #TP bcd < 4'h5 || bcd > 6;
seg_c <= #TP bcd != 2;
seg_d <= #TP bcd == 0 || bcd[3:1] == 3'b001 || bcd == 5 || bcd == 6 || bcd == 8;
seg_e <= #TP bcd == 0 || bcd == 2 || bcd == 6 || bcd == 8;
seg_f <= #TP bcd == 0 || bcd == 4 || bcd == 5 || bcd == 6 || bcd > 7;
seg_g <= #TP (bcd > 1 && bcd < 7) || (bcd > 7);
end
end
assign seven_seg_display = {seg_g,seg_f,seg_e,seg_d,seg_c,seg_b,seg_a};
endmodule
Ensuite, nous avons besoin d'un test pour vérifier si ce module fonctionne correctement. La déclaration de cas dans le banc d’essai est en fait plus facile à lire à mon avis et plus claire sur ce qu’elle fait. Mais je n'ai pas voulu mettre la même déclaration de cas dans la conception ET dans le test. C'est une mauvaise pratique. Deux modèles indépendants sont plutôt utilisés pour valider les uns les autres.
Avec le code ci-dessous, vous remarquerez deux lignes $dumpfile("testbench.vcd");
et $dumpvars(0,testbench);
. Ces lignes sont ce qui crée le fichier de sortie VCD qui sera utilisé pour effectuer une analyse graphique de la conception. Si vous les omettez, vous ne recevrez pas de fichier VCD. Créez un fichier appelé testbench.v et placez-y la source ci-dessous.
`timescale 1ns/100ps
module testbench;
reg clk;
reg reset;
reg [31:0] ii;
reg [31:0] error_count;
reg [3:0] bcd;
wire [6:0] seven_seg_display;
parameter TP = 1;
parameter CLK_HALF_PERIOD = 5;
// assign clk = #CLK_HALF_PERIOD ~clk; // Create a clock with a period of ten ns
initial
begin
clk = 0;
#5;
forever clk = #( CLK_HALF_PERIOD ) ~clk;
end
initial
begin
$dumpfile("testbench.vcd");
$dumpvars(0,testbench);
// clk = #CLK_HALF_PERIOD ~clk;
$display("%0t, Reseting system", $time);
error_count = 0;
bcd = 4'h0;
reset = #TP 1'b1;
repeat (30) @ (posedge clk);
reset = #TP 1'b0;
repeat (30) @ (posedge clk);
$display("%0t, Begin BCD test", $time); // This displays a message
for (ii = 0; ii < 10; ii = ii + 1)
begin
repeat (1) @ (posedge clk);
bcd = ii[3:0];
repeat (1) @ (posedge clk);
if (seven_seg_display !== seven_seg_prediction(bcd))
begin
$display("%0t, ERROR: For BCD %d, module output 0b%07b does not match prediction logic value of 0b%07b.",$time,bcd, seven_seg_display,seven_seg_prediction(bcd));
error_count = error_count + 1;
end
end
$display("%0t, Test Complete with %d errors", $time, error_count);
$display("%0t, Test %s", $time, ~|error_count ? "pass." : "fail.");
$finish ; // This causes the simulation to end.
end
parameter SEG_A = 7'b0000001;
parameter SEG_B = 7'b0000010;
parameter SEG_C = 7'b0000100;
parameter SEG_D = 7'b0001000;
parameter SEG_E = 7'b0010000;
parameter SEG_F = 7'b0100000;
parameter SEG_G = 7'b1000000;
function [6:0] seven_seg_prediction;
input [3:0] bcd_in;
// +--- A ---+
// | |
// F B
// | |
// +--- G ---+
// | |
// E C
// | |
// +--- D ---+
begin
case (bcd_in)
4'h0: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
4'h1: seven_seg_prediction = SEG_B | SEG_C;
4'h2: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_E | SEG_D;
4'h3: seven_seg_prediction = SEG_A | SEG_B | SEG_G | SEG_C | SEG_D;
4'h4: seven_seg_prediction = SEG_F | SEG_G | SEG_B | SEG_C;
4'h5: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_C | SEG_D;
4'h6: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_E | SEG_C | SEG_D;
4'h7: seven_seg_prediction = SEG_A | SEG_B | SEG_C;
4'h8: seven_seg_prediction = SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G;
4'h9: seven_seg_prediction = SEG_A | SEG_F | SEG_G | SEG_B | SEG_C;
default: seven_seg_prediction = 7'h0;
endcase
end
endfunction
bcd_to_7seg u0_bcd_to_7seg (
.clk (clk),
.reset (reset),
.bcd (bcd),
.seven_seg_display (seven_seg_display)
);
endmodule
Maintenant que nous avons deux fichiers, un testbench.v et un bcd_to_7seg.v, nous devons compiler, élaborer en utilisant Icarus. Pour faire ça:
$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v
Ensuite, nous devons simuler
$ vvp testbench.vvp
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
8000, Test Complete with 0 errors
8000, Test pass.
À ce stade, si vous souhaitez valider le fichier en cours de test, allez dans le fichier bcd_2_7seg.v et déplacez une partie de la logique et répétez ces deux premières étapes.
Par exemple, je change la ligne seg_c <= #TP bcd != 2;
seg_c <= #TP bcd != 4;
. Recompiler et simuler effectue les opérations suivantes:
$ iverilog -o testbench.vvp testbench.v bcd_to_7seg.v
$ vvp testbench.vvp
LXT2 info: dumpfile testbench.vcd opened for output.
0, Reseting system
6000, Begin BCD test
6600, ERROR: For BCD 2, module output 0b1011111 does not match prediction logic value of 0b1011011.
7000, ERROR: For BCD 4, module output 0b1100010 does not match prediction logic value of 0b1100110.
8000, Test Complete with 2 errors
8000, Test fail.
$
Alors maintenant, permet de visualiser la simulation en utilisant GTKWave. Depuis la ligne de commande, émettez un
gtkwave testbench.vcd &
Lorsque la fenêtre GTKWave apparaît, vous verrez dans le coin supérieur gauche le nom du module testbench. Cliquez dessus. Cela révélera les sous-modules, tâches et fonctions associés à ce fichier. Les fils et les registres apparaîtront également dans la zone inférieure gauche.
Faites maintenant glisser, clk, bcd, error_count et seven_seg_display dans la zone de signal située à côté de la fenêtre de forme d'onde. Les signaux vont maintenant être tracés. Error_count vous montrera quelle entrée BCD particulière a généré la mauvaise sortie seven_seg_display.
Vous êtes maintenant prêt à dépanner graphiquement un bug de Verilog.