How does forever get scheduled in SV event region?

  1. Before… and after. There is only one active region where statements in a module/interface get executed. All initial blocks begin executing in the active region until hitting a blocking statement. Then they become suspended until the blocking condition is satisfied, and resume execution in the active region. The execution of statements will put more activity in the active region, or schedule activity in a later event region. An NBA statement schedules a updates to variables in the NBA region. A #0 will block the current thread by putting it into the inactive region.
    When there are no more statements/events to process in the active region, the events in the inactive region are moved to the active region, we go back to executing active events. The simulator keeps repeating this until there are no more active and inactive events. Then the updates in the NBA region get moved to the active region, and then loop back to executing active events. Finally, when there are no active/inactive/NBA events, the simulator is ready to advance time to the next active time slot. (there are a few more defined regions, but for the most part, the scheduling semantics are as I have described).
  2. You are only allowed 1 active $monitor at a time. Each $monitor statement executed replaces the previous, and you have a race condition as to which $monitor wins. $monitor was intended to be a quick debugging aid before Verilog waveforms and command line interfaces were invented.
  3. The reason the last edge of a is not detected is because you called $finish before the last NBA update to a has a chance to execute. After executing the last NBA statement to a, there is a #0. That suspends the current process and schedules it to resume in the inactive region. Now you have one inactive event (resume from #0), and one NBA event updated to a scheduled. Then there are no active events. So the inactive event becomes active, and the process resumes executing the $finish, leaving the remaining NBA event in its region. Note that the process waiting on @(posedge a) is not scheduled in any region. Only an update to a will cause it to become actively scheduled.