Skip to content

VHDL · Chapter 14.7 · Testbench Development

Data-Driven and Vector-Based Testing

Vector-based testing separates the testbench harness from the test data. Each test case is a vector, a bundle of inputs plus the expected output, and the vectors live either in a constant array of records inside the testbench or in an external file. A single generic loop walks them, driving the inputs, checking the actual result against the expected, and tallying pass or fail, so the harness never changes as cases multiply. Vectors are often golden, generated by a reference model or script, with the run's results compared against the expected file. The result is a regression suite you grow by adding data rather than code, and run unattended on every change. This lesson covers the vector data model, the generic drive-and-check loop, golden vectors and diffing, and the regression mindset.

Foundation14 min readVHDLTestbenchVectorsData-DrivenRegressionVerification

1. Engineering intuition — one harness, a growing table of cases

The scalable shape of a test is a table and a loop: each row is one case (inputs + the answer you expect), and the loop applies every row the same way. Once the harness can process one vector — drive it, check it, count the result — it can process a million, because adding cases means adding rows, not rewriting the testbench. That is the whole leverage of data-driven testing: the logic of the test is fixed and small, while the coverage lives in data you can extend by hand, by script, or by a reference model. When the answers come from a trusted source (golden vectors), the loop becomes a precise yes/no over the entire table.

2. Formal explanation — the vector data model and the generic loop

vector_table.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- A VECTOR = inputs + expected output. Held as a CONSTANT ARRAY OF RECORDS (13.1) in the TB...
type vector_t is record
  a, b : std_logic_vector(7 downto 0);
  expected : std_logic_vector(8 downto 0);
end record;
type vec_array is array (natural range <>) of vector_t;
 
constant VECTORS : vec_array := (
  ( a => x"03", b => x"05", expected => "000001000" ),   -- 3 + 5  = 8
  ( a => x"FF", b => x"01", expected => "100000000" ),   -- corner: carry
  ( a => x"00", b => x"00", expected => "000000000" )    -- corner: zero
);
 
-- ...and a single GENERIC LOOP drives + checks EVERY vector, tallying results.
run : process
  variable errs : natural := 0;
begin
  for i in VECTORS'range loop
    a <= VECTORS(i).a;  b <= VECTORS(i).b;  valid <= '1';
    wait until rising_edge(clk);                          -- (account for DUT latency, 14.4)
    if sum /= VECTORS(i).expected then
      errs := errs + 1;
      report "vec " & integer'image(i) & " FAIL" severity error;
    end if;
  end loop;
  assert errs = 0 report integer'image(errs) & " failures" severity error;   -- final verdict
  wait;
end process;

A vector bundles inputs and the expected output; a constant array of records (or an external file) holds the suite; one generic loop drives and checks each entry and tallies pass/fail. The harness is fixed — coverage grows by extending the vector set.

3. Production usage — golden vectors, files, and regression

golden_and_regression.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- For large suites, keep vectors in a FILE (14.6) so they are generated/edited outside the code.
--   stimulus.txt:   "03 05 008"   "FF 01 100"   ...   (inputs + GOLDEN expected, hex)
-- A REFERENCE MODEL or script produces the golden 'expected' column; the TB never guesses the answer.
 
run : process variable l : line; variable a,b : std_logic_vector(7 downto 0);
              variable exp : std_logic_vector(8 downto 0); variable errs : natural := 0;
begin
  while not endfile(vec_file) loop
    readline(vec_file, l); hread(l,a); hread(l,b); hread(l,exp);   -- one golden vector per line
    drive_op(clk, dut_a, dut_b, dut_valid, a, b);
    wait until result_valid = '1';
    if dut_sum /= exp then errs := errs + 1; end if;               -- compare to golden
  end loop;
  -- PASS/FAIL feeds a regression: exit status / diff results.txt vs golden.txt
  if errs = 0 then report "PASS" severity note; else report "FAIL" severity error; end if;
  wait;
end process;

What hardware does this become? None — this is test methodology, not RTL. Its payoff is operational: the same harness runs ten vectors during bring-up and ten thousand in a nightly regression, scored automatically against golden data. Keeping vectors in a file (or generating them) means a script or reference model owns the expected answers, and a simple diff of results-vs-golden gives a verdict. Coverage scales with the data set, and every past bug becomes a permanent regression vector that guards against its return.

4. Structural interpretation — vector table through the loop to a verdict

vector table feeding a generic drive-and-check loop over the DUT producing a pass/fail tallydrivecheckvector table / fileinputs + golden expectedgeneric loopfor each vectorDUT + compareactual vs expectedpass/fail tallyverdict → regression12
Vector-based testing separates a fixed harness from a growing table of cases. Each vector bundles inputs and a golden expected output, held in a constant array of records or an external file. One generic loop walks the table: drive the inputs into the DUT, compare the actual output to the expected, and tally pass/fail, producing a final verdict diffable against golden data. Adding cases means adding rows, not changing code, so coverage scales with data and forms a regression suite. This is a test-methodology structure, captured by a diagram rather than a waveform.

5. Why this is structural, not timing

Vector-based testing is a methodology — how the test is organized into data plus a generic loop — so a structural diagram (table → loop → verdict) captures it, not a waveform. Any individual vector produces ordinary stimulus/response waveforms (covered in the stimulus and self-checking lessons), but the point here is the architecture of the test: separating fixed harness from extensible data. That separation is a design-time property of the verification code, which is why it is shown as structure rather than a signal trace.

6. Debugging example — data and harness entangled

Expected: adding test cases is trivial and never touches the harness. Observed: every new case requires editing the testbench logic (new assignments, new checks), cases drift out of sync, or coverage stalls because adding tests is painful. Root cause: the test was directed-only — stimulus and checks hand-written per-case and entangled with the harness — instead of data-driven, so the data and the logic were not separated. Fix: factor each case into a vector (inputs + expected) in an array or file, and write one generic loop that drives and checks any vector; then new coverage is new data, not new code. Engineering takeaway: separate test data from test logic — a vector table plus a generic loop scales to thousands of cases, while per-case hand-written stimulus does not.

separate_data_from_logic.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- BUG: directed, per-case logic — every new test edits the harness.
-- a<=x"03"; b<=x"05"; wait...; assert sum=...; a<=x"FF"; b<=x"01"; wait...; assert sum=...;
-- FIX: data-driven — one loop over a vector table; add rows, not code.
for i in VECTORS'range loop drive(VECTORS(i)); check(VECTORS(i)); end loop;

7. Common mistakes & what to watch for

  • Entangling data with logic. Keep cases as vectors (array/file) and use one generic loop; do not hand-code each case into the harness.
  • No golden source. The expected column must come from a trusted reference model or known data — not from the DUT itself.
  • Format/parse drift (files). Vector files must match the parse order/radix (14.6); a mismatch corrupts every case silently.
  • Not tallying / no verdict. Count failures and emit an explicit PASS/FAIL so regressions are scored automatically.
  • Throwing away bug vectors. Add every fixed bug's case to the suite permanently so regressions catch recurrence.

8. Engineering insight & continuity

Vector-based, data-driven testing separates a fixed harness from a growing table of {inputs, expected} vectors — in an array of records or a file — walked by one generic loop that drives, checks, and tallies, with golden answers from a reference model and results diffed for a verdict. Coverage scales by adding data, and the suite becomes a regression. So far the vectors have been directed (chosen by hand); the next lesson adds breadth automatically: Randomized Stimulus in VHDL — generating large, varied input sets to reach cases you would not think to write.