Signal Transition detection - wait until... or if construct

M

MJ

Guest
Hello,

I have a question about "if (....)" and "wait until ..." usage in
testbenches.

I want to wait for a start pulse from the DUT in the testbench to do
some other things.
Process_A does not work. Ready1 is never set.
Process_B works. Why? What is wrong?

Here is are the two processes:

Process_A : process
begin
ready1 <= '0';
if (rising_edge(transfer_start)) then
-- do something ...
ready1 <= '1';
wait for c_clock_cycle;
ready1 <= '0';
end if;
wait;
end process;

Process_B : process
begin
ready2 <= '0';
wait until rising_edge(transfer_start);
-- do something ...
ready2 <= '1';
wait for c_clock_cycle;
ready2 <= '0';
wait;
end process;
 
On Sun, 10 Feb 2008 23:07:21 -0800 (PST), MJ <markus.jank@gmx.de>
wrote:

Hello,

I have a question about "if (....)" and "wait until ..." usage in
testbenches.

I want to wait for a start pulse from the DUT in the testbench to do
some other things.
Process_A does not work. Ready1 is never set.
Process_B works. Why? What is wrong?
Process_A executes at time zero, and again at regular intervals
because of the "wait for c_clock_cycle" delay. At each execution,
you test rising_edge(transfer_start). This expression is true
only in the exact delta cycle in which transfer_start goes from
low to high (0->1). It isn't going to happen - or, at least,
it isn't going to happen reliably.

Process_B stalls at the "wait until" statement. "wait until"
creates a sensitivity list from all signals mentioned in its
expression - in your case, simply transfer_Start. On *any*
transition of transfer_start, the sensitivity list is tripped
and the expression evaluated. If it's true, the wait is
released; if not, the wait goes back to sleep until the next
transition. Consequently you will asynchronously detect, and
execute on, the rising edge of transfer_start.

If you want to wait until transfer_start has a SYNCHRONOUS
rising edge - in other words, it was zero on the previous
clock event, but it's 1 on the current event- then you need
to store the old value yourself, and do an explicit comparison.
In a testbench, this works well:

procedure synch_await_rise (signal clock, control: std_logic);
variable old_control: std_logic := control;
begin
loop
wait until rising_edge(clock);
exit when control = '1' and old_control = '0';
old_control := control;
end loop;
end;

Here is are the two processes:

Process_A : process
begin
ready1 <= '0';
if (rising_edge(transfer_start)) then
-- do something ...
ready1 <= '1';
wait for c_clock_cycle;
ready1 <= '0';
end if;
wait;
end process;

Process_B : process
begin
ready2 <= '0';
wait until rising_edge(transfer_start);
-- do something ...
ready2 <= '1';
wait for c_clock_cycle;
ready2 <= '0';
wait;
end process;
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
jonathan.bromley@MYCOMPANY.com
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
MJ wrote:

Hello,

I have a question about "if (....)" and "wait until ..." usage in
testbenches.

I want to wait for a start pulse from the DUT in the testbench to do
some other things.
Process_A does not work. Ready1 is never set.
Process_B works. Why? What is wrong?

Here is are the two processes:

Process_A : process
begin
ready1 <= '0';
if (rising_edge(transfer_start)) then
-- do something ...
ready1 <= '1';
wait for c_clock_cycle;
ready1 <= '0';
end if;
wait;
end process;
Jonathan Bromley wrote:

On Sun, 10 Feb 2008 23:07:21 -0800 (PST), MJ <markus.jank@gmx.de

Process_A executes at time zero, and again at regular intervals
because of the "wait for c_clock_cycle" delay. At each execution,
you test rising_edge(transfer_start). This expression is true
only in the exact delta cycle in which transfer_start goes from
low to high (0->1). It isn't going to happen - or, at least,
it isn't going to happen reliably.

It is not going to happen at all, because transfer_start is not in the
sensitivity list, nor is there a wait on this signal.

What will happen is: Process_A is executed at time zero. Signal ready1 will
be driven '0', and because at time zero there will be no rising edge on
transfer start, the condition of the 'if' will be false. Hence the wait
statement is executed and the process will fall asleep for ever.

If the OP wants to use an 'if', he should add transfer_start to the
sensitivity list, so the process is woken up on each event on this signal:

Process_A : process(transfer_start)
begin
ready1 <= '0';
if (rising_edge(transfer_start)) then
-- do something ...
ready1 <= '1';
wait for c_clock_cycle;
ready1 <= '0';
end if;
end process;

A wait statement is not needed and not allowed if you use a sensitivity
list.

The only difference with Process_B is that Process_B will work only for one
rising edge on transfer_start. After it has driven ready2 low, the process
will be suspended for ever (by the wait statement without arguments).
Subsequent events on transfer_start will have no effect.

--
Paul Uiterlinden
www.aimvalley.nl
e-mail addres: remove the not.
 
Thank you for your help.

There is much I have to learn.
I will study again the "process" chapter in vhdl documentation.

Kind Regards

Markus
 

Welcome to EDABoard.com

Sponsor

Back
Top