scheduling problem

A

Alexis POLTI

Guest
Hello !

I have a problem with Verilog scheduling semantic. Given the following code :

***************************************
module top;
reg clk;
reg d;

initial
begin
d = 0;
clk = 0;
#10 clk <= 1;
#15 $finish;
end

always @(posedge clk)
d <= 1;

bottom bottom(clk, d);

endmodule



module bottom(clk, d);
input clk;
input d;

always@(posedge clk)
begin
$display("bottom : got clock pulse, d=", d);
end

endmodule // bottom


***************************************

What should this code display ?

I might think that the correct value is "d=0" (as given by modelsim), but cver gives "d=1". I ask Pragamatic-software
(cver) why, and they answered me that this design has a race condition. Could someone please explain where exactly is
this race condition ?

Thanx !

Alex :)
 
Nope. There is no race condition here.
[...]
Well great answer, thanx a lot ! Seems that we have now to submit a patch to cver...

Alex :)
 
Agreed. This is not a race condition. The nonblocking assignment
to d should not finish until after the display has already executed.

It sounds like cver is not handling nonblocking assignments
correctly. Perhaps once they have executed any nonblocking
events (such as the assignment to clk), they fail to defer new
nonblocking events properly.
 
On Wed, 09 Feb 2005 17:42:07 +0100, Alexis POLTI <polti@enst.fr>
wrote:

Hello !

I have a problem with Verilog scheduling semantic. Given the following code :

***************************************
module top;
reg clk;
reg d;

initial
begin
d = 0;
clk = 0;
#10 clk <= 1;
#15 $finish;
end

always @(posedge clk)
d <= 1;

bottom bottom(clk, d);

endmodule



module bottom(clk, d);
input clk;
input d;

always@(posedge clk)
begin
$display("bottom : got clock pulse, d=", d);
end

endmodule // bottom


***************************************

What should this code display ?

I might think that the correct value is "d=0" (as given by modelsim), but cver gives "d=1". I ask Pragamatic-software
(cver) why, and they answered me that this design has a race condition. Could someone please explain where exactly is
this race condition ?

Thanx !

Alex :)
In this code there is no race condition. The non-blocking assignment
in the first always block should be queued till all events on the
current posedge clk are executed so the second always block should see
d=0.
Two different simulators I have also say d=0 which is the right value.
 
Alexis POLTI wrote:

(snip)

What should this code display ?

I might think that the correct value is "d=0" (as given by modelsim),
but cver gives "d=1". I ask Pragamatic-software (cver) why, and they
answered me that this design has a race condition. Could someone please
explain where exactly is this race condition ?
A race condition is when the logic depends on the order that
something happens in, when you can't depend on that order.

As one example, signals on two wires may arrive at the
destination logic at about the same time, such that you can't
guarantee the result.

Consider:

reg q1,q2;

always @(posedge clk) q1=d;

always @(posedge clk) q2=q1;

The represents two flip-flops forming a two bit shift register.
Note that q1 is used on the same clock edge that it is set.

If you build this using the TTL SN7474 flip flop you have a race
condition, but if you use an SN74LS74, with 0ns hold time, you
don't. I believe that zero hold time FF's are allowed in
verilog, though for synthesis you should verify that the target
logic family supports it.

In the case above, the simulator schedules the assignment to
come just after the clock transition so that it works. By
scheduling the change to occur after all the expressions are
evaluated it can avoid a race condition, even if the always
blocks are executed in a different order.


For

always@(posedge clk)
begin
$display("bottom : got clock pulse, d=", d);
end
there is no scheduling of signal changes involved. It is
completely dependent on the order of execution, and there isn't
anything you can do about it. Well,

always@(posedge clk)
begin
#1 $display("bottom : got clock pulse, d=", d);
end
to delay slightly.

-- glen
 
Thank you for your answer !

there is no scheduling of signal changes involved. It is completely
dependent on the order of execution, and there isn't anything you can do
about it.

In this code there is no race condition. The non-blocking assignment
in the first always block should be queued till all events on the
current posedge clk are executed so the second always block should see
d=0.
Two different simulators I have also say d=0 which is the right value.
Well, that might not be that simple. Verilog 2001 LRM states (p. 68) that port are modeled as continuous assigments. In
other words the bottom module instanciation is equivalent to

assign top.bottom.clk = top.clk;
assign top.bottom.d = top.d;

By examining the behaviour of cver (gpl version 2.1) with "cver -t -et +debug", it seems that it is modelling ports as
something like

assign top.bottom.clk = #0 top.clk;
assign top.bottom.d = #0 top.d;

which causes the propagation of clk and d to the bottom module to be executed after the non blocking assignment.
Then, by relying on the fact that any process can be suspended to execute another eligible process then resumed, there
may be effectively a race condition !

Which one (#0 or no #0) is the correct behaviour ? (if there is any correct behaviour...)

Thank you again !

Alex :)
 
Alexis POLTI wrote:
Hello !

I have a problem with Verilog scheduling semantic. Given the following
code :

***************************************
module top;
reg clk;
reg d;

initial
begin
d = 0;
clk = 0;
#10 clk <= 1;
#15 $finish;
end

always @(posedge clk)
d <= 1;

bottom bottom(clk, d);

endmodule



module bottom(clk, d);
input clk;
input d;

always@(posedge clk)
begin
$display("bottom : got clock pulse, d=", d);
end

endmodule // bottom


***************************************

What should this code display ?

I might think that the correct value is "d=0" (as given by modelsim),
but cver gives "d=1". I ask Pragamatic-software (cver) why, and they
answered me that this design has a race condition. Could someone please
explain where exactly is this race condition ?
This may not be the best style, but there is no race condition. The
$display triggered by the posedge clk must be scheduled before all
the non-blocking assignments initiated by the same posedge clk. The
answer is in the stratified event queue as defined by the Verilog
standard.

FWIW Icarus Verilog gets this right (d=0) too.

--
Steve Williams "The woods are lovely, dark and deep.
steve at icarus.com But I have promises to keep,
http://www.icarus.com and lines to code before I sleep,
http://www.picturel.com And lines to code before I sleep."
 
Alexis POLTI wrote:
Well, that might not be that simple. Verilog 2001 LRM states (p. 68)
that port are modeled as continuous assigments. In
other words the bottom module instanciation is equivalent to

assign top.bottom.clk = top.clk;
assign top.bottom.d = top.d;

By examining the behaviour of cver (gpl version 2.1) with "cver -t
-et +debug", it seems that it is modelling ports as
something like

assign top.bottom.clk = #0 top.clk;
assign top.bottom.d = #0 top.d;
First of all, the presence or absence of #0 makes no
difference to the behavior of a continuous assignment.
It is admittedly unclear in the LRM, but the statement
about #0 suspending the process and putting it on the
inactive event queue is talking about delay controls
in procedural code. It has nothing to do with #0
delays on continuous assignments, primitives or nets.

which causes the propagation of clk and d to the bottom module to be
executed after the non blocking assignment.

Even if the continuous assignment did schedule the
output as an inactive event, this would still not be
true. The propagation of clk and d would be inactive
events, which must still be processed before any
nonblocking assign events. Nonblocking assign events
are not processed until there are no active or
inactive events left for the current time.

Then, by relying on the fact that any process can be suspended to
execute another eligible process then resumed, there
may be effectively a race condition!
Nope. There is no race condition here.

Which one (#0 or no #0) is the correct behaviour ? (if there is any
correct behaviour...)

The #0 is irrelevant here, twice over.
 

Welcome to EDABoard.com

Sponsor

Back
Top