Industrial manufacturing
Industrial Internet of Things | Industrial materials | Equipment Maintenance and Repair | Industrial programming |
home  MfgRobots >> Industrial manufacturing >  >> Industrial programming >> VHDL

Driving VHDL Testbenches from External Stimulus Files with TEXTIO

Reading stimulus data from an external file is a powerful way to control a Device‑Under‑Test (DUT) in VHDL. By scripting a sequence of signal values and simulation times in a plain‑text file, designers can quickly swap test patterns without modifying the testbench logic. This article, the second in a series on VHDL file access, demonstrates how to read a stimulus file with the TEXTIO library and apply its values to a 4‑input multiplexer.

Test Case Overview

The DUT is a standard, asynchronous 4‑to‑1 multiplexer with 8‑bit data words. The testbench does not perform any output verification – it merely drives the inputs so that the waveform can be examined manually. The entity declaration is reproduced below for reference.

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;

Signals that connect to the DUT are declared in the testbench architecture and instantiated with the 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
);

Designing the Stimulus File

Although many formats are possible, the example below illustrates a clear, human‑readable layout. Each line represents a simulation step and contains:

Comments that begin a line are ignored by the testbench; comments that follow a data set are printed to the simulator console.

# 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

Reading the File with TEXTIO

Below is the core process that opens the stimulus file, parses each line, assigns values to the DUT inputs, and handles comments. The example assumes a well‑formatted file – one space separates columns, and the # character is followed by a single space.

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;

Simulation Output

When run in ModelSim the console displays the trailing comments along with the cumulative simulation time. The following excerpt shows the sequence of printed notes:

# ** 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

The waveform produced by the testbench mirrors the timing and data values from the file, allowing designers to verify the DUT’s behavior visually.

Key Takeaways

By following the example above, you can harness the full flexibility of VHDL’s TEXTIO to drive complex test scenarios while maintaining a clean, maintainable testbench structure.

Driving VHDL Testbenches from External Stimulus Files with TEXTIO

VHDL

  1. Reading BMP Bitmap Images in VHDL Testbenches with TEXTIO
  2. Initializing FPGA Block RAM from Text Files Using VHDL’s TEXTIO Library
  3. Enhance Hardware Verification with a Tcl-Based Interactive Testbench
  4. C++ File Handling: Mastering Open, Read, Write, and Close Operations
  5. File Operations in C# – A Practical Guide
  6. Reading Files in Java with BufferedReader – A Practical Guide with Examples
  7. How to Rename Files and Directories in Python with os.rename() – Step-by-Step Guide
  8. How to Read and Write CSV Files in Python: A Comprehensive Guide
  9. Python JSON: Encoding, Decoding, and File Handling – A Practical Guide
  10. Seamless PLC‑to‑Cloud Integration: Harnessing IoT for Real‑Time Data Retrieval