Verilog任务调度语义合规性问询:iverilog仿真输出异常解析
Verilog仿真输出的调度语义疑问
我在iverilog中运行了一段Verilog代码,得到的输出让我困惑,尤其是task_time为5时task_counter等于1,而task_time为15时task_counter等于0。我已经研究过Verilog调度语义,但无法解释这个结果,想确认该输出是否符合Verilog调度语义。
Verilog代码
module top(); reg clk; reg[31:0] counter; reg[19:0] in; reg[31:0] out; reg[19:0] xxx; reg[19:0] yyy; always #5 clk = ~clk; initial begin clk <= 0; counter <= 0; out <= 0; end always @(posedge(clk)) begin decode_inst(counter); $strobe("pre-counter is %0t",counter); counter = counter + 1; out <= counter; $strobe("time is %0t",$time); $strobe("counter is %0t",counter); $strobe("out is %0t",out); decode_inst(counter); if (counter == 2) $finish(); end task decode_inst(input xxx); begin $strobe("task_time is %0t",$time); $strobe("task_counter is %0t",xxx); end endtask endmodule
仿真输出
task_time is 5 task_counter is 1 pre-counter is 1 time is 5 counter is 1 out is 1 task_time is 5 task_counter is 1 task_time is 15 task_counter is 0 pre-counter is 2 time is 15 counter is 2 out is 2 task_time is 15 task_counter is 0
分析解答
输出与Verilog调度语义的匹配性
输出中大部分现象完全符合Verilog调度规则,核心在于$strobe的特性:$strobe会将输出请求放入Postponed(监控)队列,需等待当前时间步的所有Active(阻塞赋值)和NBA(非阻塞赋值)操作完成后,才输出变量的最终值。因此,即便$strobe写在阻塞赋值counter = counter +1之前,它输出的也是赋值完成后的counter值——这就是pre-counter is 1(时间5)和pre-counter is 2(时间15)的原因,完全符合Verilog语义。
task_counter异常的原因
task_counter的异常值是代码中的两个错误导致的,并非Verilog语义问题:
- 格式符误用:
%0t是用于格式化时间类型的格式符,却被用来输出整数变量counter和xxx。虽然部分仿真器会兼容输出整数,但这不符合Verilog规范,可能引发解析异常。正确的整数格式符应为%d。 - 变量名冲突:模块内定义了
reg[19:0] xxx,同时task的输入参数也命名为xxx。Verilog中task参数应为局部变量,但部分仿真器可能因同名导致解析混淆,使得task内部的xxx指向了模块内未初始化的xxx变量(而非传入的counter参数)。由于iverilog对未初始化reg默认初始化为0,这就解释了时间15时task_counter is 0的现象;时间5时的1则是仿真器解析异常导致的结果。
结论
若修正格式符和变量名冲突的问题,输出会完全符合Verilog调度语义。当前输出的异常部分是代码错误引发的仿真器解析问题,而非Verilog语义本身的问题。
内容的提问来源于stack exchange,提问作者giuseppe maugeri
相关产品推荐
相关产品推荐

