aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--testsuite/pyunit/dom/StopWatch.py (renamed from testsuite/pyunit/dom/SimplePackage.py)56
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/Counter.vhdl45
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl58
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl21
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl127
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/Utilities.pkg.vhdl99
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl90
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/seg7_Encoder.vhdl46
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/toplevel.Display.vhdl65
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/toplevel.Encoder.vhdl42
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.tb.vhdl58
-rw-r--r--testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl118
12 files changed, 813 insertions, 12 deletions
diff --git a/testsuite/pyunit/dom/SimplePackage.py b/testsuite/pyunit/dom/StopWatch.py
index 9c62db4a1..a51c44cf2 100644
--- a/testsuite/pyunit/dom/SimplePackage.py
+++ b/testsuite/pyunit/dom/StopWatch.py
@@ -42,22 +42,54 @@ if __name__ == "__main__":
exit(1)
-class SimplePackage(TestCase):
+class Display(TestCase):
_root = Path(__file__).resolve().parent.parent
- _filename: Path = _root / "SimplePackage.vhdl"
+ _sourceDirectory: Path = _root / "dom/examples/StopWatch"
- def test_Package(self):
+ def test_Encoder(self):
design = Design()
- document = Document(self._filename)
- design.Documents.append(document)
+ files = (
+ Path("Utilities.pkg.vhdl"),
+ Path("StopWatch.pkg.vhdl"),
+ Path("seg7_Encoder.vhdl"),
+ Path("toplevel.Encoder.vhdl"),
+ )
+ for file in files:
+ document = Document(self._sourceDirectory / file)
+ design.Documents.append(document)
- self.assertEqual(1, len(design.Documents[0].Packages))
- self.assertEqual("pack_1", design.Documents[0].Packages[0].Identifier)
+ self.assertEqual(len(files), len(design.Documents))
- def test_PackageBody(self):
+ def test_Display(self):
design = Design()
- document = Document(self._filename)
- design.Documents.append(document)
+ files = (
+ Path("Utilities.pkg.vhdl"),
+ Path("StopWatch.pkg.vhdl"),
+ Path("Counter.vhdl"),
+ Path("seg7_Encoder.vhdl"),
+ Path("seg7_Display.vhdl"),
+ Path("toplevel.Display.vhdl"),
+ )
+ for file in files:
+ document = Document(self._sourceDirectory / file)
+ design.Documents.append(document)
- self.assertEqual(1, len(design.Documents[0].PackageBodies))
- self.assertEqual("pack_1", design.Documents[0].PackageBodies[0].Identifier)
+ self.assertEqual(len(files), len(design.Documents))
+
+ def test_StopWatch(self):
+ design = Design()
+ files = (
+ Path("Utilities.pkg.vhdl"),
+ Path("StopWatch.pkg.vhdl"),
+ Path("Counter.vhdl"),
+ Path("seg7_Encoder.vhdl"),
+ Path("seg7_Display.vhdl"),
+ Path("StopWatch.vhdl"),
+ Path("Debouncer.vhdl"),
+ Path("toplevel.StopWatch.vhdl"),
+ )
+ for file in files:
+ document = Document(self._sourceDirectory / file)
+ design.Documents.append(document)
+
+ self.assertEqual(len(files), len(design.Documents))
diff --git a/testsuite/pyunit/dom/examples/StopWatch/Counter.vhdl b/testsuite/pyunit/dom/examples/StopWatch/Counter.vhdl
new file mode 100644
index 000000000..3ef284b98
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/Counter.vhdl
@@ -0,0 +1,45 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+use work.Utilities.all;
+
+
+entity Counter is
+ generic (
+ MODULO : positive;
+ BITS : natural := log2(MODULO)
+ );
+ port (
+ Clock : in std_logic;
+ Reset : in std_logic;
+ Enable : in std_logic;
+
+ Value : out unsigned(BITS - 1 downto 0);
+ WrapAround : out std_logic
+ );
+end entity;
+
+
+architecture rtl of Counter is
+ signal CounterValue : unsigned(log2(MODULO) - 1 downto 0) := (others => '0');
+begin
+ process (Clock)
+ begin
+ if rising_edge(Clock) then
+ if ((Reset or WrapAround) = '1') then
+ CounterValue <= (others => '0');
+ elsif (Enable = '1') then
+ CounterValue <= CounterValue + 1;
+ end if;
+ end if;
+ end process;
+
+ Value <= resize(CounterValue, BITS);
+ WrapAround <= Enable when (CounterValue = MODULO - 1) else '0';
+end architecture;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl b/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl
new file mode 100644
index 000000000..18207c7f1
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/Debouncer.vhdl
@@ -0,0 +1,58 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+use work.Utilities.all;
+
+
+entity Debouncer is
+ generic (
+ CLOCK_PERIOD : time := 10 ns;
+ DEBOUNCE_TIME : time := 3 ms;
+
+ BITS : positive
+ );
+ port (
+ Clock : in std_logic;
+
+ Input : in std_logic_vector(BITS - 1 downto 0);
+ Output : out std_logic_vector(BITS - 1 downto 0) := (others => '0')
+ );
+end entity;
+
+architecture rtl of Debouncer is
+ constant DEBOUNCE_COUNTER_MAX : positive := DEBOUNCE_TIME / (CLOCK_PERIOD* ite(IS_SIMULATION, 20, 1));
+ constant DEBOUNCE_COUNTER_BITS : positive := log2(DEBOUNCE_COUNTER_MAX);
+
+begin
+ assert false report "CLOCK_PERIOD: " & time'image(CLOCK_PERIOD);
+ assert false report "DEBOUNCE_TIME: " & time'image(DEBOUNCE_TIME);
+ --assert false report "DEBOUNCE_COUNTER_MAX: " & to_string(10 ns);
+ --assert false report "INTEGER'high: " & integer'image(integer'high);
+
+ genBits: for i in Input'range generate
+ signal DebounceCounter : signed(DEBOUNCE_COUNTER_BITS downto 0) := to_signed(DEBOUNCE_COUNTER_MAX - 3, DEBOUNCE_COUNTER_BITS + 1);
+ begin
+ process (Clock)
+ begin
+ if rising_edge(Clock) then
+ -- restart counter, whenever Input(i) was unstable within DEBOUNCE_TIME_MS
+ if (Input(i) /= Output(i)) then
+ DebounceCounter <= DebounceCounter - 1;
+ else
+ DebounceCounter <= to_signed(DEBOUNCE_COUNTER_MAX - 3, DebounceCounter'length);
+ end if;
+
+ -- latch input bit, if input was stable for DEBOUNCE_TIME_MS
+ if (DebounceCounter(DebounceCounter'high) = '1') then
+ Output(i) <= Input(i);
+ end if;
+ end if;
+ end process;
+ end generate;
+end architecture;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl
new file mode 100644
index 000000000..3bcafdd6d
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.pkg.vhdl
@@ -0,0 +1,21 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+
+package StopWatch_pkg is
+ subtype T_BCD is unsigned(3 downto 0);
+ type T_BCD_Vector is array(natural range <>) of T_BCD;
+
+ type T_DIGIT_CONFIGURATION is record
+ Modulo : positive;
+ Dot : std_logic;
+ end record;
+
+ type T_STOPWATCH_CONFIGURATION is array(natural range <>) of T_DIGIT_CONFIGURATION;
+end package;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl
new file mode 100644
index 000000000..c7c9068ab
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/StopWatch.vhdl
@@ -0,0 +1,127 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+use work.Utilities.all;
+use work.StopWatch_pkg.all;
+
+
+entity Stopwatch is
+ generic (
+ CLOCK_PERIOD : time := 10 ns;
+
+ TIMEBASE : time;
+ CONFIG : T_STOPWATCH_CONFIGURATION
+ );
+ port (
+ Clock : in std_logic;
+ Reset : in std_logic;
+
+ Start : in std_logic;
+
+ Digits : out T_BCD_Vector(CONFIG'length - 1 downto 0);
+ Dots : out std_logic_vector(CONFIG'length - 1 downto 0)
+ );
+end entity;
+
+
+architecture trl of Stopwatch is
+ type T_STATE is (ST_RESET, ST_IDLE, ST_COUNTING, ST_PAUSE);
+
+ signal State : T_STATE := ST_IDLE;
+ signal NextState : T_STATE;
+
+ signal FSM_Reset : std_logic;
+ signal FSM_Enable : std_logic;
+
+ signal Tick : std_logic;
+ signal Overflows : std_logic_vector(CONFIG'length downto 0);
+
+
+begin
+ process(Clock)
+ begin
+ if rising_edge(Clock) then
+ if (Reset = '1') then
+ State <= ST_RESET;
+ else
+ State <= NextState;
+ end if;
+ end if;
+ end process;
+
+ process(State, Start)
+ begin
+ NextState <= State;
+
+ FSM_Reset <= '0';
+ FSM_Enable <= '0';
+
+ case State is
+ when ST_RESET =>
+ FSM_Reset <= '1';
+ NextState <= ST_IDLE;
+
+ when ST_IDLE =>
+ if (Start = '1') then
+ NextState <= ST_COUNTING;
+ end if;
+
+ when ST_COUNTING =>
+ FSM_Enable <= '1';
+
+ if (Start = '1') then
+ NextState <= ST_PAUSE;
+ end if;
+
+ when ST_PAUSE =>
+ if (Start = '1') then
+ NextState <= ST_COUNTING;
+ end if;
+
+ when others =>
+ NextState <= ST_RESET;
+
+ end case;
+ end process;
+
+ TimeBaseCnt: entity work.Counter
+ generic map (
+ MODULO => TIMEBASE / (CLOCK_PERIOD * ite(IS_SIMULATION, 100, 1)),
+ BITS => 0
+ )
+ port map (
+ Clock => Clock,
+ Reset => FSM_Reset,
+ Enable => FSM_Enable,
+
+ Value => open,
+ WrapAround => Tick
+ );
+
+ Overflows(0) <= Tick;
+
+ genDigits: for i in CONFIG'range generate
+ cnt: entity work.Counter
+ generic map (
+ MODULO => CONFIG(i).Modulo,
+ BITS => Digits(i)'length
+ )
+ port map (
+ Clock => Clock,
+ Reset => FSM_Reset,
+ Enable => Overflows(i),
+
+ Value => Digits(i),
+ WrapAround => Overflows(i + 1)
+ );
+
+ Dots(i) <= CONFIG(i).Dot;
+ end generate;
+
+end architecture;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/Utilities.pkg.vhdl b/testsuite/pyunit/dom/examples/StopWatch/Utilities.pkg.vhdl
new file mode 100644
index 000000000..8daf39614
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/Utilities.pkg.vhdl
@@ -0,0 +1,99 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+
+package Utilities is
+ type freq is range integer'low to integer'high units
+ Hz;
+ kHz = 1000 Hz;
+ MHz = 1000 kHz;
+ GHz = 1000 MHz;
+ THz = 1000 GHz;
+ end units;
+
+ -- deferred constant
+ constant IS_SIMULATION : boolean;
+
+ function ite(condition : boolean; ThenValue : integer; ElseValue : integer) return integer;
+
+ function log2(Value : positive) return positive;
+
+ function bin2onehot(binary : std_logic_vector; bits : natural := 0) return std_logic_vector;
+ function bin2onehot(binary : unsigned; bits : natural := 0) return std_logic_vector;
+
+ function to_index(value : unsigned; max : positive) return natural;
+ function to_index(value : natural; max : positive) return natural;
+end package;
+
+
+package body Utilities is
+ function simulation return boolean is
+ variable result : boolean := FALSE;
+ begin
+ -- synthesis translate_off
+ result := TRUE;
+ -- synthesis translate_on
+ return result;
+ end function;
+
+ -- deferred constant initialization
+ constant IS_SIMULATION : boolean := simulation;
+
+ function ite(condition : boolean; ThenValue : integer; ElseValue : integer) return integer is
+ begin
+ if condition then
+ return ThenValue;
+ else
+ return ElseValue;
+ end if;
+ end function;
+
+ function log2(Value : positive) return positive is
+ variable twosPower : natural := 1;
+ variable result : natural := 0;
+ begin
+ while (twosPower < Value) loop
+ twosPower := twosPower * 2;
+ result := result + 1;
+ end loop;
+ return result;
+ end function;
+
+ function bin2onehot(binary : std_logic_vector; bits : natural := 0) return std_logic_vector is
+ begin
+ return bin2onehot(unsigned(binary), bits);
+ end function;
+
+ function bin2onehot(binary : unsigned; bits : natural := 0) return std_logic_vector is
+ variable result : std_logic_vector(2**binary'length - 1 downto 0) := (others => '0');
+ begin
+ result(to_integer(binary)) := '1';
+
+ if (bits = 0) then
+ return result;
+ else
+ return result(bits - 1 downto 0);
+ end if;
+ end function;
+
+ function to_index(value : unsigned; max : positive) return natural is
+ begin
+ return to_index(to_integer(value), max);
+ end function;
+
+ function to_index(value : natural; max : positive) return natural is
+ begin
+ if (value <= max) then
+ return value;
+ else
+ return max;
+ end if;
+ -- return minimum(value, max);
+ end function;
+end package body;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl b/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl
new file mode 100644
index 000000000..c3771ba68
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/seg7_Display.vhdl
@@ -0,0 +1,90 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+use work.Utilities.all;
+use work.StopWatch_pkg.all;
+
+
+entity seg7_Display is
+ generic (
+ CLOCK_PERIOD : time := 10 ns;
+ REFRESH_RATE : time := 200 us;
+ DIGITS : positive
+ );
+ port (
+ Clock : in std_logic;
+
+ DigitValues : in T_BCD_Vector(DIGITS - 1 downto 0);
+ DotValues : in std_logic_vector(DIGITS - 1 downto 0) := (others => '0');
+
+ Seg7_Segments : out std_logic_vector(7 downto 0);
+ Seg7_Selects : out std_logic_vector(DIGITS - 1 downto 0)
+ );
+end entity;
+
+
+architecture rtl of seg7_Display is
+ constant TIMEBASE_COUNTER_MAX : positive := REFRESH_RATE / (CLOCK_PERIOD * ite(IS_SIMULATION, 1_000, 1));
+
+ signal Timebase_Counter : unsigned(log2(TIMEBASE_COUNTER_MAX) - 1 downto 0) := (others => '0');
+ signal Timebase_Tick : std_logic;
+
+ signal Digit_Select : unsigned(log2(DIGITS) - 1 downto 0) := (others => '0');
+ signal Digit_Select_ov : std_logic;
+
+ signal Digit : T_BCD;
+ signal Dot : std_logic;
+begin
+ -- refresh rate
+ process(Clock)
+ begin
+ if rising_edge(Clock) then
+ if (Timebase_Tick = '1') then
+ Timebase_Counter <= (others => '0');
+ else
+ Timebase_Counter <= Timebase_Counter + 1;
+ end if;
+ end if;
+ end process;
+
+ Timebase_Tick <= '1' when (Timebase_Counter = TIMEBASE_COUNTER_MAX - 1) else '0';
+
+
+ -- counter to select digits (time multiplexing)
+ process(Clock)
+ begin
+ if rising_edge(Clock) then
+ if (Timebase_Tick = '1') then
+ if (Digit_Select_ov = '1') then
+ Digit_Select <= (others => '0'); -- to_unsigned(5, Digit_Select'length);
+ else
+ Digit_Select <= Digit_Select + 1;
+ end if;
+ end if;
+ end if;
+ end process;
+
+ Digit_Select_ov <= '1' when (Digit_Select = DIGITS - 1) else '0';
+
+ -- multiplexer
+ Digit <= DigitValues(to_index(Digit_Select, DigitValues'high));
+ Dot <= DotValues(to_index(Digit_Select, DotValues'high));
+
+ -- 7-segment encoder
+ enc: entity work.seg7_Encoder
+ port map (
+ BCDValue => Digit,
+ Dot => Dot,
+
+ Seg7Code => Seg7_Segments
+ );
+
+
+ Seg7_Selects <= bin2onehot(Digit_Select, DIGITS);
+end architecture;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/seg7_Encoder.vhdl b/testsuite/pyunit/dom/examples/StopWatch/seg7_Encoder.vhdl
new file mode 100644
index 000000000..e4c731ff9
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/seg7_Encoder.vhdl
@@ -0,0 +1,46 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+use work.Utilities.all;
+use work.StopWatch_pkg.all;
+
+
+entity seg7_Encoder is
+ port (
+ BCDValue : in T_BCD;
+ Dot : in std_logic := '0';
+
+ Seg7Code : out std_logic_vector(7 downto 0)
+ );
+end entity;
+
+
+architecture rtl of seg7_Encoder is
+
+begin
+ process(BCDValue, Dot)
+ variable temp : std_logic_vector(6 downto 0);
+ begin
+ case BCDValue is -- segments: GFEDCBA -- Segment Pos. Index Pos.
+ when x"0" => temp := "0111111"; --
+ when x"1" => temp := "0000110"; --
+ when x"2" => temp := "1011011"; -- AAA 000
+ when x"3" => temp := "1001111"; -- F B 5 1
+ when x"4" => temp := "1100110"; -- F B 5 1
+ when x"5" => temp := "1101101"; -- GGG 666
+ when x"6" => temp := "1111101"; -- E C 4 2
+ when x"7" => temp := "0000111"; -- E C 4 2
+ when x"8" => temp := "1111111"; -- DDD DOT 333 7
+ when x"9" => temp := "1101111"; --
+ when others => temp := "XXXXXXX"; --
+ end case;
+
+ Seg7Code <= Dot & temp;
+ end process;
+end architecture;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/toplevel.Display.vhdl b/testsuite/pyunit/dom/examples/StopWatch/toplevel.Display.vhdl
new file mode 100644
index 000000000..67228a5ac
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/toplevel.Display.vhdl
@@ -0,0 +1,65 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+use work.Utilities.all;
+use work.StopWatch_pkg.all;
+
+
+entity toplevel is
+ generic (
+ constant CLOCK_PERIOD : time := 10 ns
+ );
+ port (
+ NexysA7_SystemClock : in std_logic;
+
+ NexysA7_GPIO_Switch : in std_logic_vector(15 downto 0);
+
+ NexysA7_GPIO_Seg7_Cathode_n : out std_logic_vector(7 downto 0);
+ NexysA7_GPIO_Seg7_Anode_n : out std_logic_vector(7 downto 0)
+ );
+end entity;
+
+
+architecture rtl of toplevel is
+ signal Digits : T_BCD_Vector(5 downto 0);
+
+ signal Cathode : std_logic_vector(7 downto 0);
+ signal Anode : std_logic_vector(Digits'range);
+
+begin
+ -- connect switches to first 4 digits
+ genDigits: for i in 0 to 3 generate
+ Digits(i) <= unsigned(NexysA7_GPIO_Switch(i * 4 + 3 downto i * 4));
+ end generate;
+
+ -- do arithmetic calculations on next 2 digits
+ Digits(4) <= Digits(1) + Digits(0);
+ Digits(5) <= Digits(3) - Digits(2);
+
+
+ -- 7-segment display
+ display: entity work.seg7_Display
+ generic map (
+ CLOCK_PERIOD => CLOCK_PERIOD,
+ DIGITS => Digits'length
+ )
+ port map (
+ Clock => NexysA7_SystemClock,
+
+ DigitValues => Digits,
+ DotValues => 6d"16",
+
+ Seg7_Segments => Cathode,
+ Seg7_Selects => Anode
+ );
+
+ -- convert low-active outputs
+ NexysA7_GPIO_Seg7_Cathode_n <= not Cathode;
+ NexysA7_GPIO_Seg7_Anode_n <= not ((NexysA7_GPIO_Seg7_Anode_n'high downto Anode'length => '0') & Anode);
+end architecture;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/toplevel.Encoder.vhdl b/testsuite/pyunit/dom/examples/StopWatch/toplevel.Encoder.vhdl
new file mode 100644
index 000000000..7775a6eb6
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/toplevel.Encoder.vhdl
@@ -0,0 +1,42 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+use work.Utilities.all;
+use work.StopWatch_pkg.all;
+
+
+entity toplevel is
+ port (
+ NexysA7_GPIO_Switch : in std_logic_vector(3 downto 0);
+
+ NexysA7_GPIO_Seg7_Cathode_n : out std_logic_vector(7 downto 0);
+ NexysA7_GPIO_Seg7_Anode_n : out std_logic_vector(7 downto 0)
+ );
+end entity;
+
+
+architecture rtl of toplevel is
+ signal Cathode : std_logic_vector(7 downto 0);
+ signal Anode : std_logic_vector(7 downto 0);
+
+begin
+
+ -- 7-segment encoder
+ encoder: entity work.seg7_Encoder
+ port map (
+ BCDValue => unsigned(NexysA7_GPIO_Switch),
+ Dot => '1',
+
+ Seg7Code => Cathode
+ );
+
+ -- convert low-active outputs
+ NexysA7_GPIO_Seg7_Cathode_n <= not Cathode;
+ NexysA7_GPIO_Seg7_Anode_n <= not x"01";
+end architecture;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.tb.vhdl b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.tb.vhdl
new file mode 100644
index 000000000..a334475c4
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.tb.vhdl
@@ -0,0 +1,58 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+library lib_StopWatch;
+use lib_StopWatch.Utilities.all;
+use lib_StopWatch.StopWatch_pkg.all;
+
+
+entity toplevel_tb is
+end entity;
+
+
+architecture tb of toplevel_tb is
+ constant CLOCK_PERIOD : time := 10 ns;
+
+ signal StopSimulation : std_logic := '0';
+ signal Clock : std_logic := '1';
+ signal Reset : std_logic := '1';
+
+ signal StartButton : std_logic := '0';
+
+begin
+ StopSimulation <= '1' after 30 ms;
+
+ Clock <= (Clock xnor StopSimulation) after CLOCK_PERIOD / 2;
+ Reset <= '0' after 2 us,
+ '1' after 3 us,
+ '0' after 20 ms,
+ '1' after 20 ms + 2 us;
+ StartButton <= '1' after 10 us,
+ '0' after 15 us,
+ '1' after 10 ms,
+ '0' after 10 ms + 1 us,
+ '1' after 12 ms,
+ '0' after 12 ms + 2 us,
+ '1' after 22 ms,
+ '0' after 22 ms + 2 us;
+
+ DUT: entity lib_StopWatch.toplevel
+ generic map (
+ CLOCK_PERIOD_NS => CLOCK_PERIOD / 1 ns
+ )
+ port map (
+ Clock => Clock,
+ Reset_n => Reset,
+
+ Button(0) => StartButton,
+ Seg7_Cathode_n => open,
+ Seg7_Anode_n => open
+ );
+
+end architecture;
diff --git a/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl
new file mode 100644
index 000000000..1c8547446
--- /dev/null
+++ b/testsuite/pyunit/dom/examples/StopWatch/toplevel.StopWatch.vhdl
@@ -0,0 +1,118 @@
+-- Author: Patrick Lehmann
+-- License: MIT
+--
+-- A generic counter module used in the StopWatch example.
+--
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+use work.Utilities.all;
+use work.StopWatch_pkg.all;
+
+
+entity toplevel is
+ generic (
+ constant CLOCK_PERIOD : time := 10 ns
+ );
+ port (
+ NexysA7_SystemClock : in std_logic;
+ NexysA7_GPIO_Button_Reset_n : in std_logic;
+
+ NexysA7_GPIO_Button : in std_logic_vector(0 downto 0);
+ NexysA7_GPIO_Seg7_Cathode_n : out std_logic_vector(7 downto 0);
+ NexysA7_GPIO_Seg7_Anode_n : out std_logic_vector(7 downto 0)
+ );
+end entity;
+
+
+architecture rtl of toplevel is
+ constant STOPWATCH_CONFIGURATION : T_STOPWATCH_CONFIGURATION := (
+ 0 => (Modulo => 10, Dot => '0'),
+ 1 => (Modulo => 10, Dot => '0'),
+ 2 => (Modulo => 10, Dot => '0'),
+ 3 => (Modulo => 6, Dot => '0'),
+ 4 => (Modulo => 10, Dot => '0'),
+ 5 => (Modulo => 6, Dot => '0')
+ );
+
+ signal Board_Reset : std_logic;
+
+ signal Deb_Reset : std_logic;
+ signal Deb_Start : std_logic;
+ signal Deb_Start_d : std_logic := '0';
+ signal Deb_Start_re : std_logic;
+
+ signal Reset : std_logic;
+ signal Start : std_logic;
+
+
+ signal Digits : T_BCD_Vector(STOPWATCH_CONFIGURATION'length - 1 downto 0);
+
+ signal Cathode : std_logic_vector(7 downto 0);
+ signal Anode : std_logic_vector(Digits'range);
+
+begin
+ -- convert from low-active inputs
+ Board_Reset <= not NexysA7_GPIO_Button_Reset_n;
+
+ -- Debounce input signals
+ deb: entity work.Debouncer
+ generic map (
+ CLOCK_PERIOD => CLOCK_PERIOD,
+ BITS => 2
+ )
+ port map (
+ Clock => NexysA7_SystemClock,
+
+ Input(0) => Board_Reset,
+ Input(1) => NexysA7_GPIO_Button(0),
+ Output(0) => Deb_Reset,
+ Output(1) => Deb_Start
+ );
+
+ Reset <= Deb_Reset;
+
+ -- Rising edge detection
+ Deb_Start_d <= Deb_Start when rising_edge(NexysA7_SystemClock);
+ Deb_Start_re <= not Deb_Start_d and Deb_Start;
+
+ -- renaming
+ Start <= Deb_Start_re;
+
+ -- Stopwatch
+ sw: entity work.Stopwatch
+ generic map (
+ CLOCK_PERIOD => CLOCK_PERIOD,
+
+ TIMEBASE => 10 ms,
+ CONFIG => STOPWATCH_CONFIGURATION
+ )
+ port map (
+ Clock => NexysA7_SystemClock,
+ Reset => Reset,
+
+ Start => Start,
+
+ Digits => Digits
+ );
+
+ -- 7-segment display
+ display: entity work.seg7_Display
+ generic map (
+ CLOCK_PERIOD => CLOCK_PERIOD,
+ DIGITS => Digits'length
+ )
+ port map (
+ Clock => NexysA7_SystemClock,
+
+ DigitValues => Digits,
+
+ Seg7_Segments => Cathode,
+ Seg7_Selects => Anode
+ );
+
+ -- convert to low-active outputs
+ NexysA7_GPIO_Seg7_Cathode_n <= not Cathode;
+ NexysA7_GPIO_Seg7_Anode_n <= not ((NexysA7_GPIO_Seg7_Anode_n'high downto Anode'length => '0') & Anode);
+end architecture;