There are different ways to wait on a signal change in VHDL. In my testbench I need to wait on a signal but if it does not change in say 100us, then I must continue the test. How to do this?
3 Answers
If you are just looking for a change, using a wait
with both an on signal
and for timeout-value
gets the job done:
wait on A for 100 us ;
When you are looking for more interesting things, you can also use the until. For example, resume when Ready='1' at the rising edge of clock, but timeout if 100 clocks go by and the condition does not happen:
wait on Clk until rising_edge(Clk) and Ready='1' for 100 * TPeriod_Clk ;
-- Check for ready not responding
assert rising_edge(Clk) and Ready='1' report "no ready. DUT is not responding" severity FAILURE ;
```
-
\$\begingroup\$ Of course there's some risk when duplicating the condition between the wait and the subsequent assert... in this example the assertion can pass even though the wait was never satisfied and timed out. \$\endgroup\$ Jul 28, 2023 at 15:06
-
\$\begingroup\$ @BenVoigt No. If Ready was not 1 when the wait wakes up, it will not be 1 during the assert. Signals only update when a process suspends and since this process uses a wait statement, that would take another wait statement inserted before the assert statement. The only thing this check can miss is that the wait timed out due to Clk not rising. If Clk did not rise, the test case is hopelessly dead and is unlikely to get far - so it is pointless to check for that or worry about it. \$\endgroup\$ Jul 29, 2023 at 16:10
-
1\$\begingroup\$ There are two ways for the wait to timeout but still pass the assert. First is if the clock is not running. Second is if
Ready
is high during part of the clock cycle, but not during the rising clock edge. \$\endgroup\$ Jul 30, 2023 at 22:51 -
\$\begingroup\$ @BenVoigt Good point. In the general case, such as I proposed here, that would be a problem, and hence, I updated it. OTOH, in the verification components where I use this sort of code, the entire process maintains alignment to clock and the timeout is based on multiples of the clock period. As a result, the wait statement wakes up on the rising edge of clock - even when it wakes up due to timeout. \$\endgroup\$ Aug 1, 2023 at 1:27
You can just combine a wait for
with a wait until
statement. For your example:
wait until your_bestie_signal`event for 100us;
This will return when an event is registered on the signal or 100 microseconds of simulation time have passed.
-
\$\begingroup\$ Wow its that simple? I wonder why none of my books or resources mention this. \$\endgroup\$– gyuunyuuJul 29, 2019 at 13:03
-
1\$\begingroup\$ @Quantum0xE7 Dunno, it's vaguely explained in my Doulos VHDL Golden Reference Guide and you can find some tutorials if you search for "vhdl wait until for", but honestly, I just remember reading the syntax in a SystemC test-bench tutorial where they mentioned that
sc_core::wait(a, b)
is equivalent towait until a for b
. \$\endgroup\$ Jul 29, 2019 at 16:11 -
\$\begingroup\$ It's not combining them, one is a condition clause the other is a timeout clause. See IEEE Std 1076-2008 10.2 Wait statement. A condition is an expression providing a Boolean value. An explicit timeout clause provides a time expression, which for an implicit timeout clause is TIME'HIGH. Note the standard also requires a separator between an numeric literal and an identifier as in the answer's time expression (15.2). \$\endgroup\$– user8352Jul 29, 2019 at 16:58
-
\$\begingroup\$ A time expression isn't a lexical element and there is a -2008 lexical element (Bit string) where the lack of a separator can be ambiguous despite a couple of commercial implementations treating time expressions as lexical elements. \$\endgroup\$– user8352Jul 29, 2019 at 17:10
-
\$\begingroup\$ @user8352 Feel free to edit or provide a more correct answer, it's been years since I wrote a VHDL test, so I'm sure you're right. \$\endgroup\$ Jul 30, 2019 at 7:57
Tested:
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.Numeric_STD.ALL;
entity wwt is end entity;
architecture bhv of wwt is
signal ts1, tm1, ts2, tm2 : std_logic := '0';
begin
tp1: process
begin tm1 <= '1';
ts1 <= '1' after 100 ns;
wait until ts1 = '1' for 200 ns;
ts1 <= '0' after 100 ns;
wait until ts1 = '0' for 50 ns;
tm1 <= '0'; wait for 100 ns;
end process;
tp2: process
begin tm2 <= '1';
ts2 <= '1' after 100 ns;
wait until ts2'event for 200 ns;
ts2 <= '0' after 100 ns;
wait until ts2'event for 50 ns;
tm2 <= '0'; wait for 100 ns;
end process;
end architecture bhv;
And all the waits are terminated by whatever occurs first (event, event+signal value, timeout). Note: wait until = ; means waiting until both: (1) 'event to occur; and (2) the signal value to match;
-- if the signal initially has the specified value, the wait don't recognize the condition to match, as there is no event then - e.g. a "sig <= '1'; wait until sig = '1' for 1 ms;" waits 1 ms.