File-driven testbenches¶
File-driven verification separates test data from VHDL. It is useful when vectors come from Python, MATLAB, a spreadsheet export, a protocol trace, or a golden algorithm.
Vector file¶
Keep the first format simple: whitespace-separated decimal integers with comment lines.
Reading with TextIO¶
library std;
use std.textio.all;
stimulus : process
file vectors : text open read_mode is VECTOR_FILE;
variable row : line;
variable a_value : natural;
variable b_value : natural;
variable cin_value : natural;
variable expected : natural;
begin
while not endfile(vectors) loop
readline(vectors, row);
if row.all'length > 0 and row.all(row.all'left) /= '#' then
read(row, a_value);
read(row, b_value);
read(row, cin_value);
read(row, expected);
-- Drive, wait, calculate actual, assert.
end if;
end loop;
finish;
end process;
Use a string generic for the path:
The automation script can pass an absolute file path, making the test independent of the simulator working directory.
Robust file-format rules¶
Document:
- Radix: decimal, hexadecimal, or binary.
- Signedness.
- Field order.
- Units.
- Whether values are input or expected output.
- How comments and blank lines work.
- Version of the vector schema.
- Expected number of rows.
Fail when a required row cannot be parsed. Silently skipping malformed vectors can create false passes.
Generate vectors with Python¶
Example generator for the adder:
from pathlib import Path
output = Path("tb/vectors-generated.txt")
with output.open("w", encoding="utf-8") as stream:
stream.write("# a b cin expected\n")
for a in range(16):
for b in range(16):
for cin in (0, 1):
stream.write(f"{a} {b} {cin} {a + b + cin}\n")
The expected value comes from Python integer arithmetic, independently of the VHDL implementation.
Floating-point scientific models¶
An FPGA design often uses fixed-point while a Python reference uses floating-point. Define the conversion exactly:
- Scale:
integer = round(real × 2^fraction_bits). - Rounding mode: nearest, floor, truncate, or convergent.
- Overflow behavior: wrap or saturate.
- Signed representation: two's complement.
- Acceptable error tolerance in least significant bits.
Compare using a tolerance when the specification permits:
error_value := abs(actual_integer - expected_integer);
assert error_value <= MAX_ERROR_LSB
report "Result exceeds allowed error"
severity failure;
Binary files¶
Text is easiest to inspect and version-control. Binary files are useful for large datasets but require explicit endianness, packing, and tool-portability rules. Start with text unless performance becomes a measured problem.
Golden vectors and source control¶
Store small, meaningful vector sets in Git. For large generated datasets, store:
- Generator script.
- Seed.
- Model version.
- Configuration.
- Checksum if reproducibility matters.
Avoid checking in huge generated files when they can be recreated deterministically.
Common pitfalls¶
- Relative path interpreted from the simulator build directory.
- Windows backslashes misread by another tool.
- Reading signed data into
natural. - Comparing before signal updates settle.
- Forgetting to count executed vectors.
- Passing because the file was empty.
At the end, assert the number of tests: