SystemVerilog时钟块周期延迟异常问题及@(cb)作用解析
SystemVerilog时钟块周期延迟异常问题解析
问题根源:时钟块操作的时间对齐错位
原代码的核心问题在于测试代码没有和时钟沿对齐,导致时钟块赋值与##n的周期计数出现错位。
先拆解原代码的时间线(时钟周期为10ns,always #5 clk = ~clk):
- 0ns:
initial块启动,直接执行cb.reset <= '0。由于此时还未出现第一个时钟上升沿(第一个posedge clk在5ns),该赋值会被调度到第一个上升沿后5ns,也就是10ns时reset变为0。 - 紧接着执行
##2:##n的语义是从当前代码执行的时间点(0ns)开始,等待n个时钟块触发事件(即posedge clk)。第一个上升沿在5ns,第二个在15ns,因此##2在15ns结束,随后cb.reset <= '1被调度到15ns后5ns,也就是20ns时reset变为1。 - 最终
reset的0状态仅从10ns持续到20ns(1个时钟周期),和预期的2个周期不符。
@(cb)的作用:对齐时钟沿,修正计数起点
@(cb)等价于@(posedge clk),它会强制initial块暂停,直到第一个时钟上升沿到来后再继续执行,让后续所有时钟块操作和时钟沿严格对齐:
修复后的时间线:
- 0ns:
initial块启动,执行@(cb),等待第一个posedge clk(5ns)。 - 5ns:时钟上升沿触发,
initial块继续执行cb.reset <= '0,赋值被调度到5ns后5ns,也就是10ns时reset变为0。 - 紧接着执行
##2:此时计数起点是5ns,等待2个posedge clk(15ns、25ns),##2在25ns结束,cb.reset <= '1被调度到25ns后5ns,也就是30ns时reset变为1。 - 最终
reset的0状态从10ns持续到30ns(2个时钟周期),完全符合预期。
结论:这是代码逻辑问题,而非编译器问题
该现象完全符合SystemVerilog标准定义:
##n的计数起点是当前语句的执行时间点,而非赋值生效的时间点。- 时钟块的赋值在无时钟上下文时,会绑定到下一个时钟事件,但不会自动调整后续
##n的计数基准。
使用时钟块编写测试代码时,必须先通过@(cb)或@(posedge clk)让测试逻辑和时钟沿对齐,避免出现时间计数错位。
内容的提问来源于stack exchange,提问作者Duy-Manh NGUYEN
相关产品推荐
相关产品推荐

