Dominando $display em Verilog: Técnicas Eficazes de Depuração e Controle de Exibição

目次

1. Introdução: A Importância e o Propósito de “display” no Verilog

O que Significa “display” no Verilog?

No Verilog, $display é uma tarefa de sistema usada como ferramenta para “exibir” o estado interno de um design durante a simulação. Semelhante ao printf da linguagem C, permite que você envie sinais, valores de variáveis e strings para um terminal ou console—desempenhando um papel central na depuração e verificação funcional.

Por que $display é Essencial para o Desenvolvimento em Verilog?

  • Eficiência de depuração aprimorada : Em projetos de circuitos complexos, visualizar se os sinais internos estão funcionando corretamente é crítico. Ao usar $display, você pode verificar instantaneamente os valores dos sinais de interesse durante a simulação.
  • Visualização da simulação : Ao rastrear transições de valores em pontos específicos no tempo, as formas de onda podem ser insuficientes. Os logs de exibição fornecem um meio confiável de indicar esses momentos precisos.
  • Útil também para documentação : Ao transmitir a intenção do design ou regras operacionais para outros engenheiros, inserir logs de exibição anotados pode melhorar a compreensão do código.

Propósito e Estrutura deste Artigo

Neste artigo, explicaremos metodicamente o seguinte:
  1. Sintaxe básica e uso : Uma introdução cuidadosa à sintaxe fundamental e ao uso de $display.
  2. Comparação com outras tarefas de sistema : Organizaremos as diferenças entre tarefas relacionadas a exibição, como $write, $strobe e $monitor.
  3. Especificadores de formato e técnicas avançadas de uso : Serão introduzidos o uso de especificadores de formato como %d, %b, %h, %s e técnicas especiais de exibição.
  4. Exemplos práticos de uso : Mostraremos usos concretos em test benches e código com exemplos, fornecendo know-how imediatamente aplicável.
  5. Aplicações de controle de exibição : Casos de uso de exemplo incluirão saída de hardware como controle de LCD ou monitor e exibição de texto/imagem.
Com esta estrutura, tanto iniciantes quanto usuários intermediários podem compreender adequadamente o $display no Verilog e aplicá‑lo na prática. Em cada seção a seguir, avançaremos de forma clara usando exemplos e diagramas sempre que possível.

2. Conceitos Básicos de $display: Sintaxe, Casos de Uso e Precauções

Sintaxe Básica de $display

Ao usar $display no Verilog, a sintaxe básica é a seguinte.
$display("string or format specifiers", signal1, signal2, ...);
  • Porção de string : Escreva qualquer texto ou especificadores de formato (por exemplo: %d, %b, %h).
  • Argumentos : Liste nomes de sinais ou variáveis a serem exibidos no formato correspondente.
Exemplo: Exibindo contagem de clock e valores de sinais
$display("Time=%0t : clk=%b, reset=%b", $time, clk, reset);
Neste exemplo, o tempo de simulação e os valores dos sinais de clock/reset são exibidos.

Casos de Uso do $display

  1. Acompanhar o progresso da simulação Ao inserir $display em pontos específicos do seu design, você pode verificar qual parte do código a execução alcançou.
  2. Verificação de valores de sinais Mesmo quando visualizadores de forma de onda dificultam a compreensão intuitiva de ramificações condicionais ou transições de estado, a saída como texto facilita a compreensão.
  3. Exibição condicional de mensagens Ao combinar com instruções if, você pode registrar mensagens somente quando condições específicas são atendidas. if (reset) $display("Reset asserted at %0t", $time);

Diferença entre $display e $write

$display adiciona automaticamente uma quebra de linha ao final da saída. Por outro lado, $write continua a saída sem acrescentar uma quebra de linha. Exemplo:
$display("Hello");
$display("World");
Saída:
Hello
World
$write("Hello");
$write("World");
Saída:
HelloWorld
Se precisar de logs linha a linha mais claros, use $display. Quando quiser formatar saídas em uma única linha, use $write.

Precauções

  1. Evite saída excessiva Se você usar $display a cada ciclo de relógio, os logs crescem muito e a legibilidade diminui. → Use condicionamento para reduzir a saída.
  2. Utilize a exibição de tempo Exibir $time ou $realtime permite capturar com precisão o tempo das operações.
  3. Tarefa apenas para simulação $display não pode ser usado para síntese (implementação em FPGA/ASIC). É estritamente uma ferramenta de depuração para simulação.

3. Comparando Tarefas de Sistema de Saída de Log: $display, $write, $strobe, $monitor

Verilog oferece tarefas de sistema além de $display para saída. Seus diferentes casos de uso e temporizações tornam eficiente entender como utilizá‑las de forma distinta.

$display: Tarefa de Exibição Padrão

  • Características Adiciona automaticamente uma nova linha e registra uma linha por invocação.
  • Caso de uso Mais comumente usada como método básico de depuração; pode ser chamada a qualquer momento para saída pontual.

$write: Exibição Sem Nova Linha

  • Características Não acrescenta nova linha e, portanto, continua a saída na mesma linha.
  • Caso de uso Útil quando você deseja exibir vários valores lado a lado.
  • Exemplo $write("A=%d, ", a); $write("B=%dn", b); → Saída: A=5, B=10.

$strobe: Saída ao Final do Ciclo de Simulação

  • Características Imprime valores após todas as avaliações da simulação no passo atual terem sido concluídas.
  • Caso de uso Útil para evitar condições de corrida (quando múltiplos sinais mudam simultaneamente).
  • Exemplo $strobe("Time=%0t, signal=%b", $time, sig); → Enquanto $display pode mostrar valores intermediários, $strobe mostra valores estabilizados.

$monitor: Saída de Rastreamento Automático

  • Características Emite automaticamente quando qualquer sinal monitorado muda.
  • Caso de uso Conveniente quando você deseja monitorar continuamente um conjunto de sinais.
  • Exemplo $monitor("At %0t: a=%b, b=%b", $time, a, b); → Registra quando a ou b mudam.

Tabela Resumo

TarefaNova linhaTempo de SaídaPrincipal Caso de Uso
$displaySimQuando invocadoSaída de log básica
$writeNoQuando invocadoFormatação lado a lado
$strobeSimApós o ciclo de simulação terminarVerificar valores liquidados
$monitorSimAutomaticamente na mudança de sinalMonitoramento contínuo

Dicas para Uso Eficaz

  • Use $display por padrão : Legível e fácil para iniciantes.
  • Use $write quando quiser uma saída combinada em uma única linha .
  • Use $strobe quando precisar de valores estabilizados após mudanças .
  • Use $monitor quando precisar de monitoramento contínuo de sinais .

4. Especificadores de Formato e Técnicas Avançadas de Exibição

Com tarefas como $display ou $write, você pode incluir “especificadores de formato” nas strings para exibir sinais ou variáveis nos formatos desejados. Como se assemelha ao printf do C, usá‑los corretamente de acordo com seu objetivo aumenta significativamente a eficiência da depuração.

Especificadores de Formato Básicos

EspecificadorDescriçãoExemplo de Saída
%bbinário1010
%ddecimal10
%hhexadecimalA
%ooctal12
%ccaractere ASCIIA
%sstringHello
%tsimulation time#100
%mnome da hierarquia do módulotop.u1.u2

Exemplos Práticos

  1. Exibir um sinal em múltiplos formatos reg [7:0] data = 8'b10101010; $display("data = %b (bin), %d (dec), %h (hex)", data, data, data); → Exemplo de saída: data = 10101010 (bin), 170 (dec), AA (hex)
  2. Verificar hierarquia de módulo $display("Current module hierarchy is %m"); → Exemplo de saída: Current module hierarchy is top.u1.counter
  3. Exibir tempo de simulação $display("Time=%0t: clk=%b", $time, clk); → Exemplo de saída: Time=100: clk=1

Técnicas Avançadas de Exibição

  • Preenchimento com zeros e largura de campo Você pode especificar preenchimento com zeros ou largura de campo como %0d. Exemplo: $display("Count=%04d", count); → Saída: Count=0012
  • Distinção entre sinalizado e não‑sinalizado %d trata valores como assinados, %u trata como não‑assinados. Se um valor negativo não for exibido como esperado, ajuste o especificador.
  • Formatação de mensagens multilinha Use \n para quebrar linhas e melhorar a legibilidade. Exemplo: $display("Start of test\nSignal A=%b\nSignal B=%b", A, B);

Precauções

  • Atenção à largura de bits : Sinais Verilog podem ter larguras diferentes; usar %d pode causar truncamento ou extensão de sinal indesejada.
  • Manipulação de valores indefinidos (X, Z) : Se você incluir bits indefinidos, usar %b exibirá x ou z diretamente.

5. Exemplos Práticos: Usando $display em Bancos de Teste e Módulos

A partir daqui, apresentaremos usos eficazes de $display por meio de exemplos reais de código Verilog, cobrindo o básico de test benches até registro de depuração condicional.

Exemplo Básico: Saída em um Test Bench

Ao inserir $display em um test bench, você pode observar o comportamento durante a simulação.
module tb_counter;
  reg clk;
  reg reset;
  wire [3:0] count;

  // DUT (Device Under Test)
  counter uut (
    .clk(clk),
    .reset(reset),
    .count(count)
  );

  // Clock generation
  initial begin
    clk = 0;
    forever #5 clk = ~clk;  // invert every 5 units
  end

  // Test scenario
  initial begin
    reset = 1;
    #10 reset = 0;

    #50 $finish;
  end

  // Display state
  always @(posedge clk) begin
    $display("Time=%0t | reset=%b | count=%d", $time, reset, count);
  end
endmodule
Neste exemplo, cada borda de subida do clock aciona a saída de reset e count. Como você pode inspecionar logs de texto assim como formas de onda, rastrear o comportamento torna‑se mais fácil.

Exemplo de Display Condicional

Ao combinar com instruções if você pode registrar apenas quando condições específicas são atendidas.
always @(posedge clk) begin
  if (count == 4'd10) begin
    $display("Count has reached 10 (Time=%0t)", $time);
  end
end
→ Isso permite evitar logs supérfluos enquanto identifica os eventos que lhe interessam.

Exemplo de Mensagem de Depuração

Durante a depuração de design, é eficaz capturar quando um sinal entra em um “estado inesperado”.
always @(posedge clk) begin
  if (count > 4'd12) begin
    $display("WARNING: count overflow detected! Time=%0t, value=%d", $time, count);
  end
end
→ Você pode descobrir rapidamente falhas de design ou comportamentos inesperados na simulação.

Monitoramento de Múltiplos Sinais Juntos

Ao emitir muitos sinais, coletá‑los em uma única linha usando $display torna os logs mais legíveis.
$display("Time=%0t | clk=%b | reset=%b | A=%h | B=%h | SUM=%h",
         $time, clk, reset, A, B, SUM);

Resumo de Dicas Práticas

  • Coloque $display no test bench para visualizar o progresso
  • Use ramificações condicionais para refinar os logs
  • Gere mensagens de aviso para detectar anomalias
  • Consolide múltiplos sinais em uma linha para melhorar a legibilidade

6. Aplicações de Controle de Display (Pixel/Texto/Imagem)

Até agora, apresentamos $display para logs de simulação. Entretanto, Verilog também é amplamente usado para “controle de display” em implementações de hardware (saídas LCD, VGA, HDMI). Nesta seção, introduzimos brevemente como implementar a exibição em tela no nível de hardware.

Conceito Fundamental de Controle de Display

Para exibir texto ou imagens em uma tela, você deve gerar sinais de vídeo em vez de simplesmente usar $display. Os sinais de controle típicos incluem:
  • HSYNC (Sincronismo Horizontal) : Sinal que indica o fim de cada linha
  • VSYNC (Sincronismo Vertical) : Sinal que indica o fim de cada quadro
  • Dados RGB : Sinal que representa a cor de cada pixel (ex.: 8 bits × 3 = cor de 24 bits)
Em Verilog, você controla esses sinais via contadores e máquinas de estado e os emite com base no timing para realizar a “exibição em tela”.

Exemplo 1: Exibindo Barras de Cor

O exemplo mais básico é gerar barras de cor horizontalmente em um display.
always @(posedge clk) begin
  if (h_counter < 100)       rgb <= 24'hFF0000; // red
  else if (h_counter < 200)  rgb <= 24'h00FF00; // green
  else if (h_counter < 300)  rgb <= 24'h0000FF; // blue
  else                       rgb <= 24'h000000; // black
end
→ Isso resulta em barras de cor vermelha, verde e azul alinhadas horizontalmente na tela.

Exemplo 2: Exibição de Texto

Para exibir texto, você prepara uma ROM de fonte e converte o padrão de pontos de cada caractere em pixels.
// Referencing the pattern of 'A' from the font ROM and displaying
if (font_rom[char_code][y][x] == 1'b1)
    rgb <= 24'hFFFFFF;  // white for display
else
    rgb <= 24'h000000;  // black background
→ Isso desenha um caractere específico (ex.: “A”) na tela.

Exemplo 3: Exibição de Imagem

Para exibir uma imagem você lê dados de bitmap pré‑armazenados (ROM ou memória externa) e os converte em saída de pixels.
rgb <= image_rom[addr];  // Retrieve color data from ROM
Em sistemas embarcados que utilizam FPGAs, esse método permite exibir ícones ou logotipos simples.

Diferença em Relação ao Debug $display

  • $display é saída de texto (somente simulação)
  • Controle de exibição é geração de sinal de vídeo (implementável em hardware)
Embora seus propósitos sejam diferentes, aprendizes de Verilog costumam confundir os dois.
  • “Quero verificar o comportamento durante a simulação” → Use $display
  • “Quero enviar a saída para a tela real no FPGA” → Projete a lógica de sinal de vídeo

Expansão de Aplicações

  • Em placas de aprendizado de FPGA, Verilog é frequentemente usado para exibição em display de LED de 7 segmentos ou pequeno display LCD.
  • Avançando mais, você pode construir sistemas que suportam saída VGA/HDMI para desenvolvimento de jogos ou exibição de GUI.
  • Ao combinar o conhecimento de $display com a lógica de controle de exibição, você pode lidar com “display” tanto na simulação quanto no hardware real.

7. Uso Apropriado e Dicas Baseadas em Cenários de Aplicação

Quando falamos de “display” em Verilog há dois aspectos: as tarefas $display apenas para simulação, e o controle de exibição implementado em hardware. Usar cada uma adequadamente leva a um desenvolvimento e depuração mais eficientes.

Uso na Simulação

  1. $display como log de depuração
    • Saia variáveis ou sinais críticos com $display para verificar se seu design se comporta como esperado.
    • Verificar “valores sob condições específicas” ou “contador atingindo pontos” via logs é eficiente.
  2. Evite saída excessiva
    • Emitir a cada ciclo de clock inunda os logs e reduz a legibilidade. Restrinja as condições.
    • Exemplo: if (state == ERROR) $display("Error occured at %0t", $time);
  3. Diferencie entre as tarefas
    • $monitor → Para sinais que você deseja observar continuamente
    • $strobe → Quando precisar emitir valores estabilizados
    • $write → Para saída formatada horizontal

Uso no Controle de Exibição em Hardware

  1. Display de 7 segmentos para aprendizado
    • Em projetos iniciais de FPGA, exibir o valor de um contador em um LED de 7 segmentos é padrão.
    • Combine com a saída de simulação $display para aprofundar a compreensão de exibição vs. simulação.
  2. Controle de LCD ou monitor VGA
    • Use ROM de fonte ou ROM de imagem para exibir texto ou imagem.
    • Também usando $display na simulação, você pode verificar duplamente se a geração do sinal de vídeo está correta.
  3. Sobreposição de depuração em hardware
    • Você pode sobrepor “valor do contador”, “coordenadas”, “mensagens de depuração” na saída de vídeo real.
    • No desenvolvimento de FPGA é comum “transformar a tela em uma ferramenta de depuração”.

Dicas Práticas

  • Siga o fluxo simulação → hardware Primeiro use $display para validar o comportamento na simulação, depois passe para a lógica de controle de exibição para a implementação em hardware.
  • Use logs e formas de onda em conjunto Logs de texto de $display indicam “momento de ocorrência do evento”, enquanto formas de onda mostram “transições detalhadas”. Usar ambos aumenta a precisão da depuração.
  • Unifique o formato de mensagens em desenvolvimento de equipe Padronizar o formato das mensagens $display (prefixo, exibição de tempo, etc.) facilita a análise de logs quando várias pessoas trabalham juntas.

Resumo

  • Tarefas do tipo $display são ferramentas de “observação” apenas para simulação
  • Controle de exibição significa “método de exibição” implementado em hardware
  • Usando cada uma adequadamente e combinando-as, você pode alcançar um desenvolvimento eficiente

8. FAQ (Perguntas Frequentes)

Q1. Qual a diferença entre $display e $monitor?

A. $display emite uma vez no momento em que é chamado. Em contraste, $monitor emite automaticamente sempre que um sinal registrado muda.
  • Para depuração pontual → $display
  • Para monitoramento contínuo → $monitor

Q2. Quando devo usar $strobe?

A. $strobe exibe o valor estabilizado ao final de um ciclo de simulação. Por exemplo, quando vários sinais mudam simultaneamente na borda de um relógio, $display pode mostrar valores intermediários. Nesses casos $strobe é conveniente para mostrar os valores finais.

Q3. Qual é o uso do especificador de formato %m?

A. %m exibe o nome da hierarquia atual do módulo. Em projetos grandes, registrar “de qual hierarquia a mensagem veio” facilita muito a análise.
$display("Current module: %m");
Exemplo de saída:
Current module: top.u1.counter

Q4. Meus logs ficaram enormes porque usei muitos $display. O que devo fazer?

A. As medidas a seguir são eficazes:
  • Use instruções if para filtrar a saída
  • Emita apenas detecção de erros ou eventos específicos
  • Use $monitor para observar apenas os sinais mínimos necessários
  • Direcione a saída para um arquivo de log e aplique ferramentas de filtragem durante a análise

Q5. $display pode ser usado para síntese (FPGA/ASIC)?

A. Não. $display é estritamente uma tarefa apenas de simulação. Ferramentas de síntese o ignoram, portanto não aparece no hardware real. Se quiser exibir saída em hardware real, você deve projetar com “display de 7 segmentos”, “LCD”, “controle VGA”, etc., em Verilog.

Q6. Como exibir texto ou imagens no hardware real?

A. Não por meio de $display, mas gerando sinais de vídeo.
  • Display de 7 segmentos → Para exibir números ou caracteres simples
  • VGA/LCD → Gere sinais HSYNC, VSYNC, RGB e controle-os
  • Texto → Use ROM de fontes e envie padrões de pontos
  • Imagens → Armazene bitmaps em ROM ou memória externa e envie os pixels correspondentes

9. Conclusão & Próximos Passos

Resumo deste Artigo

Neste artigo abordamos “display” em Verilog, dos fundamentos às aplicações. Pontos principais incluíram:
  1. Fundamentos do $display
    • Uma tarefa de simulação que exibe sinais ou variáveis, utilizável de forma semelhante ao printf de C.
  2. Diferenças em relação a tarefas semelhantes
    • $write → Exibe sem nova linha
    • $strobe → Emite valores estabilizados ao final do ciclo de simulação
    • $monitor → Monitora automaticamente mudanças de sinal
  3. Uso de especificadores de formato
    • Usando %b, %d, %h, %m, %t, você pode gerar logs mais claros e práticos.
  4. Exemplos práticos
    • Insira $display em test benches para monitorar o progresso.
    • Use mensagens condicionais para habilitar depuração eficiente.
  5. Aplicações em controle de exibição
    • $display é apenas para simulação; a implementação em hardware usa HSYNC, VSYNC, RGB para exibir texto/imagem.
    • Do aprendizado de display de 7 segmentos ao controle avançado de VGA/HDMI, há muitas possibilidades de expansão.

Próximos Passos

  • Avançar para SystemVerilog → Na linguagem sucessora SystemVerilog você pode usar recursos de depuração mais avançados (asserts, $display aprimorado, etc.).
  • Combinar com visualizador de formas de onda → Ao combinar logs de $display e dados de forma de onda, você pode analisar tanto valores numéricos quanto transições, aumentando a precisão da depuração.
  • Aprender saída de exibição em hardware → Em um pequeno projeto com FPGA, experimente saída em 7‑segmentos ou LCD para vivenciar a diferença entre “exibição de simulação” e “controle de exibição em hardware”.
  • Aplicar em desenvolvimento em equipe → Padronizando o formato de mensagens de $display você melhora a eficiência da análise de logs em desenvolvimento colaborativo.

Em Conclusão

$display é mais que simples “saída de texto”. É uma ferramenta poderosa para depuração de simulação. E quando você avançar para o mundo do controle de exibição, poderá experimentar a alegria de mostrar gráficos em monitores reais via FPGA. Espero que este artigo ajude os aprendizes de Verilog a entender claramente tanto a “depuração de simulação” quanto a “saída de exibição em hardware”.