Wait is very useful operation for simulation. It easily allows to simulate timing or signal dependencies. In next posts I am going to use it more often, so I wanted to give a short information about that statement.
In general, wait statements suspend the execution of the process. There are four different ways to use wait:
- wait until condition
When simulator encounters that operation, it stops executing the process. It will jump to the next operation only after condition evaluates to true.
- wait on signal
Simulator will stop at that operation and will resume execution of the process whenever any of the signals change the state.
- wait for time
In simulation execution of the process is suspended by the given time.
Simulator stops executing the process.
To better understand how wait statements work, I prepared short tests and simulated following code:
library ieee; use ieee.std_logic_1164.all; entity WaitTests is end entity; architecture WaitTests_rtl of WaitTests is signal clk :std_logic; signal a :std_logic := '1'; signal b :std_logic := '0'; signal oa :std_logic := '0'; signal ob :std_logic := '0'; constant ClkGenConst :time := 10 ns; begin WaitFor: process begin clk <= '0' after ClkGenConst, '1' after 2*ClkGenConst; wait for 2*ClkGenConst; end process; WaitUntil: process begin wait until rising_edge(a); oa <= '1'; end process; WaitOn: process begin wait on b; ob <= '1'; wait on b; ob <= '0'; wait until falling_edge(b); ob <= '1'; end process; run_proc: process begin wait for 100 ns; a <= '0'; b <= '1'; wait for 100 ns; a <= '1'; b <= '0'; wait for 100 ns; b <= '1'; wait for 100 ns; b <= '0'; wait; end process; end architecture;
Wait & Synthesis
As I wrote before, wait statement is mainly dedicated and used in testbenches. It can be also used in synthesis but with some limitations. I made some simple tests with Altera and Xilinx compiler. Below you can find how compilers try to synthesise wait statements.
* I did not test wait for, because it is not synthesizable by definition. I did not test wait either (I have no idea why someone would like to use it in hardware?). I tested only wait on and wait until.
library ieee; use ieee.std_logic_1164.all; entity WaitTests is port ( clka :in std_logic; clkb :in std_logic; a :in std_logic; b :in std_logic; oa :out std_logic; ob :out std_logic ); end entity; architecture WaitTests_rtl of WaitTests is begin WaitUntil1: process begin wait until rising_edge(clka); oa <= a; end process; WaitUntil2: process begin wait until clkb = '1'; ob <= b; end process; end architecture;
Additional processes for testing:
- wait on
WaitOn: process begin wait on clkb; ob <= b; end process;
- two wait until in one process
WaitUntil: process begin wait until rising_edge(clka); oa <= a; wait until clka = '1'; oa <= b; end process;
Altera treats wait until as clocks:
Synthesis of wait on fails:
More than one wait statement in the process is not allowed:
Regarding wait until, Xilinx compiler gives results exactly the same as Altera.
Xilinx tried to generate some structure for wait on, but I expected to see here something else. Not sure which approach is better – give unexpected result (Xilinx) or not compile the code at all (Altera).
Xilinx, like Altera, does not support more than one wait statement in the process:
Waits are not recommended for synthesis and this is bad practice to use them there. Examples show that you can’t be confident about results of synthesis. Use waits in testbenches in simulation where are very powerful function, but not for synthesis!
*** *** ***
All source codes used in that post you can find on gitlab.com.
*** *** ***