分析

这个问题是当前 Verilator 仿真(eval)顺序引起的,Verilator 会把 initial 块和 always 块的仿真完全隔离开, 生成的 C++ 代码是这样的:

void Vtest::eval_step() {
    // ...
    if (!vlSymsp->__Vm_didInit) {
        vlSymsp->__Vm_didInit = true;
        Vtest___024root___eval_static(&(vlSymsp->TOP));
        Vtest___024root___eval_initial(&(vlSymsp->TOP));
        Vtest___024root___eval_settle(&(vlSymsp->TOP));
    }
    Vtest___024root___eval(&(vlSymsp->TOP));
    // ...
}

其中 _eval_initial 的实现如下:

VlCoroutine Vtest___024root___eval_initial__TOP__Vtiming__0(Vtest___024root* vlSelf) {
    // ...
    auto &vlSelfRef = std::ref(*vlSelf).get();
    vlSelfRef.test__DOT__a = 1U;
    co_await vlSelfRef.__VdlySched.delay(1ULL, nullptr,
                                         "verilator-issues/5499/test.sv",
                                         9);
    VL_WRITEF_NX("b = %b\n",0,1,vlSelfRef.test__DOT__b);
    VL_FINISH_MT("verilator-issues/5499/test.sv", 15, "");
}

void Vtest___024root___eval_initial(Vtest___024root* vlSelf) {
    // ...
    auto &vlSelfRef = std::ref(*vlSelf).get();
    Vtest___024root___eval_initial__TOP__Vtiming__0(vlSelf);
    vlSelfRef.__Vtrigprevexpr___TOP__test__DOT__a__0
        = vlSelfRef.test__DOT__a;
}

函数 Vtest_024root_eval_initialTOPVtiming0 就对应于 sv design 中的 initial 块, 注意到 Vtrigprevexpr_TOPtestDOTa__0 的值会是 1,这意味着在 always 不会看到 a 的上升沿, 因此不会执行。

修复方案