Fix SYNCASYNCNET false positive with changed non-edge logic (#7980).

Fixes #7980.
This commit is contained in:
Wilson Snyder 2026-07-24 09:53:36 -04:00
parent d2de6b42cf
commit f8fb1d6646
4 changed files with 34 additions and 22 deletions

View File

@ -67,6 +67,7 @@ Verilator 5.051 devel
* Fix variable scope in unique on dynamic array (#7981). [Kornel Uriasz, Antmicro Ltd.]
* Fix table optimization causing not contextually convertible to bool error (#7983). [Jakub Michalski]
* Fix $fgets being mis-optimized away (#7976). [G-A. Kamendje]
* Fix SYNCASYNCNET false positive with changed non-edge logic (#7980). [Oron Port]
Verilator 5.050 2026-07-01

View File

@ -199,6 +199,7 @@ class GateBuildVisitor final : public VNVisitorConst {
const AstScope* m_scopep = nullptr; // Current scope being processed
AstActive* m_activep = nullptr; // Current active
bool m_inClockedActive = false; // Underneath clocked active
bool m_inEdgeActive = false; // Underneath edge active
bool m_inStaticActive = false; // Underneath static active
bool m_inSenItem = false; // Underneath AstSenItem; any varrefs are clocks
@ -248,9 +249,11 @@ class GateBuildVisitor final : public VNVisitorConst {
UASSERT_OBJ(!m_activep, nodep, "Should not nest");
VL_RESTORER(m_activep);
VL_RESTORER(m_inClockedActive);
VL_RESTORER(m_inEdgeActive);
VL_RESTORER(m_inStaticActive);
m_activep = nodep;
m_inClockedActive = nodep->hasClocked();
m_inEdgeActive = nodep->sentreep() && nodep->sentreep()->hasEdge();
m_inStaticActive = nodep->hasStatic();
// AstVarScope::user2 -> bool: Signal used in SenItem in *this* active block
@ -286,7 +289,7 @@ class GateBuildVisitor final : public VNVisitorConst {
if (m_inSenItem) {
vVtxp->setIsClock();
vscp->user2(true);
} else if (m_inClockedActive && nodep->access().isReadOnly()) {
} else if (m_inEdgeActive && nodep->access().isReadOnly()) {
// For SYNCASYNCNET
if (vscp->user2()) {
if (!vVtxp->rstAsyncNodep()) vVtxp->rstAsyncNodep(nodep);

View File

@ -1,9 +1,9 @@
%Warning-SYNCASYNCNET: t/t_lint_syncasyncnet_bad.v:14:9: Signal flopped as both synchronous and async: 'rst_both_l'
t/t_lint_syncasyncnet_bad.v:52:13: ... Location of async usage
52 | q4 <= (~rst_both_l) ? 1'b0 : d;
%Warning-SYNCASYNCNET: t/t_lint_syncasyncnet_bad.v:9:11: Signal flopped as both synchronous and async: 'rst_both_l'
t/t_lint_syncasyncnet_bad.v:50:13: ... Location of async usage
50 | q4 <= (~rst_both_l) ? 1'b0 : d;
| ^~~~~~~~~~
t/t_lint_syncasyncnet_bad.v:34:12: ... Location of sync usage
34 | q2 <= (rst_both_l) ? d : 1'b0;
t/t_lint_syncasyncnet_bad.v:31:12: ... Location of sync usage
31 | q2 <= (rst_both_l) ? d : 1'b0;
| ^~~~~~~~~~
... For warning description see https://verilator.org/warn/SYNCASYNCNET?v=latest
... Use "/* verilator lint_off SYNCASYNCNET */" and lint_on around source to disable this message.

View File

@ -4,18 +4,14 @@
// SPDX-FileCopyrightText: 2010 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk, rst_both_l, rst_sync_l, rst_async_l, d
);
/*AUTOINPUT*/
module t (
input clk,
input rst_both_l,
input rst_sync_l,
input rst_async_l,
input d
);
input clk;
input rst_both_l;
input rst_sync_l;
input rst_async_l;
input d;
reg q1;
reg q2;
@ -25,24 +21,26 @@ module t (/*AUTOARG*/
// Beginning of autoreset for uninitialized flops
q1 <= 1'h0;
// End of automatics
end else begin
end
else begin
q1 <= d;
end
end
always @(posedge clk) begin
q2 <= (rst_both_l) ? d : 1'b0;
if (0 && q1 && q2) ;
if (0 && q1 && q2);
end
reg q3;
reg q3;
always @(posedge clk or negedge rst_async_l) begin
if (~rst_async_l) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
q3 <= 1'h0;
// End of automatics
end else begin
end
else begin
q3 <= d;
end
end
@ -55,7 +53,17 @@ module t (/*AUTOARG*/
reg q5;
always @(posedge clk or negedge rst_both_l) begin
q5 <= (~rst_both_l) ? 1'b0 : d;
if (0 && q3 && q4 && q5) ;
if (0 && q3 && q4 && q5);
end
// Issue #7980 - should not cause a warning
logic mirror;
logic [15:0] settle;
// Level-sensitive block (NO posedge/negedge): a plain combinational observer of `value`.
always @(mirror) $display("%0d", mirror);
always_ff @(posedge clk) begin
mirror <= d;
if (mirror != 1'd0) settle <= settle + 16'd1;
end
endmodule