SystemVerilog中delta周期是否在中间阶段发生?跨区域调度处理问询
在Stuart Sutherland所著《RTL Modelling with SystemVerilog for Simulation and Synthesis》一书中,阐述了给定仿真时隙内不同事件区域的事件评估流程,明确提到:在处理较晚[事件]区域的事件时,可能会在更早的区域调度新事件。待该较晚区域处理完成后,仿真会循环遍历各事件区域以处理新调度的事件,直至所有区域无待处理事件(即当前仿真时刻无新事件被调度)。
我的疑问在于这种循环触发的具体时机:假设当前处于NBA区域,触发器的Q输出更新后驱动某逻辑门,进而在同一仿真时隙内调度了一个active区域事件。当NBA区域处理结束后,SystemVerilog标准是否规定模拟器立即回到active区域处理该事件,还是先处理NBA区域之后的其他事件区域,再循环返回处理?我推测答案是前者,但暂未明确测试方法。
根据IEEE 1800-2017 SystemVerilog标准的事件区域调度规则,你的推测是正确的:当NBA区域处理完成后,模拟器会立即回到最早的存在未处理事件的区域开始处理,而不是先处理NBA之后的后续区域(比如Postponed区域)。
标准中明确了仿真时刻的事件处理流程是按优先级从高到低遍历事件区域:Active > Inactive > NBA > Postponed。当某一区域处理完成后,仿真器会重新从最高优先级的区域开始检查,只要有未处理的事件就会进入该区域处理,直到所有区域都没有待处理事件,才会推进到下一个仿真时刻。
测试方法示例
你可以写一个简单的Testbench验证这个行为:
module tb; logic clk, d, q; // 触发器,在NBA区域更新q always @(posedge clk) begin q <= d; // NBA区域赋值 end // 检测q的变化,在Active区域触发事件 always @(q) begin $display("%0t [Active Region] q updated to %b", $time, q); // 用阻塞赋值触发Active区域的后续操作 d = ~d; end // 添加Postponed区域的打印,验证执行顺序 always @(posedge clk) begin #0 $display("%0t [Postponed Region] clk posedge processed", $time); end initial begin clk = 0; d = 0; #10 clk = 1; #10 clk = 0; #10 $finish; end endmodule
运行这个Testbench后,你会观察到输出顺序是:Active区域的打印先于Postponed区域的打印,证明NBA区域处理完成后,仿真器立即回到Active区域处理新调度的事件,而非先执行后续低优先级区域的操作。
内容的提问来源于stack exchange,提问作者EE18

