Cómo construir un testbench de auto-comprobación en VHDL: Guía práctica
Un testbench de auto-comprobación es un programa VHDL que verifica la corrección de un dispositivo bajo prueba (DUT) sin inspección manual. Una vez ejecutado, informa automáticamente un estado OK o Failed, lo que lo convierte en una herramienta esencial para el desarrollo confiable de VHDL.
Cada módulo VHDL debería tener un testbench de auto-comprobación asociado. Esto asegura que cualquier cambio —ya sea en el propio DUT, un submódulo o una interfaz— no introduzca regresiones silenciosamente. Un testbench bien elaborado es la primera línea de defensa contra errores sutiles.
El dispositivo bajo prueba
Usaremos un DUT simple pero ilustrativo: un convertidor de código binario a Gray. A continuación se muestra la implementación RTL completa.
library ieee;
use ieee.std_logic_1164.all;
entity gray_converter is
port (
bin : in std_logic_vector;
gray : out std_logic_vector
);
end gray_converter;
architecture rtl of gray_converter is
begin
process(bin) is
begin
gray(gray'high) <= bin(bin'high);
for i in bin'high - 1 downto bin'low loop
gray(i) <= bin(i + 1) xor bin(i);
end loop;
end process;
end architecture;
El código Gray es un esquema de codificación binaria donde solo un bit cambia entre valores sucesivos, minimizando la probabilidad de error en comunicación serial y contadores digitales. La tabla siguiente muestra la correspondencia para valores de 4 bits.
| Decimal | Binario | Gray |
|---|---|---|
| 0 | 0000 | 0000 |
| 1 | 0001 | 0001 |
| 2 | 0010 | 0011 |
| 3 | 0011 | 0010 |
| 4 | 0100 | 0110 |
| 5 | 0101 | 0111 |
| 6 | 0110 | 0101 |
| 7 | 0111 | 0100 |
| 8 | 1000 | 1100 |
| 9 | 1001 | 1101 |
| 10 | 1010 | 1111 |
| 11 | 1011 | 1110 |
| 12 | 1100 | 1010 |
| 13 | 1101 | 1011 |
| 14 | 1110 | 1001 |
| 15 | 1111 | 1000 |
El esqueleto del testbench
A continuación se muestra un testbench mínimo que instancia el DUT y declara las señales necesarias. Observe la inclusión de std.env.finish, una característica de VHDL-2008 que termina la simulación limpiamente.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.env.finish;
entity gray_converter_tb is
end gray_converter_tb;
architecture sim of gray_converter_tb is
signal bin : std_logic_vector(3 downto 0) := (others => '0');
signal gray : std_logic_vector(3 downto 0);
DUT : entity work.gray_converter(rtl)
port map (
bin => bin,
gray => gray
);
end architecture;
Si compila este archivo en un simulador compatible con VHDL-2008 como ModelSim, es posible que deba establecer la versión del lenguaje del archivo a 2008. En ModelSim, haga clic derecho en el archivo, elija Properties → VHDL → Use 1076-2008.
Generando entradas exhaustivas
El siguiente paso es producir un barrido completo de todos los valores posibles de 4 bits. Una prueba exhaustiva es preferible porque garantiza que se ejercen todos los casos frontera.
PROC_SEQUENCE : process
begin
-- Iterar sobre cada valor de 4 bits
for i in 0 to 2**bin'length - 1 loop
bin <= std_logic_vector(to_unsigned(i, bin'length));
wait for 10 ns;
end loop;
-- Vuelta al estado inicial
bin <= (others => '0');
wait for 10 ns;
report "Test: OK";
finish;
end process;
El retraso de 10 ns es arbitrario; cualquier valor positivo basta porque el DUT es puramente combinacional. La sentencia finish final termina la simulación graciosamente.
Verificando la salida del DUT
Simplemente imprimir "Test: OK" carecería de sentido si la salida fuera incorrecta. Para imponer corrección, comparamos la salida Gray del DUT contra la propiedad fundamental del código Gray: las salidas sucesivas deben diferir en exactamente un bit.
PROC_CHECKER : process
variable prev : std_logic_vector(gray'range);
variable count : integer;
begin
wait on bin;
prev := gray;
-- Permitir que la lógica combinacional se resuelva
wait for 1 ns;
count := 0;
for i in gray'range loop
if gray(i) /= prev(i) then
count := count + 1;
end if;
end loop;
assert count = 1
report integer'image(count) & " bits changed, should have been 1"
severity failure;
end process;
Este proceso monitorea cambios en bin, captura la salida Gray anterior, espera la propagación, cuenta bits diferentes y afirma que el conteo es exactamente uno. Si la aserción falla, el simulador se detiene inmediatamente, impidiendo que aparezca el mensaje "Test: OK".
Ejecutando el testbench
En ModelSim, inicie la simulación y ejecute run -all. Una ejecución exitosa termina con:
VSIM 1> run -all # ** Note: Test: OK # Time: 170 ns Iteration: 0 Instance: /gray_converter_tb
Probando la robustez del testbench
Para confirmar que el verificador detecta fallos, introduzca temporalmente un error en el DUT —por ejemplo, fuerce gray(3) a cero.
process(bin) is
begin
gray(gray'high) <= bin(bin'high);
for i in bin'high - 1 downto bin'low loop
gray(i) <= bin(i + 1) xor bin(i);
end loop;
-- Emular un fallo stuck-at-zero
gray(3) <= '0';
end process;
Ejecutar el testbench ahora dispara la falla de aserción, mostrando el número exacto de bits que cambiaron:
VSIM 2> run -all # ** Failure: 0 bits changed, should have been 1 # Time: 81 ns Iteration: 0 Process: /gray_converter_tb/PROC_CHECKER # File: gray_converter_tb.vhd # Break in Process PROC_CHECKER at ray_converter_tb.vhd line 61
Comenzando con testbenches de auto-comprobación
Adopte el hábito de escribir testbenches de auto-comprobación para cada módulo VHDL. Ahorran tiempo al detectar regresiones temprano y proporcionan un registro claro de la intención del diseño. Aunque los testbenches no necesitan ser sintetizables, deben ser claros, mantenibles y usar los últimos constructos VHDL para legibilidad y eficiencia.
Para un aprendizaje más profundo, considere cursos avanzados que cubran el flujo de diseño completo —desde la especificación hasta el prototipo FPGA— mientras enfatizan prácticas de verificación rigurosas.
Actualizado 12 de octubre de 2020: He completado el curso de VHDL y FPGA. Haga clic en la imagen a continuación para obtener más información.
¡Lea más sobre el curso Dot Matrix VHDL y FPGA aquí!
Apertura:
Por decidir.
VHDL
- Creación de experiencias de usuario sin fricción: una guía de diseño UX
- Construya su primera plantilla AWS CloudFormation – Guía práctica
- Construyendo un Cloud Center of Excellence: estrategias para migración exitosa y customer success
- Construye un plan estratégico de adopción Cloud
- Construir Ciudades Inteligentes Centradas en el Humano: Un Plan Estratégico
- Creación de listas de cadenas en VHDL: Buenas prácticas y ejemplo
- Creación de un testbench dirigido por Tcl para un módulo VHDL de cerradura por código
- Finalizar elegantemente una simulación de testbench VHDL
- Implementación de un controlador PWM en VHDL: Diseño, simulación y demo en FPGA
- Implementación de lista enlazada dinámica en VHDL con tipos protegidos y punteros de acceso
- Crear un array de objetos en Java: Guía paso a paso