Verilog静态任务参数执行结果不符预期的疑问求助
First, let's restate your code with proper formatting for clarity:
module tb; initial begin $display("[%0t] Main Thread: Fork join going to start", $time); fork begin fork print(10, "Thread1"); print(20, "Thread2"); join_none $display("[%0t] Nested fork has finished", $time); end print(30, "Thread3"); join_none $display("[%0t] Main Thread: Fork join has finished", $time); end task print (int _time, string t_name); #(_time) $display ("[%0t] %s", $time, t_name); endtask endmodule
Your confusion stems from how static task variables interact with parallel execution and delay evaluation. Here's the breakdown:
1. Static Task Variables = Shared State
By default, Verilog tasks are static, meaning all concurrent calls to the same task share the same instance of the task's variables (_time and t_name here). When you call print multiple times in parallel, each call overwrites these variables immediately—before any of the delayed $display statements execute.
2. Delay Duration is Fixed When Scheduled
The #(_time) delay in the task uses the value of _time at the moment the delay is first encountered (when the task is called), not when the delay completes.
- When
print(10, "Thread1")is called,_timeis set to 10, and a delay of 10 time units is scheduled. This delay length stays fixed even if_timeis overwritten later. - Next,
print(20, "Thread2")sets_timeto 20, scheduling a 20-unit delay. - Finally,
print(30, "Thread3")sets_timeto 30, scheduling a 30-unit delay.
These delays fire at simulation times 10, 20, and 30 respectively—hence the different timestamps in your output.
3. Variable Values are Read at Display Time
The $display statement uses the current value of t_name when it runs, not the value when the task was called. In your simulation, the last call to print that overwrote t_name was print(20, "Thread2") (due to the unspecified execution order of parallel threads in a fork). By the time all three $display statements execute, t_name is still set to "Thread2", so all lines show that name.
4. Unspecified Parallel Execution Order
Verilog does not guarantee the order in which parallel threads within a fork execute in the same time step. In your case, print(20, "Thread2") happened to run last, overwriting t_name to "Thread2" after the other two calls. If the order had been different (e.g., print(30, "Thread3") ran last), all lines would have shown "Thread3" instead.
Fix to Get Isolated Task Behavior
If you want each task call to retain its own variable values, declare the task as automatic:
task automatic print (int _time, string t_name); #(_time) $display ("[%0t] %s", $time, t_name); endtask
This creates a separate instance of the task's variables for each call, resulting in the output:
[0] Main Thread: Fork join going to start [0] Main Thread: Fork join has finished [0] Nested fork has finished [10] Thread1 [20] Thread2 [30] Thread3
内容的提问来源于stack exchange,提问作者ss77

