You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Verilog静态任务参数执行结果不符预期的疑问求助

Explanation of Verilog Static Task Behavior in Your Simulation

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, _time is set to 10, and a delay of 10 time units is scheduled. This delay length stays fixed even if _time is overwritten later.
  • Next, print(20, "Thread2") sets _time to 20, scheduling a 20-unit delay.
  • Finally, print(30, "Thread3") sets _time to 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 08:20:56