Le waveform que tu veux vraiment
$display affiche du texte. C'est bien pour un check rapide, mais dès l'instant où tu débugges un compteur avec un problème de timing ou une machine à états bloquée, tu veux une image : les signaux dessinés comme des tensions au cours du temps, scrollable, zoomable, avec un curseur que tu peux poser sur n'importe quelle transition.
Cette image est un fichier VCD - « value change dump », un format texte que l'IEEE a standardisé dans la spec Verilog originale. Chaque simulateur moderne peut en écrire un ; chaque visualiseur de waveform moderne peut en lire un. Le coût pour en produire est de deux lignes dans ton testbench.
Les deux lignes
À l'intérieur d'un bloc initial - généralement le même qui tient ton stimulus - ajoute :
$dumpfile("dump.vcd");
$dumpvars(0, test);
$dumpfilenomme le fichier de sortie. Passe n'importe quel chemin ; s'il n'a pas de répertoire il atterrit dans le répertoire de travail du simulateur.$dumpvars(0, test)dit « enregistre chaque signal dans la portéetestet chaque sous-portée, récursivement, avec profondeur illimitée ».
C'est tout le setup. Lance la simulation et tu auras un dump.vcd que tu peux ouvrir dans GTKWave ou l'onglet Waveform de l'éditeur du navigateur.
Un exemple complet
Lance-le. L'onglet Waveform montre maintenant trois signaux - clk, reset, count - dessinés sur tout le temps de simulation. Tu peux poser un curseur sur n'importe quel point et lire les valeurs des signaux à ce moment. Tu peux drag-zoomer pour inspecter un seul cycle d'horloge.
Ce que fait le premier argument de $dumpvars
$dumpvars(depth, scope) parcourt scope et chaque sous-instance qu'il contient, enregistrant les signaux jusqu'à depth niveaux. Les valeurs de profondeur :
0- illimité. Chaque signal dansscopeet chaque sous-module imbriqué est enregistré.1- seulement les signaux déclarés directement dansscope. Les sous-modules ne sont pas enregistrés.2-scopeplus un niveau de sous-module.N-scopeplus N-1 niveaux de sous-modules.
En pratique, $dumpvars(0, test) est ce que presque tous les testbenches utilisent. Capturer tout est peu coûteux (les VCD ne stockent que les transitions, pas les états stables) et tu ne veux pas découvrir au milieu du debug que le signal dont tu as besoin n'a pas été dumpé.
Si tu as un design vraiment gros et que le VCD est trop gros, tu peux dumper sélectivement :
$dumpvars(0, dut.inner_module); // juste le sous-module intéressant
$dumpvars(0, dut.regs); // juste la banque de registres
Tu peux appeler $dumpvars plusieurs fois pour accumuler les portées.
Dumper des signaux spécifiques
$dumpvars peut aussi prendre une liste de signaux spécifiques au lieu d'une portée entière :
$dumpvars(0, test.clk, test.reset, dut.count);
Ça enregistre seulement ces trois signaux. Utile quand le design est énorme et que tu ne te soucies que d'une poignée de signaux. Pour les petits designs, dumper tout est plus simple.
Contrôler le dump en milieu de simulation
Deux tâches de plus s'associent à $dumpvars :
$dumpoff- pause le dump. Plus de changements n'entrent dans le VCD.$dumpon- reprend le dump.
initial begin
$dumpfile("dump.vcd");
$dumpvars(0, test);
// ... région intéressante ...
#1000 $dumpoff;
// ... longue région ennuyeuse qu'on ne veut pas dans le VCD ...
#5000 $dumpon;
// ... une autre région intéressante ...
end
C'est comme ça que tu sautes la partie ennuyeuse « tourne pendant un million de cycles » d'un long test sans produire un fichier VCD de 5 Go.
Voir le résultat
Deux façons principales :
Dans l'éditeur du navigateur
L'éditeur sur cette page rend les VCD inline. Lance la simulation ; passe à l'onglet Waveform ; les signaux apparaissent avec leur hiérarchie à gauche et un curseur draggable à droite. Clique n'importe où sur un trace pour poser le curseur ; il montre les valeurs des signaux à ce temps comme des petites pilules à côté de chaque nom de signal.
Dans GTKWave
Si tu as lancé la simulation en local (iverilog -o sim test.v puis vvp sim), ouvre le VCD résultant avec :
gtkwave dump.vcd
GTKWave charge le fichier, présente l'arbre de portée à gauche, et attend que tu drag-and-drop les signaux dans la zone waveform à droite. Clic-droit sur un signal multi-bits pour changer le format d'affichage (binaire, hex, décimal, analogique). Utilise la barre de recherche en bas pour sauter à des moments ou transitions de signaux spécifiques.
Motifs courants
Un mini helper de testbench
La plupart des fichiers de testbench commencent par ce bloc exact. Tu peux le garder court en combinant tout dans un seul initial :
initial begin
$dumpfile("dump.vcd");
$dumpvars(0, test);
// ... stimulus ...
$finish;
end
Dump conditionnel
Dans un environnement de test où tu ne veux la sortie VCD que pour les tests qui échouent :
initial begin
if (DUMP_VCD) begin
$dumpfile("dump.vcd");
$dumpvars(0, test);
end
// ... stimulus ...
end
DUMP_VCD serait un parameter que tu fixes depuis la ligne de commande ou que tu définis selon le mode de test. Économise de l'espace disque dans les suites de régression.
Dumps de mémoire
Les mémoires (tableaux non packés) ne sont pas dumpées par $dumpvars par défaut - elles peuvent être énormes. Utilise $dumpvars(0, dut.memory) explicitement si tu les veux, ou $dumpmem dans certains simulateurs.
Erreurs courantes
Fichier VCD vide. Tu as oublié $dumpfile ou $dumpvars, ou la simulation a appelé $finish avant qu'aucun signal ne change. Laisse tourner pour au moins quelques unités de temps après le setup.
Signaux manquants du waveform. La portée que tu as passée ne les incluait pas. $dumpvars(0, dut) n'enregistre que ce qui est dans dut ; si ton testbench pilote des signaux au niveau test, ils n'apparaîtront pas. Dumpe toujours depuis la portée testbench : $dumpvars(0, test).
Le fichier VCD est énorme. Une longue simulation avec des signaux larges qui changent rapidement produit beaucoup de lignes VCD. Trois corrections : dumpe une portée plus étroite, utilise $dumpoff/$dumpon autour des parties ennuyeuses, ou passe à un format plus compact comme FST (que iverilog et GTKWave supportent tous deux avec les flags -fst).
La suite
Le dernier document de ce chapitre - Timescale et délais - explique la directive `timescale et comment #delay se mappe en fait au temps horloge mural. Après ça tu as complété la documentation de bout en bout.
Questions fréquentes
Qu'est-ce qu'un fichier VCD en Verilog ?
VCD veut dire Value Change Dump - un format texte pour enregistrer chaque transition de signal pendant la simulation. Le simulateur écrit la valeur initiale de chaque signal au temps 0, puis chaque changement avec son timestamp. Les visualiseurs de waveform comme GTKWave lisent le fichier et le rendent comme un diagramme de timing graphique que tu peux scroller et zoomer.
Comment générer un fichier VCD en Verilog ?
Ajoute deux tâches système à l'intérieur d'un bloc initial dans ton testbench : $dumpfile("dump.vcd"); nomme le fichier de sortie, et $dumpvars(0, top_module); enregistre chaque signal dans top_module et en dessous. Après que la simulation se termine, tu auras un fichier dump.vcd que tu peux ouvrir dans n'importe quel visualiseur de waveform.
Que veut dire $dumpvars(0, ...) en Verilog ?
$dumpvars(depth, instance) enregistre les signaux à partir de instance et descend depth niveaux. $dumpvars(0, test) veut dire « tous les signaux dans la portée test et chaque sous-portée, récursivement » - profondeur 0 est spéciale et veut dire illimitée. $dumpvars(1, test) n'enregistrerait que les signaux directement dans test, pas dans les sous-modules instanciés.
Pourquoi mon fichier VCD est-il vide en Verilog ?
Trois causes probables : tu n'as pas appelé $dumpfile/$dumpvars du tout ; la simulation a atteint $finish avant qu'aucun signal ne change (laisse tourner pour au moins quelques unités de temps après l'appel de dump) ; ou la portée que tu as passée à $dumpvars ne correspond pas à la hiérarchie réelle. Une séquence minimale qui marche est $dumpfile("dump.vcd"); $dumpvars(0, test); #10; $finish;.