|
From: Martin W. <ic...@ma...> - 2017-04-21 19:40:17
|
Jim Peterson wrote:
...
> Devs,
>
> Commit 54feb8... has altered the expected behavior of my simulations.
> In particular, outputs at the beginning are now unknown (x) rather than
> the expected value. Test code is at the end of this email (most of it
> is copyright Xilinx).
It's probably easier to explain with a simpler example:
module test();
reg a = 0;
reg b;
always @* begin
b = a;
end
initial begin
a = 0;
#1 $display(a,,b);
a = 1;
#1 $display(a,,b);
end
endmodule
This example contains three separate processes:
1. The process that sets the initial value of a.
2. The process that executes the 'always' statement.
3. The process that executes the 'initial' statement.
Standard Verilog does not specify which order these three processes are
run. If either (1) or (3) run before (2), 'a' is already set to '0' when
the 'always' statement is first run and the '@*' event doesn't trigger
until 'a' is changed to '1' at time 1. So for standard Verilog, either
0 x
1 1
or
0 0
1 1
are valid outputs from this example, depending on the order the processes
are executed.
When compiling standard Verilog, Icarus tries to protect you from
inadvertent races like this by scheduling the processes that execute
'always' statements first. But this is not required by the IEEE standard,
and other simulators may behave differently.
SystemVerilog, however, adds a rule for variable initialisation:
"Setting the initial value of a static variable as part of the variable
declaration (including static class members) shall occur before any initial
or always procedures are started (also see 6.21 and 10.5 on variable
initialization with static and automatic lifetimes)."
so the only legal output from the above example is
0 x
1 1
Before commit 54feb8..., Icarus wasn't following this rule. Now it does,
but only if you specify a SystemVerilog language generation. If you compile
with -g2005 or earlier, you get the old behaviour.
To fix this ordering problem, SystemVerilog provides the 'always_comb'
statement, which is guaranteed to run once at time 0, after all the
'initial' statements and variable initialisations have run. But I'm afraid
Icarus doesn't yet support 'always_comb'.
Martin
|