In many test benches I see the following pattern for clock generation:
process
begin
clk <= '0';
wait for 10 NS;
clk <= '1';
wait for 10 NS;
end process;
On other cases I see:
clk <= not clk after 10 ns;
The later is said to be better, because it is scheduled before any process is executed, and thus signals that are changed synchronously to the clk edge are handled properly.
The following sections from the LRM may seem to support this theory:
Page 169: 12.6.4 The simulation cycle
A simulation cycle consists of the following steps:
- b) Each active explicit signal in the model is updated. (Events may
occur on signals as a result.)
This should be the signals with a new projected value such as signals delayed by the after
.
- d) For each process P, if P is currently sensitive to a signal S and if
an event has occurred on S in this simulation cycle, then P resumes.
That would be most of the logic to be simulated
- e) Each nonpostponed process that has resumed in the current simulation
cycle is executed until it suspends.
And now all processes that are suspended by a wait for
are executed.
TL;DR:
- Is the
after
method always superior to thewait for
method? - Does it help to prevent the problems synchronously set input signals?
Best Answer
The simulator can't really be blamed for sometimes acting like the clock happened right after or right before the input changes, if you assign both
clk
and inputs usingwait for
. Asking if one style is superior or inferior to the other is, in a way, the wrong question. You need to specify behaviour in a non-ambiguous way, if you desire a deterministic and non-ambiguous output.What I've done for years and has worked for me pretty flawlessly (for synchronous designs) is to assign the inputs preceding them with
wait until rising_edge(clk)
orwait until falling_edge(clk)
. How you generate theclk
becomes unimportant. For simple testbenches theafter
one-liner does the job nicely and succinctly, but does not offer the flexibility of aprocess
withwait for
orwait until
statements.I have a little simple procedure that has served me well:
Which I keep in a
tb_pkg.vhd
that I alwaysuse
in testbenches.A use example could be:
Some designers assign their stimulus signals at the opposite edge to what the unit under test is sensitive to. I personally don't like doing this because it is not how the rest of the circuit will simulate, where signals change at the 'trigger' edge. But there is certainly nothing wrong with that approach. The above procedure can also be used for it.