From 9fe058677bf09e9639044ce1d9c8c821d9cb2955 Mon Sep 17 00:00:00 2001 From: Muzaffer Kal <13210229+muzafferkal@users.noreply.github.com> Date: Sun, 17 May 2026 04:34:29 -0700 Subject: [PATCH] Support NBAs in initial blocks with delay/event controls (#7566) (#7600) Fixes #7566. --- docs/CONTRIBUTORS | 1 + docs/guide/warnings.rst | 5 +++- src/V3Active.cpp | 8 +++++- test_regress/t/t_assert_preponed_nba.py | 18 +++++++++++++ test_regress/t/t_assert_preponed_nba.v | 34 +++++++++++++++++++++++++ 5 files changed, 64 insertions(+), 2 deletions(-) create mode 100755 test_regress/t/t_assert_preponed_nba.py create mode 100644 test_regress/t/t_assert_preponed_nba.v diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index cf0f40070..834fb934f 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -320,3 +320,4 @@ emmettifelts Yogish Sekhar 24bit-xjkp Zubin Jain +Muzaffer Kal diff --git a/docs/guide/warnings.rst b/docs/guide/warnings.rst index 8ceb7242b..4ce0a8cee 100644 --- a/docs/guide/warnings.rst +++ b/docs/guide/warnings.rst @@ -1179,7 +1179,10 @@ List Of Warnings Warns that the code has a delayed assignment inside of an ``initial`` or ``final`` block. If this message is suppressed, Verilator will convert - this to a non-delayed assignment. See also :option:`COMBDLY`. + this to a non-delayed assignment. With :vlopt:`--timing`, delayed + assignments in ``initial`` blocks that also contain a `#` delay + control, or `@` even control statement are scheduled as + non-blocking assignments. See also :option:`COMBDLY`. Ignoring this warning may make Verilator simulations differ from other simulators. diff --git a/src/V3Active.cpp b/src/V3Active.cpp index 846183f4c..97e7601b4 100644 --- a/src/V3Active.cpp +++ b/src/V3Active.cpp @@ -509,7 +509,13 @@ class ActiveVisitor final : public VNVisitor { void visit(AstInitialStatic* nodep) override { moveUnderSpecial(nodep); } void visit(AstInitial* nodep) override { - const ActiveDlyVisitor dlyvisitor{nodep, ActiveDlyVisitor::CT_INITIAL}; + const bool timedInitial + = v3Global.opt.timing().isSetTrue() + && nodep->exists([](const AstNode* const subp) { + return VN_IS(subp, Delay) || VN_IS(subp, EventControl); + }); + const ActiveDlyVisitor dlyvisitor{nodep, timedInitial ? ActiveDlyVisitor::CT_SUSPENDABLE + : ActiveDlyVisitor::CT_INITIAL}; visitSenItems(nodep); moveUnderSpecial(nodep); } diff --git a/test_regress/t/t_assert_preponed_nba.py b/test_regress/t/t_assert_preponed_nba.py new file mode 100755 index 000000000..46d1fe4c0 --- /dev/null +++ b/test_regress/t/t_assert_preponed_nba.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of either the GNU Lesser General Public License Version 3 +# or the Perl Artistic License Version 2.0. +# SPDX-FileCopyrightText: 2026 Wilson Snyder +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=['--binary']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_assert_preponed_nba.v b/test_regress/t/t_assert_preponed_nba.v new file mode 100644 index 000000000..8f905ead1 --- /dev/null +++ b/test_regress/t/t_assert_preponed_nba.v @@ -0,0 +1,34 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Wilson Snyder +// SPDX-License-Identifier: CC0-1.0 + +module t; + bit clk = 0; + int cnt = 0; + bit fire = 0; + + always #1 clk = ~clk; + + always_ff @(posedge clk) begin + if (fire) cnt <= cnt + 1; + end + + assert property (@(posedge clk) fire |-> (cnt == 0)) + $write("Assertion fired and passed: cnt=%0d\n", cnt); + else begin + $write("%%Error: sampled fire=1 cnt=%0d, expected preponed cnt 0\n", cnt); + $stop; + end + + initial begin + @(posedge clk); + fire <= 1; + @(posedge clk); + fire <= 0; + repeat (2) @(posedge clk); + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule