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.