From e5ad9b3a4b29f4d4dbd82a9e635a4f74e75fd676 Mon Sep 17 00:00:00 2001 From: Nick Brereton <85175726+nbstrike@users.noreply.github.com> Date: Wed, 4 Mar 2026 22:39:05 -0500 Subject: [PATCH] Support Z non-blocking assignment (#7192) (#496) (#7197) --- src/V3Tristate.cpp | 1 + test_regress/t/t_tri_assigndly_nba.py | 18 ++++++++ test_regress/t/t_tri_assigndly_nba.v | 60 +++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100755 test_regress/t/t_tri_assigndly_nba.py create mode 100644 test_regress/t/t_tri_assigndly_nba.v diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 159aa514b..74c8b1b34 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -1561,6 +1561,7 @@ class TristateVisitor final : public TristateBaseVisitor { } void visit(AstAssignW* nodep) override { visitAssign(nodep); } void visit(AstAssign* nodep) override { visitAssign(nodep); } + void visit(AstAssignDly* nodep) override { visitAssign(nodep); } void visit(AstAlias* nodep) override { VL_RESTORER(m_alhs); VL_RESTORER(m_inAlias); diff --git a/test_regress/t/t_tri_assigndly_nba.py b/test_regress/t/t_tri_assigndly_nba.py new file mode 100755 index 000000000..8a938befd --- /dev/null +++ b/test_regress/t/t_tri_assigndly_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() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_tri_assigndly_nba.v b/test_regress/t/t_tri_assigndly_nba.v new file mode 100644 index 000000000..c62e4b9ef --- /dev/null +++ b/test_regress/t/t_tri_assigndly_nba.v @@ -0,0 +1,60 @@ +// DESCRIPTION: Verilator: Tristate with non-blocking assignment to Z state +// +// 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 + +// verilog_format: off +`define stop $stop +`define checkh(gotv, expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0x exp=%0x (%s !== %s)\n", `__FILE__, `__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0); +// verilog_format: on + +module t ( + input clk +); + + int cyc; + + // verilator lint_off MULTIDRIVEN + logic tribus; + // verilator lint_on MULTIDRIVEN + + wire driver1_en = cyc[0]; + wire driver1_dat = cyc[1]; + always @(negedge clk) begin + tribus <= driver1_en ? driver1_dat : 1'bz; + end + + wire driver2_en = cyc[2]; + wire driver2_dat = cyc[3]; + always @(negedge clk) begin + tribus <= driver2_en ? driver2_dat : 1'bz; + end + + always @(posedge clk) begin +`ifdef TEST_VERBOSE + $write("[%0t] cyc==%0d tb=%x (%x,%x) (%x,%x)\n", $time, cyc, tribus, driver1_en, driver1_dat, + driver2_en, driver2_dat); +`endif + cyc <= cyc + 1; + if (cyc == 0) begin + // Setup + end else if (cyc < 50) begin + if (!driver1_en && !driver2_en) begin + `checkh(tribus, 1'bz); + end else if (driver1_en && !driver2_en) begin + `checkh(tribus, driver1_dat); + end else if (!driver1_en && driver2_en) begin + `checkh(tribus, driver2_dat); + end else begin + // Ignore conflict cases + end + end else if (cyc == 99) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule