Menu

Verilog $dumpfile et $dumpvars : produire des waveforms VCD

Comment ajouter la sortie waveform VCD à un testbench - $dumpfile, $dumpvars, sélection de portée, et comment voir le fichier résultant dans GTKWave ou l'éditeur du navigateur.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

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);
  • $dumpfile nomme 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ée test et 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 dans scope et chaque sous-module imbriqué est enregistré.
  • 1 - seulement les signaux déclarés directement dans scope. Les sous-modules ne sont pas enregistrés.
  • 2 - scope plus un niveau de sous-module.
  • N - scope plus 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;.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER