Bug applies to v10 and devel version.
Incomplete case/if assignments in the form of
always @(posegde clk) begin o <= 1'b0; // default value unless I specify if (condition) o <= 1'b1; // overriding value end
cause false positive edge events on "o" when condition is always true.
The attached code example should give the following output
aio 000 111 011 111 011 111 011 111 011 111
Rather than
aio 000 111 011 110 010 111 011 110 010 111 011
You have hit one of the sources of non-determinism in Verilog. If 'condition' is true, your example code above adds two events to the non-blocking assignment event queue. When there are no active/inactive events remaining at the current simulation time, the non-blocking assignment events are moved to the active queue. Each of these update events will be taken off the active queue and executed, causing an evaluation event for the 'always @(posedge i)' process to be added to the active queue. But the Verilog standard allows active events to be processed in any order (other than requiring that statements in the same begin-end block and non-blocking assignment events are performed in order). So both
execute update event 1 (i <= 0)
execute update event 2 (i <= 1)
execute evaluation event 1 (@(posedge i))
execute evaluation event 2 (@(posedge i))
and
execute update event 1 (i <= 0)
execute evaluation event 1 (@(posedge i))
execute update event 2 (i <= 1)
execute evaluation event 2 (@(posedge i))
are valid behaviours. Icarus implements the latter.
The scheduling rules are described in detail in section 11.4 of IEEE 1364-2005. See particularly the first sentence of 11.4.2, which covers this source of non-determinism.