Skip to content

Commit 8785311

Browse files
committed
Added VHDL configuration examples.
1 parent e14db0a commit 8785311

8 files changed

Lines changed: 408 additions & 0 deletions

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
-- This Source Code Form is subject to the terms of the Mozilla Public
2+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
4+
--
5+
-- Copyright (c) 2014-2023, Lars Asplund lars.anders.asplund@gmail.com
6+
library ieee;
7+
use ieee.std_logic_1164.all;
8+
9+
entity dff is
10+
generic(
11+
width : positive := 8
12+
);
13+
port(
14+
clk : in std_logic;
15+
reset : in std_logic;
16+
d : in std_logic_vector(width - 1 downto 0);
17+
q : out std_logic_vector(width - 1 downto 0)
18+
);
19+
end;
20+
21+
architecture rtl of dff is
22+
begin
23+
process(clk) is
24+
begin
25+
if rising_edge(clk) then
26+
if reset = '1' then
27+
q <= (others => '0');
28+
else
29+
q <= d;
30+
end if;
31+
end if;
32+
end process;
33+
end;
34+
35+
configuration dff_rtl of tb_selecting_dut_with_vhdl_configuration is
36+
for tb
37+
for test_fixture
38+
for dut : dff
39+
use entity work.dff(rtl);
40+
end for;
41+
end for;
42+
end for;
43+
end;
44+
45+
architecture behavioral of dff is
46+
begin
47+
process
48+
begin
49+
wait until rising_edge(clk);
50+
q <= (others => '0') when reset else d;
51+
end process;
52+
end;
53+
54+
configuration dff_behavioral of tb_selecting_dut_with_vhdl_configuration is
55+
for tb
56+
for test_fixture
57+
for dut : dff
58+
use entity work.dff(behavioral);
59+
end for;
60+
end for;
61+
end for;
62+
end;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env python3
2+
3+
# This Source Code Form is subject to the terms of the Mozilla Public
4+
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
5+
# You can obtain one at http://mozilla.org/MPL/2.0/.
6+
#
7+
# Copyright (c) 2014-2023, Lars Asplund lars.anders.asplund@gmail.com
8+
9+
from pathlib import Path
10+
from vunit import VUnit
11+
12+
vu = VUnit.from_argv()
13+
vu.add_vhdl_builtins()
14+
lib = vu.add_library("lib")
15+
root = Path(__file__).parent
16+
lib.add_source_files(root / "*.vhd")
17+
18+
# VHDL configurations are treated as a special case of the broader VUnit configuration
19+
# concept. As such the configuration can be extended beyond the capabilities of a
20+
# pure VHDL configuration. For example, by running with different generic values.
21+
tb = lib.test_bench("tb_selecting_dut_with_vhdl_configuration")
22+
23+
for vhdl_configuration_name in ["dff_rtl", "dff_behavioral"]:
24+
for width in [8, 16]:
25+
tb.add_config(
26+
name=f"{vhdl_configuration_name}_{width}",
27+
generics=dict(width=width),
28+
vhdl_configuration_name=vhdl_configuration_name,
29+
)
30+
31+
# A top-level VHDL configuration is bound to an entity, i.e. the testbench. However,
32+
# when handled as part of VUnit configurations it can also be applied to a
33+
# single test case
34+
tb.test("Test reset").add_config(name="dff_rtl_32", generics=dict(width=32), vhdl_configuration_name="dff_rtl")
35+
36+
37+
# If the test runner is placed in a component instantiated into the testbench, different architectures of that
38+
# component can implement different tests and VHDL configurations can be used to select what test to run.
39+
# This is the approach taken by a traditional OSVVM testbench. In VUnit, such a test becomes a VUnit configuration
40+
# selecting the associated VHDL configuration rather than a VUnit test case, but that is of less importance. Note that
41+
# this approach is limited in that the test runner architecture can't contain a test suite with explicit test cases
42+
# (run function calls) but only the test_runner_setup and test_runner_cleanup calls. Should you need multiple test
43+
# suites sharing the same test fixture (the DUT and the surrounding verification components), the proper approach
44+
# is to put each test suite in its own testbench and make the test fixture a component reused between the testbenches.
45+
# That approach do not require any VHDL configurations.
46+
tb = lib.test_bench("tb_selecting_test_runner_with_vhdl_configuration")
47+
for vhdl_configuration_name in ["test_reset", "test_state_change"]:
48+
for width in [8, 16]:
49+
tb.add_config(
50+
name=f"{vhdl_configuration_name}_{width}",
51+
generics=dict(width=width),
52+
vhdl_configuration_name=vhdl_configuration_name,
53+
)
54+
55+
vu.main()
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
-- This Source Code Form is subject to the terms of the Mozilla Public
2+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
4+
--
5+
-- Copyright (c) 2014-2023, Lars Asplund lars.anders.asplund@gmail.com
6+
--
7+
-- Description: This is an example of a testbench using VHDL configurations
8+
-- to select DUT architecture
9+
10+
library vunit_lib;
11+
context vunit_lib.vunit_context;
12+
13+
library ieee;
14+
use ieee.std_logic_1164.all;
15+
16+
entity tb_selecting_dut_with_vhdl_configuration is
17+
generic(
18+
runner_cfg : string;
19+
width : positive
20+
);
21+
end entity;
22+
23+
architecture tb of tb_selecting_dut_with_vhdl_configuration is
24+
constant clk_period : time := 10 ns;
25+
26+
signal reset : std_logic;
27+
signal clk : std_logic := '0';
28+
signal d : std_logic_vector(width - 1 downto 0);
29+
signal q : std_logic_vector(width - 1 downto 0);
30+
31+
component dff is
32+
generic(
33+
width : positive := width
34+
);
35+
port(
36+
clk : in std_logic;
37+
reset : in std_logic;
38+
d : in std_logic_vector(width - 1 downto 0);
39+
q : out std_logic_vector(width - 1 downto 0)
40+
);
41+
end component;
42+
43+
begin
44+
test_runner : process
45+
begin
46+
test_runner_setup(runner, runner_cfg);
47+
48+
while test_suite loop
49+
if run("Test reset") then
50+
d <= (others => '1');
51+
reset <= '1';
52+
wait until rising_edge(clk);
53+
wait for 0 ns;
54+
check_equal(q, 0);
55+
56+
elsif run("Test state change") then
57+
reset <= '0';
58+
59+
d <= (others => '1');
60+
wait until rising_edge(clk);
61+
wait for 0 ns;
62+
check_equal(q, std_logic_vector'(q'range => '1'));
63+
64+
d <= (others => '0');
65+
wait until rising_edge(clk);
66+
wait for 0 ns;
67+
check_equal(q, 0);
68+
end if;
69+
end loop;
70+
71+
test_runner_cleanup(runner);
72+
end process;
73+
74+
test_fixture : block is
75+
begin
76+
clk <= not clk after clk_period / 2;
77+
78+
dut : dff
79+
generic map(
80+
width => width
81+
)
82+
port map(
83+
clk => clk,
84+
reset => reset,
85+
d => d,
86+
q => q
87+
);
88+
end block;
89+
end architecture;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
-- This Source Code Form is subject to the terms of the Mozilla Public
2+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
4+
--
5+
-- Copyright (c) 2014-2023, Lars Asplund lars.anders.asplund@gmail.com
6+
--
7+
-- Description: This is an example of a testbench using separate architectures
8+
-- of a test runner entity to define different tests. This is a structure
9+
-- found in OSVVM-native testbenches
10+
11+
library vunit_lib;
12+
context vunit_lib.vunit_context;
13+
14+
library ieee;
15+
use ieee.std_logic_1164.all;
16+
17+
entity tb_selecting_test_runner_with_vhdl_configuration is
18+
generic(
19+
runner_cfg : string;
20+
width : positive
21+
);
22+
end entity;
23+
24+
architecture tb of tb_selecting_test_runner_with_vhdl_configuration is
25+
constant clk_period : time := 10 ns;
26+
27+
signal reset : std_logic;
28+
signal clk : std_logic := '0';
29+
signal d : std_logic_vector(width - 1 downto 0);
30+
signal q : std_logic_vector(width - 1 downto 0);
31+
32+
component test_runner is
33+
generic(
34+
clk_period : time;
35+
width : positive;
36+
nested_runner_cfg : string
37+
);
38+
port(
39+
reset : out std_logic;
40+
clk : in std_logic;
41+
d : out std_logic_vector(width - 1 downto 0);
42+
q : in std_logic_vector(width - 1 downto 0)
43+
);
44+
end component;
45+
46+
begin
47+
test_runner_inst : test_runner
48+
generic map(
49+
clk_period => clk_period,
50+
width => width,
51+
nested_runner_cfg => runner_cfg
52+
)
53+
port map(
54+
reset => reset,
55+
clk => clk,
56+
d => d,
57+
q => q
58+
);
59+
60+
test_fixture : block is
61+
begin
62+
clk <= not clk after clk_period / 2;
63+
64+
dut : entity work.dff(rtl)
65+
generic map(
66+
width => width
67+
)
68+
port map(
69+
clk => clk,
70+
reset => reset,
71+
d => d,
72+
q => q
73+
);
74+
end block;
75+
end architecture;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
-- This Source Code Form is subject to the terms of the Mozilla Public
2+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
4+
--
5+
-- Copyright (c) 2014-2023, Lars Asplund lars.anders.asplund@gmail.com
6+
7+
library vunit_lib;
8+
context vunit_lib.vunit_context;
9+
10+
library ieee;
11+
use ieee.std_logic_1164.all;
12+
13+
architecture test_reset_a of test_runner is
14+
begin
15+
main : process
16+
begin
17+
test_runner_setup(runner, nested_runner_cfg);
18+
19+
d <= (others => '1');
20+
reset <= '1';
21+
wait until rising_edge(clk);
22+
wait for 0 ns;
23+
check_equal(q, 0);
24+
25+
test_runner_cleanup(runner);
26+
end process;
27+
28+
test_runner_watchdog(runner, 10 * clk_period);
29+
end;
30+
31+
configuration test_reset of tb_selecting_test_runner_with_vhdl_configuration is
32+
for tb
33+
for test_runner_inst : test_runner
34+
use entity work.test_runner(test_reset_a);
35+
end for;
36+
end for;
37+
end;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-- This Source Code Form is subject to the terms of the Mozilla Public
2+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
4+
--
5+
-- Copyright (c) 2014-2023, Lars Asplund lars.anders.asplund@gmail.com
6+
7+
library ieee;
8+
use ieee.std_logic_1164.all;
9+
10+
entity test_runner is
11+
generic(
12+
clk_period : time;
13+
width : positive;
14+
nested_runner_cfg : string
15+
);
16+
port(
17+
reset : out std_logic;
18+
clk : in std_logic;
19+
d : out std_logic_vector(width - 1 downto 0);
20+
q : in std_logic_vector(width - 1 downto 0)
21+
);
22+
end entity;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
-- This Source Code Form is subject to the terms of the Mozilla Public
2+
-- License, v. 2.0. If a copy of the MPL was not distributed with this file,
3+
-- You can obtain one at http://mozilla.org/MPL/2.0/.
4+
--
5+
-- Copyright (c) 2014-2023, Lars Asplund lars.anders.asplund@gmail.com
6+
7+
library vunit_lib;
8+
context vunit_lib.vunit_context;
9+
10+
library ieee;
11+
use ieee.std_logic_1164.all;
12+
13+
architecture test_state_change_a of test_runner is
14+
begin
15+
main : process
16+
begin
17+
test_runner_setup(runner, nested_runner_cfg);
18+
19+
reset <= '0';
20+
21+
d <= (others => '1');
22+
wait until rising_edge(clk);
23+
wait for 0 ns;
24+
check_equal(q, std_logic_vector'(q'range => '1'));
25+
26+
d <= (others => '0');
27+
wait until rising_edge(clk);
28+
wait for 0 ns;
29+
check_equal(q, 0);
30+
31+
test_runner_cleanup(runner);
32+
end process;
33+
34+
test_runner_watchdog(runner, 10 * clk_period);
35+
end;
36+
37+
configuration test_state_change of tb_selecting_test_runner_with_vhdl_configuration is
38+
for tb
39+
for test_runner_inst : test_runner
40+
use entity work.test_runner(test_state_change_a);
41+
end for;
42+
end for;
43+
end;

0 commit comments

Comments
 (0)