Menu

Verilog $dumpfile e $dumpvars: Produzindo formas de onda VCD

Como adicionar saída de forma de onda VCD a um testbench - $dumpfile, $dumpvars, seleção de escopo e como visualizar o arquivo resultante no GTKWave ou no editor do navegador.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

A forma de onda que você de fato quer

$display imprime texto. Está bem para uma verificação rápida de sanidade, mas no momento em que você está debugando um contador com problema de timing ou uma máquina de estado que travou, você quer uma imagem: sinais desenhados como tensões ao longo do tempo, roláveis, com zoom, com um cursor que você pode soltar em qualquer transição.

Essa imagem é um arquivo VCD - "value change dump", um formato de texto que o IEEE padronizou na spec original do Verilog. Cada simulador moderno consegue escrever um; cada visualizador de forma de onda moderno consegue ler um. O custo de produzir um é duas linhas no seu testbench.

As duas linhas

Dentro de um bloco initial - geralmente o mesmo que segura seu estímulo - adicione:

$dumpfile("dump.vcd");
$dumpvars(0, test);
  • $dumpfile nomeia o arquivo de saída. Passe qualquer caminho; se não tem diretório, cai no diretório de trabalho do simulador.
  • $dumpvars(0, test) diz "registre cada sinal no escopo test e em cada sub-escopo, recursivamente, com profundidade ilimitada".

Esse é o setup todo. Rode a simulação e você terá um dump.vcd que pode abrir no GTKWave ou na aba Waveform do editor do navegador.

Um exemplo completo

Execute. A aba Waveform agora mostra três sinais - clk, reset, count - desenhados ao longo de todo o tempo de simulação. Você pode soltar um cursor em qualquer ponto e ler os valores dos sinais naquele tempo. Pode dar zoom arrastando para inspecionar um único ciclo de clock.

O que o primeiro argumento de $dumpvars faz

$dumpvars(depth, scope) caminha por scope e cada subinstância que ele contém, registrando sinais até depth níveis para dentro. Os valores de profundidade:

  • 0 - ilimitado. Cada sinal em scope e em cada submódulo aninhado é registrado.
  • 1 - só sinais declarados diretamente em scope. Submódulos não são registrados.
  • 2 - scope mais um nível de submódulo.
  • N - scope mais N-1 níveis de submódulos.

Na prática, $dumpvars(0, test) é o que quase todo testbench usa. Capturar tudo é barato (VCDs só armazenam transições, não estados estáveis) e você não quer descobrir no meio do debug que o sinal que precisa não foi dumpado.

Se você tem um design realmente grande e o VCD é grande demais, pode dumpar seletivamente:

$dumpvars(0, dut.inner_module);     // so o submodule interessante
$dumpvars(0, dut.regs);             // so o register file

Você pode chamar $dumpvars múltiplas vezes para acumular escopos.

Dumpando sinais específicos

$dumpvars também pode pegar uma lista de sinais específicos em vez de um escopo inteiro:

$dumpvars(0, test.clk, test.reset, dut.count);

Isso registra só esses três sinais. Útil quando o design é enorme e você só se importa com um punhado de sinais. Para designs pequenos, dumpar tudo é mais simples.

Controlando o dump no meio da simulação

Mais duas tasks parceiras de $dumpvars:

  • $dumpoff - pausa o dumping. Nenhuma mudança subsequente entra no VCD.
  • $dumpon - retoma o dumping.
initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, test);

    // ... regiao interessante ...

    #1000 $dumpoff;
    // ... longa regiao chata que nao queremos no VCD ...
    #5000 $dumpon;

    // ... outra regiao interessante ...
end

É assim que você pula a parte chata "rodar por um milhão de ciclos" de um teste longo sem produzir um arquivo VCD de 5GB.

Visualizando o resultado

Duas formas principais:

No editor do navegador

O editor desta página renderiza VCDs inline. Rode a simulação; troque para a aba Waveform; os sinais aparecem com a hierarquia à esquerda e um cursor arrastável à direita. Clique em qualquer lugar em um traço para soltar o cursor; ele mostra os valores dos sinais naquele tempo como pílulas ao lado de cada nome de sinal.

No GTKWave

Se você rodou a simulação localmente (iverilog -o sim test.v depois vvp sim), abra o VCD resultante com:

gtkwave dump.vcd

GTKWave carrega o arquivo, apresenta a árvore de escopo à esquerda e espera você arrastar sinais para a área de forma de onda à direita. Clique com o botão direito em um sinal multi-bit para mudar o formato de exibição (binário, hex, decimal, analógico). Use a caixa de busca embaixo para pular para tempos ou transições de sinal específicas.

Padrões comuns

Um pequeno helper de testbench

A maioria dos arquivos de testbench começa com esse bloco exato. Você pode mantê-lo curto combinando tudo em um initial:

initial begin
    $dumpfile("dump.vcd");
    $dumpvars(0, test);

    // ... estimulo ...

    $finish;
end

Dumping condicional

Em um ambiente de teste onde você só quer saída VCD para testes que falham:

initial begin
    if (DUMP_VCD) begin
        $dumpfile("dump.vcd");
        $dumpvars(0, test);
    end
    // ... estimulo ...
end

DUMP_VCD seria um parameter que você seta pela linha de comando ou define dependendo do modo de teste. Economiza espaço em disco em suítes de regressão.

Dumps de memória

Memórias (arrays unpacked) não são dumpadas por $dumpvars por padrão - podem ser enormes. Use $dumpvars(0, dut.memory) explicitamente se as quiser, ou $dumpmem em alguns simuladores.

Erros comuns

Arquivo VCD vazio. Você esqueceu $dumpfile ou $dumpvars, ou a simulação chamou $finish antes que algum sinal mudasse. Rode por pelo menos algumas unidades de tempo depois do setup.

Sinais ausentes da forma de onda. O escopo que você passou não os incluiu. $dumpvars(0, dut) registra apenas o que está dentro de dut; se seu testbench aciona sinais no nível test, esses não vão aparecer. Sempre dumpe a partir do escopo do testbench: $dumpvars(0, test).

Arquivo VCD enorme. Uma simulação longa com sinais largos mudando rapidamente produz muitas linhas de VCD. Três correções: dumpe um escopo mais estreito, use $dumpoff/$dumpon em torno das partes chatas, ou troque para um formato mais compacto como FST (que tanto iverilog quanto GTKWave suportam com flags -fst).

O que vem a seguir

O último doc deste capítulo - Timescale and Delays - explica a diretiva \timescalee como#delay` de fato mapeia para tempo de relógio. Depois disso você completou os docs de ponta a ponta.

Perguntas frequentes

O que é um arquivo VCD em Verilog?

VCD significa Value Change Dump - um formato de texto para registrar cada transição de sinal durante a simulação. O simulador escreve o valor inicial de cada sinal no tempo 0, depois cada mudança com seu timestamp. Visualizadores de forma de onda como GTKWave leem o arquivo e o renderizam como um diagrama de timing gráfico pelo qual você pode rolar e dar zoom.

Como gero um arquivo VCD em Verilog?

Adicione duas system tasks dentro de um bloco initial no seu testbench: $dumpfile("dump.vcd"); nomeia o arquivo de saída, e $dumpvars(0, top_module); registra cada sinal em top_module e abaixo. Depois que a simulação termina, você terá um arquivo dump.vcd que pode abrir em qualquer visualizador de forma de onda.

O que $dumpvars(0, ...) significa em Verilog?

$dumpvars(depth, instance) registra sinais começando em instance e recursando depth níveis para dentro. $dumpvars(0, test) significa 'todos os sinais no escopo test e em cada sub-escopo, recursivamente' - profundidade 0 é especial e significa ilimitada. $dumpvars(1, test) registraria apenas sinais diretamente em test, não em submódulos instanciados.

Por que meu arquivo VCD está vazio em Verilog?

Três causas prováveis: você não chamou $dumpfile/$dumpvars de jeito nenhum; a simulação bateu $finish antes que qualquer sinal mudasse (rode por pelo menos algumas unidades de tempo depois da chamada de dump); ou o escopo que você passou para $dumpvars não combina com a hierarquia real. Uma sequência mínima funcionando é $dumpfile("dump.vcd"); $dumpvars(0, test); #10; $finish;.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR