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

为何Verilog的fork-join中#10后加分号会引发行为差异?

为什么Verilog的fork-join里,延迟语句后的分号会改变执行行为?

问题的核心在于Verilog的分号是语句结束符,加上分号会把原本绑定在一起的「延迟+执行逻辑」拆成两个独立的并行分支,完全改变了执行时序。

两种代码的本质差异

第一种代码(#10后无分号)

module waveform_fork_join();

    reg A,B,C,D,E,F,en;
    
    initial
        fork
            en = 1'b0; A = 1'b1; B = 1'b0; C = 1'b0; D = 1'b0; E = 1'b1; F = 1'b1;
            #10 begin
            A = 1'b0; B = 1'b1; C = 1'b1; 
            end
            #20 begin
            A = 1'b1; B = 1'b0; D = 1'b1; E = 1'b0; 
            end
            #30 begin
            B = 1'b1; E = 1'b1; F = 1'b0; 
            end
            #40 begin
            en = 1'b1; B = 1'b0; D = 1'b0; F = 1'b1;
            end
            #50 begin
            B = 1'b1; 
            end
            #60 begin
            B = 1'b0; D = 1'b1; 
            end
            #70 B = 1;
            #80 $finish;
        join

endmodule

这里的#10 begin...end是一个完整的并行分支:意思是「先等10个时间单位,再执行begin块里的赋值」。同理,#20 begin...end、#30 begin...end等都是独立的延迟执行分支,各自在对应时间点触发变量更新。

输出表现:变量会按10、20、30等时间点依次切换状态,比如A在10时刻变0、20时刻变回1,完全符合预期的波形时序。

第二种代码(#10后有分号)

module waveform_fork_join1();

    reg A,B,C,D,E,F,en;
    
    initial
        fork
            en = 1'b0; A = 1'b1; B = 1'b0; C = 1'b0; D = 1'b0; E = 1'b1; F = 1'b1;
            #10;    begin
            A = 1'b0; B = 1'b1; C = 1'b1; 
            end
            #20; begin
            A = 1'b1; B = 1'b0; D = 1'b1; E = 1'b0; 
            end
            #30; begin
            B = 1'b1; E = 1'b1; F = 1'b0; 
            end
            #40; begin
            en = 1'b1; B = 1'b0; D = 1'b0; F = 1'b1;
            end
            #50; begin
            B = 1'b1; 
            end
            #60; begin
            B = 1'b0; D = 1'b1; 
            end
            #70;    B = 1;
            #80 $finish;
        join

endmodule

这里的#10;变成了一条独立的并行分支:它只做一件事——等待10个时间单位,之后就结束,完全不执行任何赋值。而后面的begin...end是另一条完全独立的并行分支,这条分支没有任何延迟,会在0时刻(和第一个赋值分支同时)执行里面的所有赋值!

同理,#20;、#30;等都是只做延迟的空分支,它们后面的begin块全都是0时刻执行的分支。这就导致所有begin块的赋值会在0时刻一次性执行,直接覆盖了第一个分支的初始值。

输出表现:0时刻所有变量就被begin块的赋值覆盖,之后仅在70时刻B被赋值为1,其余时间点无变量更新,直到80时刻执行$finish。

总结

在fork-join中,每一条以分号结尾的语句(或语句块)都是一个并行执行的线程:

  • 没加分号:#N begin...end是一个线程,等待N时间后执行块内逻辑
  • 加了分号:#N;是一个线程(仅做延迟,无操作),begin...end是另一个线程(立刻执行块内逻辑)

内容的提问来源于stack exchange,提问作者lehar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 03:30:55