non-blocking assignments, #0 and IEEE

C

C. Hymans

Guest
Hi,

I have two questions about nonblocking assignments and their interaction
with other constructs.

1. In the following program, does the simulator necessarily have to
display "Hello!" ?

module main;
reg x;
initial begin
x = 0;
#1;
x <= 1;
x <= 0;
end
always @(posedge x) $display("Hello!");
endmodule

It seems that according to the IEEE standard (5.4.1), the updates
associated with nonblocking assignments must all be performed in the
same order as the code. And so, the last process must wake up.
However, I am not sure this is really important that a simulator conform
to this.


2. Then, I don't quite understand which must be executed first between #
0-delayed process or nonblocking assignments' update.
Consider the following program:

module main;
reg x;
initial begin
x = 0;
#1;
x <= 1;
$display("0: %b", x);
#0 $display("1: %b", x);
#0 $display("2: %b", x);
#0 $display("3: %b", x);
#1 $display("-: %b", x);
end
endmodule

When does the nonblocking assignment's update really take place ? When
does x become 1 ?
From the IEEE standard, I first understood that inactive events are
executed before nonblocking assignments' update events and so I thought
only the last display would show 1. However, I tested this on 2
simulators and got 2 different outputs. I am puzzled.


Thank you in advance for your answers,
Charles
 
"C. Hymans" <no@spam.fr> wrote in message
news:Xns9465BC14686E0chymans@193.252.19.141...

1. In the following program, does the simulator necessarily have to
display "Hello!" ?

module main;
reg x;
initial begin
x = 0;
#1;
x <= 1;
x <= 0;
end
always @(posedge x) $display("Hello!");
endmodule

It seems that according to the IEEE standard (5.4.1), the updates
associated with nonblocking assignments must all be performed in the
same order as the code.
Correct.

And so, the last process must wake up.
However, I am not sure this is really important
that a simulator conform
to this.
I think that simulators vary in their response to this, although
the LRM clearly says that "Every change in value of a net or
variable... is considered an update event", and "When an update
event is executed, all the processes that are sensitive to
that event are evaluated...". It's clear, however, that it's
foolish to write any code that depends for its correct behaviour
on the existence of a zero-width pulse.

You could just as easily have asked the question for
blocking assignment:

initial begin
x = 0;
#1
x = 1; // zero-width glitch
x = 0;
end

In this case, just like yours, the glitch on 'x' is truly of
zero width.

The problem doesn't arise in VHDL.

2. Then, I don't quite understand which must be executed first
between #0-delayed process or nonblocking assignments' update.
Consider the following program:

module main;
reg x;
initial begin
x = 0;
#1;
x <= 1;
$display("0: %b", x);
#0 $display("1: %b", x);
#0 $display("2: %b", x);
#0 $display("3: %b", x);
#1 $display("-: %b", x);
end
endmodule

When does the nonblocking assignment's update really take place ? When
does x become 1 ?
From the IEEE standard, I first understood that inactive events are
executed before nonblocking assignments' update events and so I thought
only the last display would show 1. However, I tested this on 2
simulators and got 2 different outputs. I am puzzled.
I agree with your reading of the LRM; I am *always* puzzled by
Verilog's scheduling model. However, in practice I hope you
will avoid any code that depends on the behaviour of #0 to
make it work correctly.

Maybe a simulator implementor, or one of the LRM authors,
can help us a little?
--
Jonathan Bromley, Consultant

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

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, Hampshire, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail: jonathan.bromley@doulos.com
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
I think that simulators vary in their response to this, although
the LRM clearly says that "Every change in value of a net or
variable... is considered an update event", and "When an update
event is executed, all the processes that are sensitive to
that event are evaluated...". It's clear, however, that it's
foolish to write any code that depends for its correct behaviour
on the existence of a zero-width pulse.

I agree with your reading of the LRM; I am *always* puzzled by
Verilog's scheduling model. However, in practice I hope you
will avoid any code that depends on the behaviour of #0 to
make it work correctly.
Thank you very much for your answers.
I understand that in practice, in order to produce high quality code, one
must use a very limited well defined and well understood subset of the
language.
And clearly, the two examples I sent are not part of this subset.
However, I am studying formal methods and verification of hardware
descriptions. So I wanted to understand the language semantics as well as
possible.
Also, in the perspective of making verification tools that input Verilog,
both examples are easily avoided:
for the first one, reject any code that has a process sensitive on "weirdly
assigned" registers.
for the second one, syntactily forbid any occurence of #0 in the source.


You could just as easily have asked the question for
blocking assignment:

initial begin
x = 0;
#1
x = 1; // zero-width glitch
x = 0;
end

In this case, just like yours, the glitch on 'x' is truly of
zero width.

The problem doesn't arise in VHDL.
Yes, indeed.

Again, thank you for your answer.
Charles Hymans
 
"C. Hymans" <no@spam.fr> wrote in message news:<Xns9465BC14686E0chymans@193.252.19.141>...
It seems that according to the IEEE standard (5.4.1), the updates
associated with nonblocking assignments must all be performed in the
same order as the code. And so, the last process must wake up.
However, I am not sure this is really important that a simulator conform
to this.
Yes, the updates are required to be performed in order. That means
that the final value will be 0. However, that is not the only thing
that affects whether "Hello" gets printed. There is some looseness
in the definition of whether an event has occurred.

One definition is based on what happened at the writer. If it wrote
a 0 and then a 1, a posedge occurred, even if it subsequently changes
back to a 0. The other definition is based on what happened at the
reader/waiter. If it "sees" a 0 and then a 1, then a posedge occurred.
If the 1 goes away before the waiting process can respond, then it
effectively didn't happen. Intuitively, a process waiting on a posedge
shouldn't wake up to find a value of 0.

The de facto standard, Verilog-XL, uses both definitions in different
situations. Generally it uses the writer definition. But the most
practical way of implementing waiting on arbitrary expressions is to
switch to the second definition, so XL does so. And some users consider
it very important to use the second definition, because they write code
that sets a variable to a default value and then replaces that with the
actual value. They don't want things waking up because of the resulting
transitions that were artifacts of this coding style, rather than actual
transitions. So XL has a command line option that makes it use the
second definition in all cases, filtering out these zero-width glitches
at a minor cost in performance.

Since XL defined the de facto behavior, and it allows this looseness,
the behavior is effectively undefined.

So you should avoid writing code that depends on the response to
zero-width glitches. You can write code that depends on the final
value assigned by sequential nonblocking assignments, since that is
defined.

2. Then, I don't quite understand which must be executed first between #
0-delayed process or nonblocking assignments' update.
A nonblocking assignment will wait until after any number of #0 delay
controls.

Consider the following program:

module main;
reg x;
initial begin
x = 0;
#1;
x <= 1;
$display("0: %b", x);
#0 $display("1: %b", x);
#0 $display("2: %b", x);
#0 $display("3: %b", x);
#1 $display("-: %b", x);
end
endmodule

When does the nonblocking assignment's update really take place ? When
does x become 1 ?
It becomes 1 in the display labelled "-".

From the IEEE standard, I first understood that inactive events are
executed before nonblocking assignments' update events and so I thought
only the last display would show 1. However, I tested this on 2
simulators and got 2 different outputs. I am puzzled.
Your understanding was correct. If a simulator does not get that result,
then it is not implemented correctly, and is not IEEE compliant.

I am saying this as someone with experience in a Verilog simulator
implementation, as well as a participant in the IEEE standardization.
 
You could just as easily have asked the question for
blocking assignment:

initial begin
x = 0;
#1
x = 1; // zero-width glitch
x = 0;
end

In this case, just like yours, the glitch on 'x' is truly of
zero width.

The problem doesn't arise in VHDL.
Event removing can be caused by optimization depend on comparing reg
value on process resuming and process waiting - in such way x has no event
(on start ==0, on end ==0). The same story can be with nb assign - first 1
is appended to transaction list (only because it's different than current
value), next 0, but this is in the same time, so first transaction is
removed - and now first transaction has value 0, the same as current value,
so this transaction will be also removed. Final effect: no transactions on
the list - so there will be no events.

2. Then, I don't quite understand which must be executed first
between #0-delayed process or nonblocking assignments' update.
Consider the following program:

module main;
reg x;
initial begin
x = 0;
#1;
x <= 1;
$display("0: %b", x);
#0 $display("1: %b", x);
#0 $display("2: %b", x);
#0 $display("3: %b", x);
#1 $display("-: %b", x);
end
endmodule

When does the nonblocking assignment's update really take place ? When
does x become 1 ?
From the IEEE standard, I first understood that inactive events are
executed before nonblocking assignments' update events and so I thought
only the last display would show 1. However, I tested this on 2
simulators and got 2 different outputs. I am puzzled.

I agree with your reading of the LRM; I am *always* puzzled by
Verilog's scheduling model. However, in practice I hope you
will avoid any code that depends on the behaviour of #0 to
make it work correctly.

Maybe a simulator implementor, or one of the LRM authors,
can help us a little?
Nb transactions should be realized (value of transaction will be value
of reg) just before change of simulation time, but before $monitor
processes, so proper output is:
0: 0
1: 0
2: 0
3: 0
-: 1

regards,
MK.
 
hi,
i've a doubt on similar lines
let's say i've a signal sig1 high for 2 clocks and a signal sig2 which
is delayed version of sig1 ie
always @(posedge clk)
sig2 <= sig1;
now i would like to know the behaviour when i add delays to them on
LHS and RHS side....i mean
1)always @(posedge clk)
#2 sig2 <= sig1;
2)always @(posedge clk)
sig2 <= #2 sig1;

thx! in advance

"C. Hymans" <no@spam.fr> wrote in message news:<Xns9465BC14686E0chymans@193.252.19.141>...
Hi,

I have two questions about nonblocking assignments and their interaction
with other constructs.

1. In the following program, does the simulator necessarily have to
display "Hello!" ?

module main;
reg x;
initial begin
x = 0;
#1;
x <= 1;
x <= 0;
end
always @(posedge x) $display("Hello!");
endmodule

It seems that according to the IEEE standard (5.4.1), the updates
associated with nonblocking assignments must all be performed in the
same order as the code. And so, the last process must wake up.
However, I am not sure this is really important that a simulator conform
to this.


2. Then, I don't quite understand which must be executed first between #
0-delayed process or nonblocking assignments' update.
Consider the following program:

module main;
reg x;
initial begin
x = 0;
#1;
x <= 1;
$display("0: %b", x);
#0 $display("1: %b", x);
#0 $display("2: %b", x);
#0 $display("3: %b", x);
#1 $display("-: %b", x);
end
endmodule

When does the nonblocking assignment's update really take place ? When
does x become 1 ?
From the IEEE standard, I first understood that inactive events are
executed before nonblocking assignments' update events and so I thought
only the last display would show 1. However, I tested this on 2
simulators and got 2 different outputs. I am puzzled.


Thank you in advance for your answers,
Charles
 
Thank you for your answers. It makes better sense now. I have a clearer
idea of what is defined or not in the standard.


Charles
 

Welcome to EDABoard.com

Sponsor

Back
Top