In reply to mlsxdx:
First, you should be using the latest freely available version of the IEEE 1800-2012 SystemVerilog LRM.
The delay control ‘@’ executes in the active region. In fact, if you put aside assertions and a few other miscellaneous constructs, everything executes in the active region. The way the scheduler works, you have nested loops of execution. i.e.
- All events in the active region execute until empty. Execution of active events can schedule more events in this or any other region.
- The events in the inactive region become active events and we go back to step 1.
- Once the active and inactive events queues are empty, the NBA events become active and we go back to step 1.
- Once the active, inactive, and NBA event queues are empty, its time to advance to the next time slot. (assuming no assertions).
Any time you have multiple processes synchronized to the same event where some processes are reading, and other processes are writing to the same variable, you have a race condition where the results are not predictable. You need to use an NBA to move the writing process to a later region.
In your example, you have two process(two initial blocks) synchronized to the same event(time 0 startup). The initial block that appears last in your source code is going suspend itself waiting for a @(posedge a). The initial block that does a BA to a will in a race with the process with the @(posedge a). They are both executing in the same active region. If the BA executes first, the posedge of a happens before the @ executes to wait for a posdege of a, and the @ statement suspends itself waiting for a posedge of a that never happens again. If the @ executes first, then it will see the posedge of a that comes afterwards, unspend itself and execute the $display all in the same active region.
In the NBA case, the NBA statement executes in the active region, but the update to a is scheduled in the NBA event queue. The @ sill executes in the active region suspending itself, but the update to a has not happened yet. So the active and inactive event queues empty with an update to a in the NBA event queue that moves become an active event. That update to a resumes the process waiting for the posedge of a, and executes the $display.