VHDL · Chapter 14.6 · Testbench Development
File I/O with textio
Hard-coding every stimulus value in the testbench source does not scale; real verification keeps test vectors and golden results in files. The standard textio package, plus the std-logic textio helpers for logic values, gives a testbench file I/O through two objects: a file you open in read or write mode, and a line, which is a buffer you parse from or build up. You read a line and then read its fields to pull in a stimulus vector, you write fields into a line and then write that line to emit a result or log entry, and end-of-file tells you when the input is exhausted. This is the foundation of data-driven testing, where stimulus and expected results live in files, so adding cases means editing data rather than code. This lesson covers opening files, parsing and building lines, end-of-file handling, and hex and logic-value I/O, all simulation-only.
Foundation14 min readVHDLtextioFile I/OTestbenchData-DrivenVerification
1. Engineering intuition — keep the test data outside the code
A test with three vectors can hardcode them; a test with three thousand cannot. The scalable pattern is to put the
data — input vectors and expected outputs — in a file, and have the testbench read it. Now the harness
is generic ("for each line: apply inputs, check output") and the cases are just rows you add to a text file, even
generated by a script. textio is how VHDL reads and writes those files: pull a line in, parse the numbers out;
or format some values, push the line out to a results log. The mental model is line-oriented — you always work a
line at a time, reading fields from it or writing fields into it.
2. Formal explanation — file, line, and the read/write operations
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
use std.textio.all; -- file, line, readline/read, writeline/write, endfile
use ieee.std_logic_textio.all; -- read/write for std_logic types (hex/binary); in 1164 since 2008
-- FILE declarations with an open MODE:
file vec_file : text open read_mode is "stimulus.txt"; -- input vectors
file log_file : text open write_mode is "results.txt"; -- output log
read_proc : process
variable l : line; -- a line buffer
variable a, b : std_logic_vector(7 downto 0);
variable expected : std_logic_vector(8 downto 0);
begin
while not endfile(vec_file) loop -- until input is exhausted
readline(vec_file, l); -- pull one line into the buffer
hread(l, a); -- parse hex fields from the line, in order
hread(l, b);
hread(l, expected);
-- ... apply a,b to the DUT, check against expected (14.4) ...
end loop;
wait;
end process;The two objects are file (opened read_mode/write_mode) and line (a parse/build buffer). You
readline to fetch a line then read/hread to extract fields in order; you write/hwrite fields
into a line then writeline to emit it; endfile detects exhaustion. std_logic_textio provides
read/write (and hex hread/hwrite) for std_logic types.
3. Production usage — read stimulus, write a results log
-- Each input line: "AA BB 165" → a, b, expected (hex). Each result line logged to results.txt.
run : process
variable il, ol : line;
variable a, b : std_logic_vector(7 downto 0);
variable exp : std_logic_vector(8 downto 0);
begin
while not endfile(vec_file) loop
readline(vec_file, il);
hread(il, a); hread(il, b); hread(il, exp); -- parse the stimulus row
drive_op(clk, dut_a, dut_b, dut_valid, a, b); -- apply to DUT (14.2)
wait until result_valid = '1';
-- BUILD an output line and emit it.
write(ol, string'("a=")); hwrite(ol, a);
write(ol, string'(" got=")); hwrite(ol, dut_sum);
write(ol, string'(" exp=")); hwrite(ol, exp);
writeline(log_file, ol); -- one result line per vector
end loop;
wait;
end process;What hardware does this become? None — textio is simulation-only (synthesis cannot read or write
host files). Its payoff is a data-driven testbench: the harness logic is fixed, and the test content lives in
stimulus.txt / results.txt. You expand coverage by adding lines, diff the results file against a golden file
to score the run, and even generate vectors from a script or a higher-level model. Building the output line shows
the dual of parsing — write/hwrite append fields, writeline flushes the line to the file.
4. Structural interpretation — file in, parse, drive, log out
5. Why this is structural, not timing
File I/O with textio is a data-flow concern — lines in, fields parsed, results formatted and written — so
the pipeline diagram above is the right picture, not a waveform. Its effect is on test content and bookkeeping,
not signal behavior; the actual DUT waveforms come from the stimulus the file feeds (covered in the stimulus and
self-checking lessons). Because it is simulation-only and host-side, it has no hardware timing at all. The value is
structural: separating the harness from the data so tests scale by editing files.
6. Debugging example — the parse that drifted from the file format
Expected: each line's fields load into the right variables. Observed: values are shifted, wrong, or a
read error/endfile surprise, even though the file "looks right." Root cause: the read order or
radix did not match the file format — fields read in the wrong order, a decimal read used where the data is
hex (or vice versa), an extra/missing field per line, or the file not opened in the correct mode. A line
is parsed left-to-right by successive read/hread calls, so the call sequence must mirror the columns exactly.
Fix: make the read/hread calls match the file's column order and radix precisely, read the right
number of fields per line, and open files in the proper mode (read_mode/write_mode). Engineering
takeaway: textio parsing is positional and typed — line up the read/hread calls with the file's exact
field order and radix, or the data silently lands in the wrong variables.
-- BUG: file has HEX fields but parsed as decimal, and in the wrong order.
-- readline(f,l); read(l, b_dec); read(l, a_dec); -- decimal read on hex data, swapped
-- FIX: hex read, columns in the file's actual order.
readline(f, l); hread(l, a); hread(l, b); hread(l, expected);7. Common mistakes & what to watch for
- Parse order/radix mismatch.
read/hreadcalls must match the file's column order and number base exactly; otherwise fields land wrong. - Wrong open mode. Open input
read_mode, outputwrite_mode; using the wrong mode fails or truncates. - Ignoring
endfile. Loopwhile not endfile(f); reading past end is an error. - Forgetting
std_logic_textio(pre-2008).std_logic/hex line I/O needs it; in VHDL-2008 it is instd_logic_1164. - Trying to synthesize file I/O.
textiois simulation-only; never put it in RTL.
8. Engineering insight & continuity
textio gives a testbench file I/O through file and line objects: readline/read to parse stimulus
and expected values from a file, write/writeline to emit results and logs, endfile to detect the end — with
std_logic_textio for hex/std_logic fields, all simulation-only. This separates the harness from the
data, the essence of scalable testing. It leads directly into the methodology that uses it: the next lesson,
Data-Driven and Vector-Based Testing — structuring whole test suites around files of vectors and golden
results.
Standards & specifications
- Governing standard
- IEEE Std 1076 (VHDL)(opens IEEE in a new tab)
Defines the VHDL language — types, the simulation cycle, and the semantics a conforming analyser and simulator must implement. Synthesis restrictions and vendor coding rules are tool behaviour, not language rules.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of VHDL Testbenches — Stimulus, Checking & Self-Checking Design.
