Testing And Benchmarking in VHDL
Here’s an idiomatic VHDL example that demonstrates the concept of testing and benchmarking:
-- File: int_min.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity int_min is
Port ( a : in SIGNED(31 downto 0);
b : in SIGNED(31 downto 0);
min_out : out SIGNED(31 downto 0));
end int_min;
architecture Behavioral of int_min is
begin
min_out <= a when a < b else b;
end Behavioral;
-- File: int_min_tb.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
entity int_min_tb is
end int_min_tb;
architecture Behavioral of int_min_tb is
component int_min is
Port ( a : in SIGNED(31 downto 0);
b : in SIGNED(31 downto 0);
min_out : out SIGNED(31 downto 0));
end component;
signal a, b, min_out : SIGNED(31 downto 0);
type test_case is record
a, b, expected : INTEGER;
end record;
type test_case_array is array (natural range <>) of test_case;
constant test_cases : test_case_array := (
(0, 1, 0),
(1, 0, 0),
(2, -2, -2),
(0, -1, -1),
(-1, 0, -1)
);
-- For benchmarking
constant NUM_CYCLES : integer := 1000000;
begin
-- Instantiate the Unit Under Test (UUT)
uut: int_min port map (a => a, b => b, min_out => min_out);
-- Test process
test_proc: process
begin
for i in test_cases'range loop
a <= to_signed(test_cases(i).a, 32);
b <= to_signed(test_cases(i).b, 32);
wait for 10 ns;
assert min_out = to_signed(test_cases(i).expected, 32)
report "Test case " & integer'image(i) & " failed: " &
"Expected " & integer'image(test_cases(i).expected) &
", got " & integer'image(to_integer(min_out))
severity error;
end loop;
report "All tests completed";
wait;
end process;
-- Benchmark process
benchmark_proc: process
variable start_time, end_time : time;
begin
start_time := now;
for i in 1 to NUM_CYCLES loop
a <= to_signed(1, 32);
b <= to_signed(2, 32);
wait for 1 ns;
end loop;
end_time := now;
report "Benchmark completed in " & time'image(end_time - start_time);
wait;
end process;
end Behavioral;
This VHDL example demonstrates testing and benchmarking concepts similar to the Go example. Here’s a breakdown of the code:
We define an
int_min
entity that finds the minimum of two signed 32-bit integers.In the testbench (
int_min_tb
), we create a set of test cases similar to the table-driven tests in the Go example.The
test_proc
process runs through each test case, applies inputs to the Unit Under Test (UUT), and checks the output against the expected value. It reports any errors encountered.The
benchmark_proc
process performs a simple benchmark by running theint_min
entity for a fixed number of cycles and measuring the time taken.
To run this VHDL code:
- Save the
int_min
entity in a file namedint_min.vhd
. - Save the testbench in a file named
int_min_tb.vhd
. - Use a VHDL simulator like GHDL, ModelSim, or Vivado Simulator to compile and run the testbench.
For example, using GHDL:
$ ghdl -a int_min.vhd
$ ghdl -a int_min_tb.vhd
$ ghdl -e int_min_tb
$ ghdl -r int_min_tb --wave=int_min_tb.ghw
This will run the testbench and generate a waveform file (int_min_tb.ghw
) that you can view with a waveform viewer like GTKWave.
The testbench will report the results of each test case and the time taken for the benchmark. This approach allows for systematic testing and performance measurement of VHDL designs, similar to the testing and benchmarking capabilities in Go.