Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

time 0 and an always block....

100 views
Skip to first unread message

johnp

unread,
Sep 5, 2006, 6:25:03 PM9/5/06
to
Here's a simple question on how a combinatorial blocks are (or are not)
triggered at time 0. Using the following code, what should the value
for the 'bug' variable be when it is printed? ModelSim says 00,
Icarus says XX.

Should the always block be triggered at time 0? Is this simply
undefined?

Opinions?

Thanks!

John Providenza


module test;

wire [1:0] mode = 2'b0;

reg [1:0] bug;

always @(mode)
bug = mode;

initial
begin
#10;

$display("%b %b", mode, bug);

$finish;
end

endmodule

Stephen Williams

unread,
Sep 5, 2006, 7:06:06 PM9/5/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

johnp wrote:
> Here's a simple question on how a combinatorial blocks are (or are not)
> triggered at time 0. Using the following code, what should the value
> for the 'bug' variable be when it is printed? ModelSim says 00,
> Icarus says XX.
>
> Should the always block be triggered at time 0? Is this simply
> undefined?

Modelsim and Icarus Verilog are both not wrong. The initial statement
(mode = 2'b00) and the always statement are scheduled in undefined
order. If the initial statement is scheduled first, then the always
statement @() delay will miss the event. Modelsim probably schedules
the always statement first, then the initial statement, whereas Icarus
just happens to do it the other way.

In fact, Icarus Verilog snapshots "help" the lazy user resolve these
time-0 races by noticing always blocks that are level sensitive and
pushing them to the head of the time-0 scheduling queue, so with the
latest Icarus Verilog, you get the output "00 00".

The bottom line: this is a race condition, and a very common coding
error. You're not the only one to make this mistake.

>
> module test;
>
> wire [1:0] mode = 2'b0;
>
> reg [1:0] bug;
>
> always @(mode)
> bug = mode;
>
> initial
> begin
> #10;
>
> $display("%b %b", mode, bug);
>
> $finish;
> end
>
> endmodule
>


- --
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."
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFE/gLerPt1Sc2b3ikRApJ5AJ92XM3uvENQQg4jcCV4T0AIfi8NmwCgnyZ9
XR4LiREYH1og+7DCvRbTmto=
=d0Ih
-----END PGP SIGNATURE-----

sh...@cadence.com

unread,
Sep 5, 2006, 8:06:53 PM9/5/06
to

Stephen Williams wrote:
>
> Modelsim and Icarus Verilog are both not wrong. The initial statement
> (mode = 2'b00) and the always statement are scheduled in undefined
> order. If the initial statement is scheduled first, then the always
> statement @() delay will miss the event. Modelsim probably schedules
> the always statement first, then the initial statement, whereas Icarus
> just happens to do it the other way.

Steve,

The mode = 2'b00 is a continuous assignment, not an initial block,
since mode is a wire.

The basic argument still applies, but is less clear. The LRM specifies
that initial and always blocks can execute in an arbitrary order. It
doesn't say anything about continuous assignments. It doesn't even
explicitly define that the order is undefined :-).
You just have to invoke the general rules that event ordering is
nondeterministic.

The 2005 standard does explicitly specify that continuous assignments
evaluate at time zero, to ensure that constant values get propagated.
This was not actually specified in the earlier versions.


> In fact, Icarus Verilog snapshots "help" the lazy user resolve these
> time-0 races by noticing always blocks that are level sensitive and
> pushing them to the head of the time-0 scheduling queue, so with the
> latest Icarus Verilog, you get the output "00 00".

Other simulators tend to get this result as a side-effect of
optimizations that they apply to always blocks. As a result, users may
have started relying on it more.

Stephen Williams

unread,
Sep 6, 2006, 11:22:13 AM9/6/06
to
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

sh...@cadence.com wrote:
> Stephen Williams wrote:
>> Modelsim and Icarus Verilog are both not wrong. The initial statement
>> (mode = 2'b00) and the always statement are scheduled in undefined
>> order. If the initial statement is scheduled first, then the always
>> statement @() delay will miss the event. Modelsim probably schedules
>> the always statement first, then the initial statement, whereas Icarus
>> just happens to do it the other way.
>
> Steve,
>
> The mode = 2'b00 is a continuous assignment, not an initial block,
> since mode is a wire.


Doh! You're right, although the reasoning applies, but more so. The
initial time-0 event of passing the constant value to the wire is still
not ordered, so the race still exists.

> The basic argument still applies, but is less clear. The LRM specifies
> that initial and always blocks can execute in an arbitrary order. It
> doesn't say anything about continuous assignments. It doesn't even
> explicitly define that the order is undefined :-).
> You just have to invoke the general rules that event ordering is
> nondeterministic.
>
> The 2005 standard does explicitly specify that continuous assignments
> evaluate at time zero, to ensure that constant values get propagated.
> This was not actually specified in the earlier versions.

But does it say anything about ordering? The poster's code would still
be a race because of the always statement that also starts waiting for
the event at time-0. Those sorts of problems are hard to legislate
around, yet catch a lot of users.


>> In fact, Icarus Verilog snapshots "help" the lazy user resolve these
>> time-0 races by noticing always blocks that are level sensitive and
>> pushing them to the head of the time-0 scheduling queue, so with the
>> latest Icarus Verilog, you get the output "00 00".
>
> Other simulators tend to get this result as a side-effect of
> optimizations that they apply to always blocks. As a result, users may
> have started relying on it more.
>

- --
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."
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFE/uelrPt1Sc2b3ikRAvswAJ4ssI6eYlvL+JWBAdPYAf5gOev05wCbBg6g
XGKUEG/Ty4zoMOmE14BpWKY=
=sBz6
-----END PGP SIGNATURE-----

johnp

unread,
Sep 6, 2006, 2:55:39 PM9/6/06
to
I suspect the answer here is that the event ordering is
not defined for this case. This is really too bad
since the
always @(*)
construct models combinatorial logic. Most of the time.

This is a case where it doesn't model it accurately, yet
a continuous assignment to a wire would model it correctly.

I wonder how many problems would be avoided if Verilog had
specified its event ordering a bit better.

John Providenza

0 new messages