Acionando Testbenches VHDL a partir de Arquivos de Estímulo Externos com TEXTIO
Ler dados de estímulo de um arquivo externo é uma maneira poderosa de controlar um Device-Under-Test (DUT) em VHDL. Scriptando uma sequência de valores de sinais e tempos de simulação em um arquivo de texto simples, projetistas podem trocar rapidamente padrões de teste sem modificar a lógica do testbench. Este artigo, o segundo em uma série sobre acesso a arquivos em VHDL, demonstra como ler um arquivo de estímulo com a biblioteca TEXTIO e aplicar seus valores a um multiplexador de 4 entradas.
Visão Geral do Caso de Teste
O DUT é um multiplexador 4-para-1 padrão, assíncrono, com palavras de dados de 8 bits. O testbench não realiza verificação de saída — apenas aciona as entradas para que a forma de onda possa ser examinada manualmente. A declaração da entidade é reproduzida abaixo para referência.
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;
Sinais que conectam ao DUT são declarados na arquitetura do testbench e instanciados com o label 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 );
Projetando o Arquivo de Estímulo
Embora muitos formatos sejam possíveis, o exemplo abaixo ilustra um layout claro e legível por humanos. Cada linha representa um passo de simulação e contém:
- wait_time – delay do passo anterior (ex:
10 ns) - sel – valor do seletor de 2 bits
- din_0 a din_3 – valores de dados de 8 bits em hexadecimal
- Comentário final opcional começando com
#para saída no console
Comentários que iniciam uma linha são ignorados pelo testbench; comentários que seguem um conjunto de dados são impressos no console do 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
Lendo o Arquivo com TEXTIO
Abaixo está o processo principal que abre o arquivo de estímulo, faz parse de cada linha, atribui valores às entradas do DUT e lida com comentários. O exemplo assume um arquivo bem formatado — um espaço separa colunas, e o caractere # é seguido por um único espaço.
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); -- Skip empty lines and single-line comments 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; -- Print trailing comment to console, if any read(text_line, char, ok); -- Skip expected newline read(text_line, char, ok); if char = '#' then read(text_line, char, ok); -- Skip expected newline report text_line.all; end if; end loop; finish; end process;
Saída da Simulação
Quando rodado no ModelSim, o console exibe os comentários finais junto com o tempo de simulação cumulativo. O trecho a seguir mostra a sequência de notas impressas:
# ** 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
A forma de onda produzida pelo testbench espelha o tempo e valores de dados do arquivo, permitindo que projetistas verifiquem o comportamento do DUT visualmente.
Principais Conclusões
- Arquivos de estímulo externos dão aos projetistas controle granular sobre sequências de teste sem alterar código do testbench.
- Usar
TEXTIOmantém o testbench conciso, mas requer formatação disciplinada do arquivo. - Sempre inclua um mecanismo de auto-verificação — seja comparando com um modelo comportamental ou incorporando saídas esperadas no arquivo de estímulo.
Seguindo o exemplo acima, você pode aproveitar toda a flexibilidade do TEXTIO do VHDL para dirigir cenários de teste complexos mantendo uma estrutura de testbench limpa e manutenível.

VHDL
- Dominando Declarações Using em C#: Imports, Aliases e Diretivas Estáticas
- Manipulação de Arquivos em C: Dominando I/O com fopen, fprintf, fread e fseek
- Dominando Operações de Arquivo em Java com java.io – Criação, Leitura, Escrita e Exclusão
- Inicializando Block RAM de FPGA a partir de Arquivos de Texto Usando a Biblioteca TEXTIO do VHDL
- Como Construir um Testbench de Auto-Verificação em VHDL – Guia Prático
- Lendo Arquivos em Java com BufferedReader – Guia Prático com Exemplos
- Python JSON: Codificação, Decodificação e Manipulação de Arquivos – Guia Prático
- Dominando I/O de Arquivos em Verilog: Abrir, Ler, Escrever e Fechar
- Entendendo Arquivos de Cabeçalho em C: Tipos, Uso e Boas Práticas
- Lima Triangular Explicada: Design, Usos e Cuidados