La forma de onda que realmente quieres
$display imprime texto. Eso está bien para una comprobación rápida, pero en el momento en que estás depurando un contador con un problema de timing o una máquina de estados que está atascada, quieres una imagen: señales dibujadas como voltajes a lo largo del tiempo, navegable, con zoom, con un cursor que puedes dejar caer sobre cualquier transición.
Esa imagen es un archivo VCD - "value change dump", un formato de texto que el IEEE estandarizó en la especificación original de Verilog. Cualquier simulador moderno puede escribir uno; cualquier visor de formas de onda moderno puede leerlo. El coste de producir uno son dos líneas en tu testbench.
Las dos líneas
Dentro de un bloque initial - normalmente el mismo que contiene tus estímulos - añade:
$dumpfile("dump.vcd");
$dumpvars(0, test);
$dumpfilenombra el archivo de salida. Pasa cualquier ruta; si no tiene directorio aterriza en el directorio de trabajo del simulador.$dumpvars(0, test)dice "registra cada señal en el scopetesty cada subscope, recursivamente, con profundidad ilimitada".
Esa es toda la configuración. Ejecuta la simulación y tendrás un dump.vcd que puedes abrir en GTKWave o en la pestaña Waveform del editor del navegador.
Un ejemplo completo
Ejecútalo. La pestaña Waveform ahora muestra tres señales - clk, reset, count - dibujadas a lo largo del tiempo de simulación completo. Puedes dejar caer un cursor en cualquier punto y leer los valores de señal en ese tiempo. Puedes arrastrar para hacer zoom e inspeccionar un único ciclo de reloj.
Qué hace el primer argumento de $dumpvars
$dumpvars(depth, scope) recorre scope y cada subinstancia que contiene, registrando señales hasta depth niveles de profundidad. Los valores de depth:
0- ilimitado. Cada señal enscopey cada submódulo anidado se registra.1- solo señales declaradas directamente enscope. Los submódulos no se registran.2-scopemás un nivel de submódulo.N-scopemás N-1 niveles de submódulos.
En la práctica, $dumpvars(0, test) es lo que usa casi cada testbench. Capturar todo es barato (los VCDs solo almacenan transiciones, no estados estables) y no quieres descubrir a mitad de depuración que la señal que necesitabas no se volcó.
Si tienes un diseño realmente grande y el VCD es demasiado grande, puedes volcar selectivamente:
$dumpvars(0, dut.inner_module); // just the interesting sub-module
$dumpvars(0, dut.regs); // just the register file
Puedes llamar a $dumpvars varias veces para acumular scopes.
Volcando señales específicas
$dumpvars también puede tomar una lista de señales específicas en vez de un scope entero:
$dumpvars(0, test.clk, test.reset, dut.count);
Esto registra solo esas tres señales. Útil cuando el diseño es enorme y solo te importan un puñado de señales. Para diseños pequeños, volcar todo es más simple.
Controlando el dump a mitad de simulación
Dos tareas más se emparejan con $dumpvars:
$dumpoff- pausa el dumping. No entran más cambios en el VCD.$dumpon- reanuda el dumping.
initial begin
$dumpfile("dump.vcd");
$dumpvars(0, test);
// ... interesting region ...
#1000 $dumpoff;
// ... long boring region we don't want in the VCD ...
#5000 $dumpon;
// ... another interesting region ...
end
Así es como te saltas la parte aburrida del "corriendo durante un millón de ciclos" de un test largo sin producir un archivo VCD de 5 GB.
Viendo el resultado
Dos formas principales:
En el editor del navegador
El editor de esta página renderiza VCDs inline. Ejecuta la simulación; cambia a la pestaña Waveform; las señales aparecen con su jerarquía a un lado y un cursor arrastrable al otro. Haz clic en cualquier traza para dejar caer el cursor; muestra los valores de señal en ese tiempo como pequeñas pastillas junto al nombre de cada señal.
En GTKWave
Si ejecutaste la simulación localmente (iverilog -o sim test.v luego vvp sim), abre el VCD resultante con:
gtkwave dump.vcd
GTKWave carga el archivo, presenta el árbol de scope a un lado y espera a que arrastres señales al área de forma de onda del otro lado. Haz clic derecho en una señal multibit para cambiar el formato de visualización (binario, hex, decimal, analógico). Usa la caja de búsqueda en la parte inferior para saltar a tiempos o transiciones de señal específicos.
Patrones comunes
Un pequeño helper de testbench
La mayoría de los archivos de testbench empiezan con este bloque exacto. Puedes mantenerlo corto combinando todo en un initial:
initial begin
$dumpfile("dump.vcd");
$dumpvars(0, test);
// ... stimulus ...
$finish;
end
Dumping condicional
En un entorno de test donde solo quieres salida VCD para tests que fallan:
initial begin
if (DUMP_VCD) begin
$dumpfile("dump.vcd");
$dumpvars(0, test);
end
// ... stimulus ...
end
DUMP_VCD sería un parameter que pones desde la línea de comandos o defines dependiendo del modo de test. Ahorra espacio de disco en suites de regresión.
Volcado de memorias
Las memorias (arrays no empaquetados) no las vuelca $dumpvars por defecto - pueden ser enormes. Usa $dumpvars(0, dut.memory) explícitamente si las quieres, o $dumpmem en algunos simuladores.
Errores comunes
Archivo VCD vacío. Olvidaste $dumpfile o $dumpvars, o la simulación llamó a $finish antes de que cambiara ninguna señal. Ejecuta al menos unas unidades de tiempo más allá de la configuración.
Faltan señales en la forma de onda. El scope que pasaste no las incluyó. $dumpvars(0, dut) registra solo lo que está dentro de dut; si tu testbench excita señales a nivel test, esas no aparecerán. Vuelca siempre desde el scope del testbench: $dumpvars(0, test).
El archivo VCD es enorme. Una simulación larga con señales anchas que cambian rápido produce muchas líneas VCD. Tres soluciones: volcar un scope más estrecho, usar $dumpoff/$dumpon alrededor de las partes aburridas, o cambiar a un formato más compacto como FST (que iverilog y GTKWave soportan con flags -fst).
Qué viene a continuación
El último doc de este capítulo - Timescale and Delays - explica la directiva \timescaley cómo#delay` mapea realmente a tiempo de reloj de pared. Después de eso has completado los docs de principio a fin.
Preguntas frecuentes
¿Qué es un archivo VCD en Verilog?
VCD significa Value Change Dump - un formato de texto para registrar cada transición de señal durante la simulación. El simulador escribe el valor inicial de cada señal en el tiempo 0, luego cada cambio con su timestamp. Visores de formas de onda como GTKWave leen el archivo y lo renderizan como un diagrama de timing gráfico que puedes desplazar y hacer zoom.
¿Cómo genero un archivo VCD en Verilog?
Añade dos tareas de sistema dentro de un bloque initial en tu testbench: $dumpfile("dump.vcd"); nombra el archivo de salida, y $dumpvars(0, top_module); registra cada señal en top_module y por debajo. Tras terminar la simulación, tendrás un archivo dump.vcd que puedes abrir en cualquier visor de formas de onda.
¿Qué significa $dumpvars(0, ...) en Verilog?
$dumpvars(depth, instance) registra señales empezando en instance y recursivamente bajando depth niveles. $dumpvars(0, test) significa 'todas las señales en el scope test y cada subscope, recursivamente' - profundidad 0 es especial y significa ilimitada. $dumpvars(1, test) registraría solo señales directamente en test, no en ningún submódulo instanciado.
¿Por qué mi archivo VCD está vacío en Verilog?
Tres causas probables: no llamaste a $dumpfile/$dumpvars; la simulación llegó a $finish antes de que cambiara cualquier señal (ejecuta al menos unas unidades de tiempo después de la llamada de dump); o el scope que pasaste a $dumpvars no coincide con la jerarquía real. Una secuencia mínima funcional es $dumpfile("dump.vcd"); $dumpvars(0, test); #10; $finish;.