Dominar $display en Verilog: Técnicas efectivas de depuración y control de visualización

目次

1. Introducción: La importancia y el propósito de “display” en Verilog

¿Qué significa “display” en Verilog?

En Verilog, $display es una tarea del sistema utilizada como herramienta para “mostrar” el estado interno de un diseño durante la simulación. Similar a printf de C, permite imprimir señales, valores de variables y cadenas en una terminal o consola, desempeñando un papel central en la depuración y la verificación funcional.

¿Por qué $display es esencial para el desarrollo en Verilog?

  • Mayor eficiencia en la depuración : En diseños de circuitos complejos, visualizar si las señales internas funcionan correctamente es crítico. Al usar $display, puedes comprobar al instante los valores de las señales de interés durante la simulación.
  • Visualización de la simulación : Cuando se siguen transiciones de valores en momentos específicos, los diagramas de ondas pueden ser insuficientes. Los registros de display proporcionan un medio fiable para indicar esos momentos precisos.
  • Útil también para documentación : Al transmitir la intención del diseño o las reglas de operación a otros ingenieros, insertar registros de display anotados puede mejorar la comprensión del código.

Propósito y estructura de este artículo

En este artículo explicaremos metodológicamente lo siguiente:

  1. Sintaxis básica y uso : Una introducción cuidadosa a la sintaxis fundamental y al uso de $display.
  2. Comparación con otras tareas del sistema : Organizaremos las diferencias entre tareas relacionadas con display como $write, $strobe y $monitor.
  3. Especificadores de formato y técnicas avanzadas : Se presentará el uso de especificadores de formato como %d, %b, %h, %s y técnicas especiales de display.
  4. Ejemplos prácticos de uso : Mostraremos usos concretos en bancos de pruebas y código con ejemplos, proporcionando know‑how de aplicación inmediata.
  5. Aplicaciones de control de display : Los casos de uso incluirán salida de hardware como LCD o control de monitor y la generación de texto/imagen.

Con esta estructura, tanto principiantes como usuarios intermedios podrán comprender adecuadamente $display en Verilog y aplicarlo en la práctica. En cada sección que sigue, avanzaremos con claridad usando ejemplos y diagramas siempre que sea posible.

2. Conceptos básicos de $display: Sintaxis, casos de uso y precauciones

Sintaxis básica de $display

Al usar $display en Verilog, la sintaxis básica es la siguiente.

$display("string or format specifiers", signal1, signal2, ...);
  • Parte de cadena : Escribe cualquier texto o especificador de formato (por ejemplo: %d, %b, %h).
  • Argumentos : Lista los nombres de señales o variables a imprimir en el formato correspondiente.

Ejemplo: Mostrar el recuento de reloj y valores de señales

$display("Time=%0t : clk=%b, reset=%b", $time, clk, reset);

En este ejemplo, se imprimen el tiempo de simulación y los valores de las señales de reloj/reset.

Casos de uso de $display

  1. Seguimiento del progreso de la simulación Al insertar $display en puntos específicos del diseño puedes verificar qué parte del código se ha ejecutado.
  2. Verificación de valores de señales Incluso cuando los visualizadores de ondas dificultan la comprensión intuitiva de ramas condicionales o transiciones de estado, la salida como texto facilita la comprensión.
  3. Mostrar mensajes condicionales Al combinarlo con sentencias if puedes registrar mensajes solo cuando se cumplen condiciones específicas. if (reset) $display("Reset asserted at %0t", $time);

Diferencia entre $display y $write

$display agrega automáticamente un salto de línea al final de la salida. En cambio, $write continúa la salida sin añadir un salto de línea.
Ejemplo:

$display("Hello");
$display("World");

Salida:

Hello
World
$write("Hello");
$write("World");

Salida:

HelloWorld

Si necesitas registros más claros línea por línea, usa $display. Cuando quieras formatear salidas en una sola línea, usa $write.

Precauciones

  1. Evita una salida excesiva Si usas $display en cada ciclo de reloj, los registros crecen mucho y la legibilidad disminuye. → Usa condicionamiento para reducir la salida.
  2. Utiliza la visualización de tiempo Mostrar $time o $realtime te permite capturar con precisión el momento de las operaciones.
  3. Tarea solo para simulación $display no puede usarse para síntesis (implementación FPGA/ASIC). Es estrictamente una herramienta de depuración solo para simulación.

3. Comparación de tareas del sistema de salida de registro: $display, $write, $strobe, $monitor

Verilog ofrece tareas del sistema más allá de $display para la salida. Sus diferentes casos de uso y temporización hacen que sea útil entender cómo utilizarlas de forma distinta.

$display: Tarea de visualización estándar

  • Características Añade automáticamente un salto de línea y registra una línea por invocación.
  • Caso de uso Se usa con mayor frecuencia como método básico de depuración; puedes llamarla en cualquier momento para una salida puntual.

$write: Visualización sin salto de línea

  • Características No agrega salto de línea y, por lo tanto, continúa la salida en la misma línea.
  • Caso de uso Útil cuando deseas mostrar varios valores uno al lado del otro.
  • Ejemplo $write("A=%d, ", a); $write("B=%dn", b); → Salida: A=5, B=10 .

$strobe: Salida al final del ciclo de simulación

  • Características Imprime los valores después de que se hayan completado todas las evaluaciones de simulación en el paso actual.
  • Caso de uso Útil para evitar condiciones de carrera (cuando múltiples señales cambian simultáneamente).
  • Ejemplo $strobe("Time=%0t, signal=%b", $time, sig); → Mientras $display puede mostrar valores intermedios, $strobe muestra valores estabilizados.

$monitor: Seguimiento automático de la salida

  • Características Emite automáticamente cuando cualquier señal monitoreada cambia.
  • Caso de uso Conveniente cuando deseas monitorear un conjunto de señales de forma continua.
  • Ejemplo $monitor("At %0t: a=%b, b=%b", $time, a, b); → Registra cuando a o b cambian.

Tabla resumida

TareaSalto de líneaMomento de la salidaCaso de uso principal
$displayCuando se invocaSalida básica de registro
$writeNoCuando se invocaFormateo lado a lado
$strobeAl final del ciclo de simulaciónVer valores estabilizados
$monitorAutomáticamente al cambiar la señalMonitoreo continuo

Consejos para un uso eficaz

  • Usa $display por defecto : Legible y fácil para principiantes.
  • Usa $write cuando quieras una salida combinada en una sola línea .
  • Usa $strobe cuando necesites valores estabilizados después de los cambios .
  • Usa $monitor cuando necesites monitoreo continuo de señales .

4. Especificadores de formato y técnicas avanzadas de visualización

Con tareas como $display o $write, puedes incluir “especificadores de formato” en cadenas para mostrar señales o variables en los formatos deseados. Como se asemeja al printf de C, utilizarlos correctamente según tu propósito mejora significativamente la eficiencia de depuración.

Especificadores de formato básicos

EspecificadorDescripciónEjemplo de salida
%bbinario1010
%ddecimal10
%hhexadecimalA
%ooctal12
%ccarácter ASCIIA
%scadenaHello
%ttiempo de simulación#100, etc.
%mnombre de la jerarquía del módulotop.u1.u2

Ejemplos prácticos

  1. Mostrar una señal en varios formatos reg [7:0] data = 8'b10101010; $display("data = %b (bin), %d (dec), %h (hex)", data, data, data); → Salida de ejemplo: data = 10101010 (bin), 170 (dec), AA (hex)
  2. Comprobar la jerarquía del módulo $display("Current module hierarchy is %m"); → Salida de ejemplo: Current module hierarchy is top.u1.counter
  3. Mostrar el tiempo de simulación $display("Time=%0t: clk=%b", $time, clk); → Salida de ejemplo: Time=100: clk=1

Técnicas avanzadas de visualización

  • Relleno con ceros y ancho de campo Puedes especificar relleno con ceros o ancho de campo como %0d. Ejemplo: $display("Count=%04d", count); → Salida: Count=0012
  • Distinción entre con signo y sin signo %d trata los valores como con signo, %u los trata como sin signo. Si un valor negativo no se muestra como se espera, revisa el especificador.
  • Formato de mensajes multilínea Usa \n para romper líneas y mejorar la legibilidad. Ejemplo: $display("Start of test\nSignal A=%b\nSignal B=%b", A, B);

Precauciones

  • Cuidado con el ancho de bits: Las señales de Verilog pueden tener diferentes anchos; usar %d puede provocar truncamiento o problemas de extensión de signo.
  • Manejo de valores indefinidos (X, Z): Si incluyes bits indefinidos, usar %b mostrará x o z directamente.

5. Ejemplos prácticos: Uso de $display en bancos de pruebas y módulos

A partir de aquí presentaremos usos efectivos de $display mediante ejemplos reales de código Verilog, abarcando desde lo básico en bancos de pruebas hasta el registro condicional de depuración.

Ejemplo básico: Salida en un banco de pruebas

Insertando $display en un banco de pruebas, puedes observar el comportamiento durante la simulación.

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

En este ejemplo, cada flanco ascendente del reloj genera una salida de reset y count. Como puedes inspeccionar los registros de texto así como las formas de onda, el seguimiento del comportamiento se vuelve más sencillo.

Ejemplo de display condicional

Combinando con sentencias if puedes registrar solo cuando se cumplen condiciones específicas.

always @(posedge clk) begin
  if (count == 4'd10) begin
    $display("Count has reached 10 (Time=%0t)", $time);
  end
end

→ Esto te permite evitar registros superfluos mientras localizas los eventos que te interesan.

Ejemplo de mensaje de depuración

Durante la depuración del diseño es útil detectar cuando una señal entra en un “estado inesperado”.

always @(posedge clk) begin
  if (count > 4'd12) begin
    $display("WARNING: count overflow detected! Time=%0t, value=%d", $time, count);
  end
end

→ Puedes descubrir rápidamente fallas de diseño o comportamientos inesperados en la simulación.

Monitoreo de múltiples señales simultáneamente

Al mostrar muchas señales, agruparlas en una sola línea usando $display hace que los registros sean más legibles.

$display("Time=%0t | clk=%b | reset=%b | A=%h | B=%h | SUM=%h",
         $time, clk, reset, A, B, SUM);

Resumen de consejos prácticos

  • Coloca $display en el banco de pruebas para visualizar el progreso
  • Usa ramas condicionales para refinar los registros
  • Genera mensajes de advertencia para detectar anomalías
  • Consolida múltiples señales en una línea para mejorar la legibilidad

6. Aplicaciones de control de pantalla (Pixel/Text/Image Display)

Hasta ahora, hemos presentado $display para registros de simulación. Mientras tanto, Verilog también se usa ampliamente para el “control de pantalla” en implementaciones de hardware (LCD, VGA, salida HDMI). En esta sección, introducimos brevemente cómo implementar la visualización en pantalla a nivel de hardware.

Concepto fundamental del control de pantalla

Para mostrar texto o imágenes en una pantalla, debes generar señales de video en lugar de usar simplemente $display.
Los señales de control típicas incluyen:

  • HSYNC (Sincronización horizontal): Señal que indica el final de cada línea
  • VSYNC (Sincronización vertical): Señal que indica el final de cada cuadro
  • Datos RGB: Señal que representa el color de cada píxel (p. ej., 8 bits × 3 = 24 bits de color)

En Verilog, controlas estas señales mediante contadores y máquinas de estados y las emites según el timing para lograr la “visualización en pantalla”.

Ejemplo 1: Barras de color


El ejemplo más básico es generar barras de color horizontalmente en una pantalla.

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

→ Esto produce barras de color rojo, verde y azul alineadas horizontalmente a lo largo de la pantalla.

Ejemplo 2: Visualización de Texto

Para la visualización de texto se prepara una ROM de fuentes y se convierte el patrón de puntos de cada carácter en píxeles.

// 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

→ Esto dibuja un carácter concreto (p. ej., “A”) en la pantalla.

Ejemplo 3: Visualización de Imágenes

Para mostrar una imagen se lee el dato de mapa de bits pre‑almacenado (ROM o memoria externa) y se convierte en salida de píxeles.

rgb <= image_rom[addr];  // Retrieve color data from ROM

En sistemas embebidos que usan FPGAs, este método permite mostrar íconos o logotipos simples.

Diferencia respecto a la depuración con $display

  • $display es salida de texto (solo simulación)
  • El control de pantalla es generación de señal de video (implementable en hardware)

Aunque sus propósitos difieren, los estudiantes de Verilog a menudo confunden ambos.

  • “Quiero verificar el comportamiento durante la simulación” → Usa $display
  • “Quiero enviar la salida a una pantalla real en FPGA” → Diseña lógica de señal de video

Expansión de Aplicaciones

  • En placas FPGA de aprendizaje, Verilog se usa frecuentemente para pantallas LED de 7 segmentos o pequeñas pantallas LCD.
  • Avanzando más, puedes crear sistemas que soporten salida VGA/HDMI para desarrollo de juegos o visualización de interfaces gráficas.
  • Combinando el conocimiento de $display con la lógica de control de pantalla puedes manejar la “visualización” tanto en simulación como en hardware real.

7. Uso Apropiado y Consejos Según Escenarios de Aplicación

Cuando hablamos de “display” en Verilog hay dos aspectos: las tareas $display solo para simulación, y el control de visualización en la implementación de hardware. Usar cada una de forma adecuada conduce a un desarrollo y depuración eficientes.

Uso en Simulación

  1. $display como registro de depuración
    • Salida de variables o señales críticas con $display para comprobar si tu diseño se comporta como se espera.
    • Verificar “valores bajo condiciones específicas” o “el contador alcanzando puntos” mediante registros es eficiente.
  2. Evitar salida excesiva
    • Emitir salida en cada ciclo de reloj inunda los registros y reduce la legibilidad. Limita las condiciones.
    • Ejemplo: if (state == ERROR) $display("Error occurred at %0t", $time);
  3. Diferenciar entre tareas
    • $monitor → Para señales que deseas observar continuamente
    • $strobe → Cuando necesitas emitir valores estabilizados
    • $write → Para salida horizontal formateada

Uso en Control de Visualización de Hardware

  1. Pantalla de 7 segmentos para aprendizaje
    • En proyectos de iniciación con FPGA, mostrar el valor de un contador en un LED de 7 segmentos es estándar.
    • Combínalo con la salida de simulación $display para profundizar la comprensión de visualización vs simulación.
  2. Control de monitor LCD o VGA
    • Usa ROM de fuentes o ROM de imágenes para mostrar texto o imágenes.
    • Al usar también $display en simulación puedes verificar doblemente que la generación de señal de video es correcta.
  3. Superposición de depuración en hardware
    • Puedes superponer “valor del contador”, “coordenadas”, “mensajes de depuración” en la salida de video real.
    • En desarrollo FPGA es común “convertir la pantalla en una herramienta de depuración”.

Consejos Prácticos

  • Seguir simulación → flujo de hardware Primero usa $display para verificar el comportamiento en simulación, luego pasa a la lógica de control de pantalla para la implementación en hardware.
  • Usar registros y formas de onda en conjunto Los registros de texto de $display indican “momento de ocurrencia del evento”, mientras que las formas de onda muestran “transiciones detalladas”. Usar ambos aumenta la precisión de depuración.
  • Unificar el formato de mensajes en el desarrollo en equipo Estandarizar el formato de mensaje de $display (prefijo, visualización de tiempo, etc.) facilita el análisis de registros cuando varias personas trabajan juntas.

Resumen

  • Las tareas tipo $display son herramientas de “observación” solo para simulación
  • El control de pantalla implica la implementación de hardware “método de visualización”
  • Al usar cada una apropiadamente y combinarlas puedes lograr un desarrollo eficiente

8. FAQ (Preguntas frecuentes)

Q1. ¿Cuál es la diferencia entre $display y $monitor?

R. $display muestra una vez en el momento en que se llama. En contraste, $monitor muestra automáticamente cada vez que cambia una señal registrada.

  • Para depuración puntual → $display
  • Para monitoreo continuo → $monitor

Q2. ¿Cuándo debo usar $strobe?

R. $strobe muestra el valor estabilizado al final de un ciclo de simulación. Por ejemplo, cuando varias señales cambian simultáneamente en el flanco de reloj, $display podría mostrar valores intermedios. En esos casos $strobe es conveniente para mostrar los valores finales.

Q3. ¿Cuál es el uso del especificador de formato %m?

R. %m muestra el nombre de la jerarquía del módulo actual. En diseños grandes, registrar “de qué jerarquía proviene el mensaje” facilita mucho el análisis.

$display("Current module: %m");

Ejemplo de salida:

Current module: top.u1.counter

Q4. Mis registros se volvieron enormes porque usé muchos $display. ¿Qué debo hacer?

R. Las siguientes medidas son efectivas:

  • Utilizar sentencias if para filtrar la salida
  • Mostrar solo detección de errores o eventos específicos
  • Usar $monitor para observar solo las señales mínimas requeridas
  • Exportar a un archivo de registro y aplicar herramientas de filtrado durante el análisis

Q5. ¿Puede $display usarse para síntesis (FPGA/ASIC)?

R. No. $display es estrictamente una tarea solo de simulación. Las herramientas de síntesis lo ignoran, por lo que no se refleja en el hardware real. Si deseas mostrar salida en hardware real debes diseñar con “LED de 7 segmentos”, “LCD”, “lógica de control VGA”, etc., en Verilog.

Q6. ¿Cómo muestro texto o imágenes en hardware real?

R. No mediante $display, sino generando señales de video.

  • Display de 7 segmentos → Para mostrar números o caracteres simples
  • VGA/LCD → Generar señales HSYNC, VSYNC, RGB y controlarlas
  • Texto → Usar ROM de fuentes y emitir patrones de puntos
  • Imágenes → Almacenar mapas de bits en ROM o memoria externa y emitir los píxeles correspondientemente

9. Conclusión y próximos pasos

Resumen de este artículo

En este artículo cubrimos “display” en Verilog desde los fundamentos hasta las aplicaciones. Los puntos clave incluyeron:

  1. Fundamentos de $display
    • Una tarea de simulación que muestra señales o variables, usable de forma similar al printf de C.
  2. Diferencias con tareas relacionadas
    • $write → Muestra sin salto de línea
    • $strobe → Emite valores estabilizados al final del ciclo de simulación
    • $monitor → Monitorea automáticamente los cambios de señal
  3. Uso de especificadores de formato
    • Al usar %b, %d, %h, %m, %t, puedes generar registros más claros y prácticos.
  4. Ejemplos prácticos
    • Inserta $display en los bancos de pruebas para monitorear el progreso.
    • Usa mensajes condicionales para habilitar una depuración eficiente.
  5. Aplicaciones en control de pantalla
    • $display es solo de simulación; la implementación en hardware usa HSYNC, VSYNC, RGB para emitir texto/imagen.
    • Desde aprender el display de 7 segmentos hasta el control avanzado de VGA/HDMI, son posibles ampliaciones.

Próximos pasos

  • Avanzar a SystemVerilog → En el lenguaje sucesor SystemVerilog puedes usar funciones de depuración más avanzadas (aserciones, $display mejorado, etc.).
  • Combinar con visor de formas de onda → Al combinar los registros $display y los datos de forma de onda puedes analizar tanto valores numéricos como transiciones, mejorando la precisión de la depuración.
  • Aprender la salida de pantalla de hardware → En un proyecto pequeño con una placa FPGA, prueba a generar salida en un display de 7 segmentos o LCD para experimentar la diferencia entre “visualización de simulación” y “control de pantalla de hardware”.
  • Aplicar en desarrollo en equipo → Al estandarizar el formato de los mensajes $display mejoras la eficiencia del análisis de registros en desarrollos con varias personas.

En conclusión

$display es más que una simple “salida de texto”. Es una herramienta poderosa para la depuración de simulaciones. Y cuando te adentras en el mundo del control de pantallas, puedes experimentar la alegría de mostrar gráficos en monitores reales mediante FPGA.
Espero que este artículo ayude a los estudiantes de Verilog a comprender claramente tanto la “depuración de simulación” como la “salida de pantalla de hardware”.