Difficulty: Medium · Puzzle 4 of 6 · Topic: Fork Join Puzzles
Which lines print, and why does one statement after `disable` never execute?
`timescale 1ns/1ns
module p4;
initial begin
fork : outer
begin
#5 $display("%0t W1", $time);
#5 $display("%0t W2", $time);
end
begin
#6 disable outer;
$display("%0t K", $time);
end
join
$display("%0t DONE", $time);
end
endmodule`disable outer` terminates the named block and all processes inside it, including the caller process itself.
1) Worker prints W1 at t=5.
2) At t=6, second branch executes `disable outer`, which terminates the entire named fork block.
3) Because caller is terminated by disable, statement `K` is never reached.
4) `join` returns immediately after block termination, so DONE prints at t=6.
5) W2 at t=10 never occurs.Answer: W1@5 and DONE@6 only; W2 and K do not print
Checked by running the code in Icarus Verilog 13 and Verilator 5; the printed output supports the answer above. disable outer also kills the branch that runs it. (Icarus, 4-state) disable outer also kills the branch that runs it. (Verilator, 2-state)
`disable outer` also terminates the process that executes it, so K is unreachable; execution resumes after the whole fork, which is why DONE still prints at t=6.
How would behavior differ if you used `disable fork;` instead of `disable outer;` here? Model answer: `disable fork` only kills the children of the calling process, and branch 2 has none, so nothing is killed: K prints at 6, W2 at 10, then DONE at 10.
I would first see what disable of a named block does, because it kills the whole labelled block including the process that calls it. So W1 prints at 5, the second branch disables the block at 6, the statement after it is never reached, and join returns so DONE prints at 6. W2 at 10 never prints. The trap is expecting the next statement to run, or expecting only the other branch to die. I would check which scope the label names.