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

SystemVerilog测试中always与initial块顺序引发的功能异常

SystemVerilog仿真中initial与always块顺序影响功能的原因分析

你遇到的问题本质是仿真0时刻的阻塞赋值竞争,下面具体拆解原因:

可正常运行的代码(always在前)

top test(clk, reset, writedata, dataadr, pc, instr, readdata, memwrite);
    
always begin
        reset = 0;
        clk = 0;
        #10;
                
        reset = 0;
        clk = 1;
        #10;
end

initial begin
    clk = 0;  
    reset = 1; #10; 
end

仿真0时刻的执行顺序:

  1. 先执行always块的阻塞赋值:reset=0、clk=0
  2. 接着执行initial块的阻塞赋值:clk=0(无变化)、reset=1
  3. 两个块均进入#10延迟阶段

此时reset在0时刻的最终值是1,模块能正确完成复位,输出符合预期。

异常代码(initial在前)

top test(clk, reset, writedata, dataadr, pc, instr, readdata, memwrite);

initial begin
    clk = 0;  
    reset = 1; #10; 
end

always begin
        reset = 0;
        clk = 0;
        #10;
                
        reset = 0;
        clk = 1;
        #10;
end     

仿真0时刻的执行顺序:

  1. 先执行initial块的阻塞赋值:clk=0、reset=1
  2. 接着执行always块的阻塞赋值:reset=0、clk=0
  3. 两个块进入延迟阶段

此时reset在0时刻的最终值被覆盖为0,模块没有得到有效复位,导致输出变为未确定状态。

核心原因

SystemVerilog中,同一仿真时刻内的阻塞赋值(=)会按照代码书写的顺序依次执行,后面的赋值会直接覆盖前面的结果。而always块在仿真启动时(0时刻)会立即进入第一次循环,执行所有无延迟的阻塞赋值语句,直到遇到#延迟才暂停。

你原本以为两个块独立执行,但实际上0时刻它们的赋值操作是串行执行的,顺序由代码书写位置决定,最终导致信号值被覆盖。

解决方法

  • 改用非阻塞赋值(<=):同一时刻的非阻塞赋值会被放入调度队列,在当前时刻结束后统一更新信号值,不会出现覆盖问题。修改后代码如下:
top test(clk, reset, writedata, dataadr, pc, instr, readdata, memwrite);

initial begin
    clk <= 0;  
    reset <= 1; #10; 
end

always begin
        reset <= 0;
        clk <= 0;
        #10;
                
        reset <= 0;
        clk <= 1;
        #10;
end     
  • 或者避免0时刻的竞争:调整always块中reset的赋值时机,比如在第一个延迟后再设置reset=0,确保复位信号先生效:
always begin
        clk = 0;
        #10;
        reset = 0; // 延迟后再修改reset
        clk = 1;
        #10;
end

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:25:21