Add PROCINITASSIGN on initial assignments to process variables (#2481).

This commit is contained in:
Wilson Snyder 2025-04-30 22:00:06 -04:00
parent 38dd9a344e
commit 8b52bd817f
19 changed files with 292 additions and 59 deletions

View File

@ -14,6 +14,7 @@ Verilator 5.037 devel
**Other:** **Other:**
* Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu] * Add BADVLTPRAGMA on unknown Verilator pragmas (#5945). [Shou-Li Hsu]
* Add PROCINITASSIGN on initial assignments to process variables (#2481). [Niraj Menon]
* Fix filename backslash escapes in C code (#5947). * Fix filename backslash escapes in C code (#5947).
* Fix sign extension of signed compared with unsigned case items (#5968). * Fix sign extension of signed compared with unsigned case items (#5968).
* Fix constant propagation making upper bits Xs (#5969). * Fix constant propagation making upper bits Xs (#5969).

View File

@ -0,0 +1,12 @@
.. comment: generated by t_lint_procassinit_bad
.. code-block:: sv
:linenos:
:emphasize-lines: 1,5
logic flop_out = 1; // <--- Warning
always @(posedge clk, negedge reset_l) begin
if (enable) begin
flop_out <= ~in; // <--- Use of initialized
end
end

View File

@ -0,0 +1,15 @@
.. comment: generated by t_lint_procassinit_bad
.. code-block:: sv
:linenos:
:emphasize-lines: 5
logic flop2_out;
always @(posedge clk, negedge reset_l) begin
if (!reset_l) begin
flop2_out <= '1; // <--- Added reset init
end
else if (enable) begin
flop2_out <= ~in;
end
end

View File

@ -0,0 +1,12 @@
.. comment: generated by t_lint_procassinit_bad
.. code-block::
%Warning-PROCASSINIT: example.v:1:21 Procedural assignment to declaration with initial value: 'flop_out'
: ... note: In instance 't'
: ... Location of variable initialization
26 | logic flop_out = 1;
| ^
example.v:1:10 ... Location of variable process write
: ... Perhaps should initialize instead using a reset in this process
30 | flop_out <= ~in;
| ^~~~~~~~

View File

@ -1880,9 +1880,9 @@ Summary:
``-Wwarn-ASSIGNDLY`` ``-Wwarn-BLKSEQ`` ``-Wwarn-DECLFILENAME`` ``-Wwarn-ASSIGNDLY`` ``-Wwarn-BLKSEQ`` ``-Wwarn-DECLFILENAME``
``-Wwarn-DEFPARAM`` ``-Wwarn-EOFNEWLINE`` ``-Wwarn-GENUNNAMED`` ``-Wwarn-DEFPARAM`` ``-Wwarn-EOFNEWLINE`` ``-Wwarn-GENUNNAMED``
``-Wwarn-IMPORTSTAR`` ``-Wwarn-INCABSPATH`` ``-Wwarn-PINCONNECTEMPTY`` ``-Wwarn-IMPORTSTAR`` ``-Wwarn-INCABSPATH`` ``-Wwarn-PINCONNECTEMPTY``
``-Wwarn-PINNOCONNECT`` ``-Wwarn-SYNCASYNCNET`` ``-Wwarn-UNDRIVEN`` ``-Wwarn-PINNOCONNECT`` ``-Wwarn-PROCASSINIT`` ``-Wwarn-SYNCASYNCNET``
``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDLOOP`` ``-Wwarn-UNUSEDPARAM`` ``-Wwarn-UNDRIVEN`` ``-Wwarn-UNUSEDGENVAR`` ``-Wwarn-UNUSEDLOOP``
``-Wwarn-UNUSEDSIGNAL`` ``-Wwarn-VARHIDDEN``. ``-Wwarn-UNUSEDPARAM`` ``-Wwarn-UNUSEDSIGNAL`` ``-Wwarn-VARHIDDEN``.
.. option:: --x-assign <mode> .. option:: --x-assign <mode>

View File

@ -1471,6 +1471,35 @@ List Of Warnings
a var/reg must be used as the target of procedural assignments. a var/reg must be used as the target of procedural assignments.
.. option:: PROCINITASSIGN
Warns that the specified signal is given an initial value where it is
declared, and is also driven in an always process. Typically such
initial values should instead be set using a reset signal inside the
process, to match requirements of hardware synthesis tools.
Faulty example:
.. include:: ../../docs/gen/ex_PROCINITASSIGN_faulty.rst
Results in:
.. include:: ../../docs/gen/ex_PROCINITASSIGN_msg.rst
One possible fix, adding a reset to the always:
.. include:: ../../docs/gen/ex_PROCINITASSIGN_fixed.rst
Alternatively, use an initial block for the initialization:
.. code-block:: sv
initial flop_out = 1; // <--- Fixed
Disabled by default as this is a code-style warning; it will simulate
correctly.
.. option:: PROFOUTOFDATE .. option:: PROFOUTOFDATE
Warns that threads were scheduled using estimated costs, even though Warns that threads were scheduled using estimated costs, even though
@ -2164,7 +2193,7 @@ List Of Warnings
.. include:: ../../docs/gen/ex_VARHIDDEN_msg.rst .. include:: ../../docs/gen/ex_VARHIDDEN_msg.rst
To resolve this, rename the variable to an unique name. To resolve this, rename the inner or outer variable to an unique name.
.. option:: WAITCONST .. option:: WAITCONST

View File

@ -12,19 +12,26 @@ module secret_impl
input [31:0] a, input [31:0] a,
input [31:0] b, input [31:0] b,
output logic [31:0] x, output logic [31:0] x,
input clk); input clk,
input reset_l);
logic [31:0] accum_q = 0; logic [31:0] accum_q;
logic [31:0] secret_value = 9; logic [31:0] secret_value;
initial $display("[%0t] %m: initialized", $time); initial $display("[%0t] %m: initialized", $time);
always @(posedge clk) begin always @(posedge clk) begin
accum_q <= accum_q + a; if (!reset_l) begin
if (accum_q > 10) accum_q <= 0;
x <= b; secret_value <= 9;
else end
x <= a + b + secret_value; else begin
accum_q <= accum_q + a;
if (accum_q > 10)
x <= b;
else
x <= a + b + secret_value;
end
end end
endmodule endmodule

View File

@ -8,26 +8,36 @@
module top (input clk); module top (input clk);
integer cyc = 0; int cyc;
logic [31:0] a = 0; logic reset_l;
logic [31:0] b = 0; logic [31:0] a;
logic [31:0] b;
logic [31:0] x; logic [31:0] x;
verilated_secret secret (.a, .b, .x, .clk); verilated_secret secret (.a, .b, .x, .clk, .reset_l);
always @(posedge clk) begin always @(posedge clk) begin
$display("[%0t] cyc=%0d a=%0d b=%0d x=%0d", $time, cyc, a, b, x); $display("[%0t] cyc=%0d a=%0d b=%0d x=%0d", $time, cyc, a, b, x);
cyc <= cyc + 1; cyc <= cyc + 1;
if (cyc == 0) begin if (cyc == 0) begin
reset_l <= 0;
a <= 0;
b <= 0;
end
else if (cyc == 1) begin
reset_l <= 1;
a <= 5; a <= 5;
b <= 7; b <= 7;
end else if (cyc == 1) begin end
else if (cyc == 2) begin
a <= 6; a <= 6;
b <= 2; b <= 2;
end else if (cyc == 2) begin end
else if (cyc == 3) begin
a <= 1; a <= 1;
b <= 9; b <= 9;
end else if (cyc > 3) begin end
else if (cyc > 4) begin
$display("Done"); $display("Done");
$finish; $finish;
end end

View File

@ -129,6 +129,7 @@ public:
PINNOTFOUND, // instance port name not found in it's module PINNOTFOUND, // instance port name not found in it's module
PKGNODECL, // Error: Package/class needs to be predeclared PKGNODECL, // Error: Package/class needs to be predeclared
PREPROCZERO, // Preprocessor expression with zero PREPROCZERO, // Preprocessor expression with zero
PROCASSINIT, // Procedural assignment versus initialization
PROCASSWIRE, // Procedural assignment on wire PROCASSWIRE, // Procedural assignment on wire
PROFOUTOFDATE, // Profile data out of date PROFOUTOFDATE, // Profile data out of date
PROTECTED, // detected `pragma protected PROTECTED, // detected `pragma protected
@ -206,7 +207,7 @@ public:
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
"LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP", "LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP",
"MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOLATCH", "NONSTD", "NULLPORT", "PINCONNECTEMPTY", "MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOLATCH", "NONSTD", "NULLPORT", "PINCONNECTEMPTY",
"PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSWIRE", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSINIT", "PROCASSWIRE",
"PROFOUTOFDATE", "PROTECTED", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY", "PROFOUTOFDATE", "PROTECTED", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY",
"SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPLITVAR", "SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPLITVAR",
"STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
@ -259,9 +260,10 @@ public:
return (m_e == ASSIGNDLY // More than style, but for backward compatibility return (m_e == ASSIGNDLY // More than style, but for backward compatibility
|| m_e == BLKSEQ || m_e == DECLFILENAME || m_e == DEFPARAM || m_e == EOFNEWLINE || m_e == BLKSEQ || m_e == DECLFILENAME || m_e == DEFPARAM || m_e == EOFNEWLINE
|| m_e == GENUNNAMED || m_e == IMPORTSTAR || m_e == INCABSPATH || m_e == GENUNNAMED || m_e == IMPORTSTAR || m_e == INCABSPATH
|| m_e == PINCONNECTEMPTY || m_e == PINNOCONNECT || m_e == SYNCASYNCNET || m_e == PINCONNECTEMPTY || m_e == PINNOCONNECT || m_e == PROCASSINIT
|| m_e == UNDRIVEN || m_e == UNUSEDGENVAR || m_e == UNUSEDLOOP || m_e == SYNCASYNCNET || m_e == UNDRIVEN || m_e == UNUSEDGENVAR
|| m_e == UNUSEDPARAM || m_e == UNUSEDSIGNAL || m_e == VARHIDDEN); || m_e == UNUSEDLOOP || m_e == UNUSEDPARAM || m_e == UNUSEDSIGNAL
|| m_e == VARHIDDEN);
} }
// Warnings that are unused only // Warnings that are unused only
bool unusedError() const VL_MT_SAFE { bool unusedError() const VL_MT_SAFE {

View File

@ -46,6 +46,8 @@ class UndrivenVarEntry final {
const FileLine* m_alwCombFileLinep = nullptr; // File line of always_comb of var if driven const FileLine* m_alwCombFileLinep = nullptr; // File line of always_comb of var if driven
// within always_comb, else nullptr // within always_comb, else nullptr
const AstNodeVarRef* m_nodep = nullptr; // varref if driven, else nullptr const AstNodeVarRef* m_nodep = nullptr; // varref if driven, else nullptr
const AstNode* m_initStaticp = nullptr; // varref if in InitialStatic driven
const AstNode* m_procWritep = nullptr; // varref if written in process
const FileLine* m_nodeFileLinep = nullptr; // File line of varref if driven, else nullptr const FileLine* m_nodeFileLinep = nullptr; // File line of varref if driven, else nullptr
bool m_underGen = false; // Under a generate bool m_underGen = false; // Under a generate
@ -129,6 +131,11 @@ public:
m_alwCombp = alwCombp; m_alwCombp = alwCombp;
m_alwCombFileLinep = fileLinep; m_alwCombFileLinep = fileLinep;
} }
const AstNode* initStaticp() const { return m_initStaticp; }
void initStaticp(const AstNode* nodep) { m_initStaticp = nodep; }
const AstNode* procWritep() const { return m_procWritep; }
void procWritep(const AstNode* nodep) { m_procWritep = nodep; }
void underGenerate() { m_underGen = true; } void underGenerate() { m_underGen = true; }
bool isUnderGen() const { return m_underGen; } bool isUnderGen() const { return m_underGen; }
bool isDrivenWhole() const { return m_wholeFlags[FLAG_DRIVEN]; } bool isDrivenWhole() const { return m_wholeFlags[FLAG_DRIVEN]; }
@ -172,6 +179,18 @@ public:
// Combine bits into overall state // Combine bits into overall state
AstVar* const nodep = m_varp; AstVar* const nodep = m_varp;
if (initStaticp() && procWritep() && !nodep->isClassMember() && !nodep->isFuncLocal()) {
initStaticp()->v3warn(
PROCASSINIT,
"Procedural assignment to declaration with initial value: "
<< nodep->prettyNameQ() << '\n'
<< initStaticp()->warnMore() << "... Location of variable initialization\n"
<< initStaticp()->warnContextPrimary() << '\n'
<< procWritep()->warnOther() << "... Location of variable process write\n"
<< procWritep()->warnMore()
<< "... Perhaps should initialize instead using a reset in this process\n"
<< procWritep()->warnContextSecondary());
}
if (nodep->isGenVar()) { // Genvar if (nodep->isGenVar()) { // Genvar
if (!nodep->isIfaceRef() && !nodep->isUsedParam() && !unusedMatch(nodep)) { if (!nodep->isIfaceRef() && !nodep->isUsedParam() && !unusedMatch(nodep)) {
nodep->v3warn(UNUSEDGENVAR, "Genvar is not used: " << nodep->prettyNameQ()); nodep->v3warn(UNUSEDGENVAR, "Genvar is not used: " << nodep->prettyNameQ());
@ -277,10 +296,12 @@ class UndrivenVisitor final : public VNVisitorConst {
std::array<std::vector<UndrivenVarEntry*>, 3> m_entryps; // Nodes to delete when finished std::array<std::vector<UndrivenVarEntry*>, 3> m_entryps; // Nodes to delete when finished
bool m_inBBox = false; // In black box; mark as driven+used bool m_inBBox = false; // In black box; mark as driven+used
bool m_inContAssign = false; // In continuous assignment bool m_inContAssign = false; // In continuous assignment
bool m_inInitialStatic = false; // In InitialStatic
bool m_inProcAssign = false; // In procedural assignment bool m_inProcAssign = false; // In procedural assignment
bool m_inFTaskRef = false; // In function or task call bool m_inFTaskRef = false; // In function or task call
bool m_inInoutOrRefPin = false; // Connected to pin that is inout bool m_inInoutOrRefPin = false; // Connected to pin that is inout
const AstNodeFTask* m_taskp = nullptr; // Current task const AstNodeFTask* m_taskp = nullptr; // Current task
const AstAlways* m_alwaysp = nullptr; // Current always of either type
const AstAlways* m_alwaysCombp = nullptr; // Current always if combo, otherwise nullptr const AstAlways* m_alwaysCombp = nullptr; // Current always if combo, otherwise nullptr
// METHODS // METHODS
@ -384,9 +405,8 @@ class UndrivenVisitor final : public VNVisitorConst {
nodep->v3warn(PROCASSWIRE, "Procedural assignment to wire, perhaps intended var" nodep->v3warn(PROCASSWIRE, "Procedural assignment to wire, perhaps intended var"
<< " (IEEE 1800-2023 6.5): " << " (IEEE 1800-2023 6.5): "
<< nodep->prettyNameQ()); << nodep->prettyNameQ());
} } else if (m_inContAssign && !nodep->varp()->varType().isContAssignable()
if (m_inContAssign && !nodep->varp()->varType().isContAssignable() && !nodep->fileline()->language().systemVerilog()) {
&& !nodep->fileline()->language().systemVerilog()) {
nodep->v3warn(CONTASSREG, nodep->v3warn(CONTASSREG,
"Continuous assignment to reg, perhaps intended wire" "Continuous assignment to reg, perhaps intended wire"
<< " (IEEE 1364-2005 6.1; Verilog only, legal in SV): " << " (IEEE 1364-2005 6.1; Verilog only, legal in SV): "
@ -448,6 +468,13 @@ class UndrivenVisitor final : public VNVisitorConst {
if (m_alwaysCombp) if (m_alwaysCombp)
entryp->drivenAlwaysCombWhole(m_alwaysCombp, m_alwaysCombp->fileline()); entryp->drivenAlwaysCombWhole(m_alwaysCombp, m_alwaysCombp->fileline());
} }
if (nodep->access().isWriteOrRW()) {
UINFO(1, "ww is=" << m_inInitialStatic << " ipa=" << m_inProcAssign << " " << nodep
<< endl);
if (m_inInitialStatic && !entryp->initStaticp()) entryp->initStaticp(nodep);
if (m_alwaysp && m_inProcAssign && !entryp->procWritep())
entryp->procWritep(nodep);
}
if (m_inBBox || nodep->access().isReadOrRW() if (m_inBBox || nodep->access().isReadOrRW()
|| fdrv || fdrv
// Inouts have only isWrite set, as we don't have more // Inouts have only isWrite set, as we don't have more
@ -480,9 +507,16 @@ class UndrivenVisitor final : public VNVisitorConst {
m_inContAssign = true; m_inContAssign = true;
iterateChildrenConst(nodep); iterateChildrenConst(nodep);
} }
void visit(AstInitialStatic* nodep) override {
VL_RESTORER(m_inInitialStatic);
m_inInitialStatic = true;
iterateChildrenConst(nodep);
}
void visit(AstAlways* nodep) override { void visit(AstAlways* nodep) override {
VL_RESTORER(m_alwaysp);
VL_RESTORER(m_alwaysCombp); VL_RESTORER(m_alwaysCombp);
AstNode::user2ClearTree(); AstNode::user2ClearTree();
m_alwaysp = nodep;
if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) { if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) {
UINFO(9, " " << nodep << endl); UINFO(9, " " << nodep << endl);
m_alwaysCombp = nodep; m_alwaysCombp = nodep;

View File

@ -26,7 +26,7 @@ module t(/*AUTOARG*/
); );
input clk; input clk;
integer cyc = 0; int cyc;
reg [63:0] crc; reg [63:0] crc;
reg [63:0] sum; reg [63:0] sum;

View File

@ -12,7 +12,7 @@ module t (/*AUTOARG*/
); );
input clk; input clk;
integer cyc=1; int cyc;
reg [31:0] dly0; reg [31:0] dly0;
wire [31:0] dly1; wire [31:0] dly1;

View File

@ -12,8 +12,10 @@ module t_format_wide_decimal(/*AUTOARG*/
); );
input clk; input clk;
int cycle = 0; int cycle;
bit [1023:0] x = '1; bit [1023:0] x;
initial x = '1;
always @(posedge clk) begin always @(posedge clk) begin
if (cycle == 0) begin if (cycle == 0) begin

View File

@ -0,0 +1,21 @@
%Warning-PROCASSINIT: t/t_lint_procassinit_bad.v:26:21: Procedural assignment to declaration with initial value: 'flop_out'
: ... note: In instance 't'
: ... Location of variable initialization
26 | logic flop_out = 1;
| ^
t/t_lint_procassinit_bad.v:30:10: ... Location of variable process write
: ... Perhaps should initialize instead using a reset in this process
30 | flop_out <= ~in;
| ^~~~~~~~
... For warning description see https://verilator.org/warn/PROCASSINIT?v=latest
... Use "/* verilator lint_off PROCASSINIT */" and lint_on around source to disable this message.
%Warning-PROCASSINIT: t/t_lint_procassinit_bad.v:48:21: Procedural assignment to declaration with initial value: 'bad_comb'
: ... note: In instance 't'
: ... Location of variable initialization
48 | logic bad_comb = 1;
| ^
t/t_lint_procassinit_bad.v:51:7: ... Location of variable process write
: ... Perhaps should initialize instead using a reset in this process
51 | bad_comb = ok2;
| ^~~~~~~~
%Error: Exiting due to

View File

@ -0,0 +1,30 @@
#!/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('vlt')
test.lint(verilator_flags2=['-Wall -Wno-DECLFILENAME'],
fails=True,
expect_filename=test.golden_filename)
test.extract(in_filename=test.top_filename,
out_filename="../docs/gen/ex_PROCASSINIT_faulty.rst",
lines="26-32")
test.extract(in_filename=test.top_filename,
out_filename="../docs/gen/ex_PROCASSINIT_fixed.rst",
lines="36-45")
test.extract(in_filename=test.golden_filename,
out_filename="../docs/gen/ex_PROCASSINIT_msg.rst",
lines="1-9")
test.passes()

View File

@ -0,0 +1,56 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t(/*AUTOARG*/
// Inputs
clk, reset_l, in, enable
);
input clk;
input reset_l;
input in;
input enable;
logic ok1 = 1;
logic ok2 = 1;
logic ok3 = ok2;
initial begin
ok1 = 1;
end
//== Faulty example
logic flop_out = 1; // <--- Warning
always @(posedge clk, negedge reset_l) begin
if (enable) begin
flop_out <= ~in; // <--- Use of initialized
end
end
//== Fixed example
logic flop2_out;
always @(posedge clk, negedge reset_l) begin
if (!reset_l) begin
flop2_out <= '1; // <--- Added reset init
end
else if (enable) begin
flop2_out <= ~in;
end
end
// Combo version
logic bad_comb = 1; // but this is not fine
always @* begin
bad_comb = ok2;
end
wire _unused_ok = &{1'b0, flop_out, flop2_out, bad_comb, ok1, ok2, ok3};
endmodule

View File

@ -28,10 +28,10 @@ endmodule
// module unused - no warning for any of statements inside // module unused - no warning for any of statements inside
module unused(input clk); module unused(input clk);
reg unused_variable_while = 0; bit unused_variable_while;
reg unused_variable_do_while = 0; bit unused_variable_do_while;
reg unused_variable_for = 0; bit unused_variable_for;
const logic always_false = 0; const bit always_false = 0;
always @(posedge clk) begin always @(posedge clk) begin
while(unused_variable_while) begin while(unused_variable_while) begin
@ -259,7 +259,7 @@ module clock_init_race(input clk, input reset_l);
logic m_3_reset = reset_l; logic m_3_reset = reset_l;
assign m_2_clock = clk; assign m_2_clock = clk;
assign m_3_clock = clk; assign m_3_clock = clk;
int m_3_counter = 0; int m_3_counter;
initial begin initial begin
$write("*-* START TEST *-*\n"); $write("*-* START TEST *-*\n");
end end
@ -271,7 +271,7 @@ module clock_init_race(input clk, input reset_l);
end end
end end
reg m_2_ticked = 1'b0; bit m_2_ticked;
always @(posedge m_2_clock) if (!m_2_reset) begin always @(posedge m_2_clock) if (!m_2_reset) begin
m_2_ticked = 1'b1; m_2_ticked = 1'b1;
end end

View File

@ -1,37 +1,37 @@
%Warning-STMTDLY: t/t_net_delay.v:14:11: Ignoring delay on this statement due to --no-timing %Warning-STMTDLY: t/t_net_delay.v:16:11: Ignoring delay on this statement due to --no-timing
: ... note: In instance 't' : ... note: In instance 't'
14 | always #2 clk = ~clk; 16 | always #2 clk = ~clk;
| ^ | ^
... For warning description see https://verilator.org/warn/STMTDLY?v=latest ... For warning description see https://verilator.org/warn/STMTDLY?v=latest
... Use "/* verilator lint_off STMTDLY */" and lint_on around source to disable this message. ... Use "/* verilator lint_off STMTDLY */" and lint_on around source to disable this message.
%Warning-STMTDLY: t/t_net_delay.v:20:14: Ignoring delay on this statement due to --no-timing %Warning-STMTDLY: t/t_net_delay.v:22:14: Ignoring delay on this statement due to --no-timing
: ... note: In instance 't' : ... note: In instance 't'
20 | wire[3:0] #3 val1; 22 | wire[3:0] #3 val1;
| ^ | ^
%Warning-STMTDLY: t/t_net_delay.v:21:14: Ignoring delay on this statement due to --no-timing
: ... note: In instance 't'
21 | wire[3:0] #3 val2;
| ^
%Warning-ASSIGNDLY: t/t_net_delay.v:22:14: Ignoring timing control on this assignment/primitive due to --no-timing
: ... note: In instance 't'
22 | wire[3:0] #5 val3 = cyc;
| ^
... For warning description see https://verilator.org/warn/ASSIGNDLY?v=latest
... Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message.
%Warning-STMTDLY: t/t_net_delay.v:23:14: Ignoring delay on this statement due to --no-timing %Warning-STMTDLY: t/t_net_delay.v:23:14: Ignoring delay on this statement due to --no-timing
: ... note: In instance 't' : ... note: In instance 't'
23 | wire[3:0] #5 val4; 23 | wire[3:0] #3 val2;
| ^ | ^
%Warning-ASSIGNDLY: t/t_net_delay.v:24:14: Ignoring timing control on this assignment/primitive due to --no-timing %Warning-ASSIGNDLY: t/t_net_delay.v:24:14: Ignoring timing control on this assignment/primitive due to --no-timing
: ... note: In instance 't' : ... note: In instance 't'
24 | wire[3:0] #3 val5 = x, val6 = cyc; 24 | wire[3:0] #5 val3 = cyc;
| ^ | ^
%Warning-ASSIGNDLY: t/t_net_delay.v:27:11: Ignoring timing control on this assignment/primitive due to --no-timing ... For warning description see https://verilator.org/warn/ASSIGNDLY?v=latest
: ... note: In instance 't' ... Use "/* verilator lint_off ASSIGNDLY */" and lint_on around source to disable this message.
27 | assign #3 val2 = cyc; %Warning-STMTDLY: t/t_net_delay.v:25:14: Ignoring delay on this statement due to --no-timing
| ^
%Warning-STMTDLY: t/t_net_delay.v:39:26: Ignoring delay on this statement due to --no-timing
: ... note: In instance 't' : ... note: In instance 't'
39 | always @(posedge clk) #1 begin 25 | wire[3:0] #5 val4;
| ^
%Warning-ASSIGNDLY: t/t_net_delay.v:26:14: Ignoring timing control on this assignment/primitive due to --no-timing
: ... note: In instance 't'
26 | wire[3:0] #3 val5 = x, val6 = cyc;
| ^
%Warning-ASSIGNDLY: t/t_net_delay.v:29:11: Ignoring timing control on this assignment/primitive due to --no-timing
: ... note: In instance 't'
29 | assign #3 val2 = cyc;
| ^
%Warning-STMTDLY: t/t_net_delay.v:41:26: Ignoring delay on this statement due to --no-timing
: ... note: In instance 't'
41 | always @(posedge clk) #1 begin
| ^ | ^
%Error: Exiting due to %Error: Exiting due to

View File

@ -9,14 +9,16 @@
module t; module t;
// verilator lint_off UNOPTFLAT // verilator lint_off UNOPTFLAT
// verilator lint_off PROCASSINIT
logic clk = 0; logic clk = 0;
// verilator lint_on UNOPTFLAT // verilator lint_on UNOPTFLAT
// verilator lint_on PROCASSINIT
always #2 clk = ~clk; always #2 clk = ~clk;
// verilator lint_off UNDRIVEN // verilator lint_off UNDRIVEN
wire[3:0] x; wire[3:0] x;
// verilator lint_on UNDRIVEN // verilator lint_on UNDRIVEN
reg[3:0] cyc = 0; bit [3:0] cyc;
wire[3:0] #3 val1; wire[3:0] #3 val1;
wire[3:0] #3 val2; wire[3:0] #3 val2;
wire[3:0] #5 val3 = cyc; wire[3:0] #5 val3 = cyc;