From 37318ab2bda258f6ca03d179a2e7f9d75696f00d Mon Sep 17 00:00:00 2001 From: Pawel Kojma Date: Wed, 10 Dec 2025 16:59:08 +0100 Subject: [PATCH] Fix input sampling of clocking block signals (#6788) --- src/V3AssertPre.cpp | 9 ++++-- test_regress/t/t_clocking_inout.v | 2 +- test_regress/t/t_clocking_input_0_delay.py | 18 ++++++++++++ test_regress/t/t_clocking_input_0_delay.v | 33 ++++++++++++++++++++++ test_regress/t/t_clocking_input_default.py | 18 ++++++++++++ test_regress/t/t_clocking_input_default.v | 33 ++++++++++++++++++++++ test_regress/t/t_clocking_virtual.v | 4 +-- 7 files changed, 111 insertions(+), 6 deletions(-) create mode 100755 test_regress/t/t_clocking_input_0_delay.py create mode 100644 test_regress/t/t_clocking_input_0_delay.v create mode 100755 test_regress/t/t_clocking_input_default.py create mode 100644 test_regress/t/t_clocking_input_default.v diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 49ca80995..efde0dcc2 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -267,11 +267,14 @@ private: AstVarRef* const refp = new AstVarRef{flp, varp, VAccess::WRITE}; refp->user1(true); if (skewp->num().is1Step()) { - // Assign the sampled expression to the clockvar (IEEE 1800-2023 14.13) + // #1step means the value that is sampled is always the signal's last value + // before the clock edge (IEEE 1800-2023 14.4) AstSampled* const sampledp = new AstSampled{flp, exprp->cloneTreePure(false)}; sampledp->dtypeFrom(exprp); - AstAssignW* const ap = new AstAssignW{flp, refp, sampledp}; - m_clockingp->addNextHere(new AstAlways{ap}); + AstAssign* const assignp = new AstAssign{flp, refp, sampledp}; + m_clockingp->addNextHere(new AstAlways{ + flp, VAlwaysKwd::ALWAYS, + new AstSenTree{flp, m_clockingp->sensesp()->cloneTree(false)}, assignp}); } else if (skewp->isZero()) { // #0 means the var has to be sampled in Observed (IEEE 1800-2023 14.13) AstAssign* const assignp = new AstAssign{flp, refp, exprp->cloneTreePure(false)}; diff --git a/test_regress/t/t_clocking_inout.v b/test_regress/t/t_clocking_inout.v index bda438f11..2e89aa9a3 100644 --- a/test_regress/t/t_clocking_inout.v +++ b/test_regress/t/t_clocking_inout.v @@ -27,7 +27,7 @@ module t; #1 if (foo != 0 || cb.foo != 0) $stop; - if (cb.bar != 1) $stop; + if (cb.bar == 1) $stop; @(posedge foo) if ($time != 7) $stop; diff --git a/test_regress/t/t_clocking_input_0_delay.py b/test_regress/t/t_clocking_input_0_delay.py new file mode 100755 index 000000000..c55d45e6a --- /dev/null +++ b/test_regress/t/t_clocking_input_0_delay.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=["--binary"], make_main=False) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_clocking_input_0_delay.v b/test_regress/t/t_clocking_input_0_delay.v new file mode 100644 index 000000000..8169dc5a0 --- /dev/null +++ b/test_regress/t/t_clocking_input_0_delay.v @@ -0,0 +1,33 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +`timescale 1ms/1ns +module t; + bit clk = 0; + bit data = 1; + bit cb_data; + + initial forever #5 clk = ~clk; + assign cb_data = cb.data; + clocking cb @(posedge clk); + input #0 data; + endclocking + + initial begin + @(posedge clk) data = 0; + end + + initial begin + #4 + if (data != 1) $stop; + if (cb.data != 0) $stop; + #1; + #1step; + if(cb.data != 0) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_clocking_input_default.py b/test_regress/t/t_clocking_input_default.py new file mode 100755 index 000000000..c55d45e6a --- /dev/null +++ b/test_regress/t/t_clocking_input_default.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 by Wilson Snyder. 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-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +import vltest_bootstrap + +test.scenarios('simulator') + +test.compile(verilator_flags2=["--binary"], make_main=False) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_clocking_input_default.v b/test_regress/t/t_clocking_input_default.v new file mode 100644 index 000000000..00a21752f --- /dev/null +++ b/test_regress/t/t_clocking_input_default.v @@ -0,0 +1,33 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +`timescale 1ms/1ns +module t; + bit clk = 0; + bit data = 1; + bit cb_data; + + initial forever #5 clk = ~clk; + assign cb_data = cb.data; + clocking cb @(posedge clk); + input data; + endclocking + + initial begin + @(posedge clk) data = 0; + end + + initial begin + #4 + if(data != 1 ) $stop; + if(cb.data != 0) $stop; + #1; + #1step; + if(cb.data != 1) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule diff --git a/test_regress/t/t_clocking_virtual.v b/test_regress/t/t_clocking_virtual.v index dc6ad78ab..75a7d58fe 100644 --- a/test_regress/t/t_clocking_virtual.v +++ b/test_regress/t/t_clocking_virtual.v @@ -29,8 +29,8 @@ module main; if (t.mod0.io != 1'b1) $stop; if (t.mod1.cb.io != 1'b0) $stop; #1 - if (t.mod0.cb.io != 1'b1) $stop; - if (t.mod1.cb.io != 1'b1) $stop; + if (t.mod0.cb.io != 1'b0) $stop; + if (t.mod1.cb.io != 1'b0) $stop; if (t.mod1.cb.inp != 1'b1) $stop; #8; t.mod0.inp = 1'b0;