Control de testbenches VHDL desde archivos de estímulo externos con TEXTIO
Leer datos de estímulo desde un archivo externo es una forma potente de controlar un Device‑Under‑Test (DUT) en VHDL. Mediante scripting de una secuencia de valores de señal y tiempos de simulación en un archivo de texto plano, los diseñadores pueden intercambiar rápidamente patrones de prueba sin modificar la lógica del testbench. Este artículo, el segundo de una serie sobre acceso a archivos en VHDL, demuestra cómo leer un archivo de estímulo con la biblioteca TEXTIO y aplicar sus valores a un multiplexor de 4 entradas.
Visión general del caso de prueba
El DUT es un multiplexor estándar, asíncrono, de 4‑a‑1 con palabras de datos de 8 bits. El testbench no realiza verificación de salida —simplemente controla las entradas para que la forma de onda pueda examinarse manualmente. La declaración de entidad se reproduce a continuación para referencia.
entity mux_4 is port( din_0 : in unsigned(7 downto 0); din_1 : in unsigned(7 downto 0); din_2 : in unsigned(7 downto 0); din_3 : in unsigned(7 downto 0); sel : in unsigned(1 downto 0); dout : out unsigned(7 downto 0)); end entity;
Las señales que conectan al DUT se declaran en la arquitectura del testbench e instancian con la etiqueta DUT:
signal din_0 : unsigned(7 downto 0); signal din_1 : unsigned(7 downto 0); signal din_2 : unsigned(7 downto 0); signal din_3 : unsigned(7 downto 0); signal sel : unsigned(1 downto 0); signal dout : unsigned(7 downto 0); DUT: entity work.mux_4(rtl) port map ( din_0 => din_0, din_1 => din_1, din_2 => din_2, din_3 => din_3, sel => sel, dout => dout );
Diseño del archivo de estímulo
Aunque muchos formatos son posibles, el ejemplo siguiente ilustra un diseño claro y legible por humanos. Cada línea representa un paso de simulación y contiene:
- wait_time – retraso desde el paso anterior (p.ej.,
10 ns) - sel – valor de selector de 2 bits
- din_0 a din_3 – valores de datos de 8 bits en hexadecimal
- Comentario final opcional que empieza con
#para salida en consola
Los comentarios que comienzan una línea son ignorados por el testbench; los comentarios que siguen a un conjunto de datos se imprimen en la consola del simulador.
# Column description: # wait_time | sel | din_0 | din_1 | din_2 | din_3 # Optional console printout 0 ns 0 AA BB CC DD # Setting initial values 10 ns 1 AA BB CC DD # Testing by changing the selector signal 10 ns 2 AA BB CC DD 10 ns 3 AA BB CC DD 10 ns 3 A1 B1 C1 D1 # Testing by changing all data inputs 10 ns 3 A2 B2 C2 D2 10 ns 3 A3 B3 C3 D3 10 ns 3 00 00 00 D2 # Changing all unselected inputs 10 ns 3 01 02 03 D2 10 ns 3 11 22 33 D2 1 ns 0 CC DD EE FF # Changing all inputs fast 1 ns 1 DD EE FF CC 1 ns 2 EE FF CC DD 1 ns 3 FF CC DD EE 10 ns 0 00 00 00 00 # Simulation stop
Lectura del archivo con TEXTIO
A continuación se muestra el proceso principal que abre el archivo de estímulo, parsea cada línea, asigna valores a las entradas del DUT y maneja comentarios. El ejemplo asume un archivo bien formateado —un espacio separa columnas, y el carácter # va seguido de un solo espacio.
PROC_SEQUENCER : process file text_file : text open read_mode is "stimulus.txt"; variable text_line : line; variable ok : boolean; variable char : character; variable wait_time : time; variable selector : sel'subtype; variable data : dout'subtype; begin while not endfile(text_file) loop readline(text_file, text_line); -- Saltar líneas vacías y comentarios de una línea if text_line.all'length = 0 or text_line.all(1) = '#' then next; end if; read(text_line, wait_time, ok); assert ok report "Read 'wait_time' failed for line: " & text_line.all severity failure; hread(text_line, selector, ok); assert ok report "Read 'sel' failed for line: " & text_line.all severity failure; sel <= selector; hread(text_line, data, ok); assert ok report "Read 'din_0' failed for line: " & text_line.all severity failure; din_0 <= data; hread(text_line, data, ok); assert ok report "Read 'din_1' failed for line: " & text_line.all severity failure; din_1 <= data; hread(text_line, data, ok); assert ok report "Read 'din_2' failed for line: " & text_line.all severity failure; din_2 <= data; hread(text_line, data, ok); assert ok report "Read 'din_3' failed for line: " & text_line.all severity failure; din_3 <= data; wait for wait_time; -- Imprimir comentario final en consola, si existe read(text_line, char, ok); -- Saltar salto de línea esperado read(text_line, char, ok); if char = '#' then read(text_line, char, ok); -- Saltar salto de línea esperado report text_line.all; end if; end loop; finish; end process;
Salida de simulación
Al ejecutarse en ModelSim, la consola muestra los comentarios finales junto con el tiempo de simulación acumulado. El siguiente extracto muestra la secuencia de notas impresas:
# ** Note: Setting initial values # Time: 0 ns Iteration: 1 Instance: /file_stim_tb # ** Note: Testing by changing the selector signal # Time: 10 ns Iteration: 0 Instance: /file_stim_tb # ** Note: Testing by changing all data inputs # Time: 40 ns Iteration: 0 Instance: /file_stim_tb # ** Note: Changing all unselected inputs # Time: 70 ns Iteration: 0 Instance: /file_stim_tb # ** Note: Changing all inputs fast # Time: 91 ns Iteration: 0 Instance: /file_stim_tbf # ** Note: Simulation stop # Time: 104 ns Iteration: 0 Instance: /file_stim_tb # Break in Process PROC_SEQUENCER at file_stim_tb.vhd line 98
La forma de onda producida por el testbench refleja los tiempos y valores de datos del archivo, permitiendo a los diseñadores verificar el comportamiento del DUT visualmente.
Conclusiones clave
- Los archivos de estímulo externos dan a los diseñadores control granular sobre secuencias de prueba sin alterar código de testbench.
- Usar
TEXTIOmantiene el testbench conciso, pero requiere formato de archivo disciplinado. - Incluya siempre un mecanismo de auto-comprobación —ya sea comparando contra un modelo conductual o incrustando salidas esperadas en el archivo de estímulo.
Siguiendo el ejemplo anterior, puede aprovechar toda la flexibilidad de TEXTIO de VHDL para impulsar escenarios de prueba complejos manteniendo una estructura de testbench limpia y mantenible.

VHDL
- Lima triangular: diseño, usos y cuidados
- Uso de firmas digitales para verificar integridad de archivos binarios en Linux
- Dominando las Sentencias Using en C#: Importaciones, Alias y Directivas Estáticas
- Manejo de archivos en C: Dominando E/S con fopen, fprintf, fread y fseek
- Entendiendo los Archivos de Cabecera en C: Tipos, Uso y Buenas Prácticas
- Inicialización de RAM de bloques FPGA desde archivos de texto usando la biblioteca TEXTIO de VHDL
- Cómo construir un testbench de auto-comprobación en VHDL: Guía práctica
- Dominando la E/S de Archivos en Verilog: Abrir, Leer, Escribir y Cerrar
- Python JSON: Codificación, decodificación y manejo de archivos – Guía práctica
- Dominando las operaciones de archivos en Java con java.io: creación, lectura, escritura y eliminación
- Lectura de archivos en Java con BufferedReader – Guía práctica con ejemplos