Features Under Consideration for Removal
Two Verilog features placed on a deprecation list by the SystemVerilog committee — defparam and procedural assign/deassign — why each is problematic, what problems each causes for tools and designers, and the clean alternatives that replace them.
⚠ Why Deprecation?
The SystemVerilog committee identified Verilog language features that share three characteristics: they are simulation inefficient, they are easily abused, and they are the source of design problems. Crucially, each deprecated feature has a clean, unambiguous alternative that provides the same capability without the problems.
Deprecation does not mean removal. Tools are still required to support both features in this standard. Deprecation means a future revision of the standard might remove them. Engineers are strongly encouraged to migrate away from these features now.
The two deprecated features are: defparam statements and procedural assign/deassign statements.
📋 defparam
A defparam statement overrides the value of a module parameter from outside the module and its instantiation hierarchy — potentially from a completely separate file, compiled separately, at any point in the design.
// Old practice — defparam overrides parameter from a separate scope module mem_ctrl; adder #() u_add(...); // instantiated with defaults defparam u_add.WIDTH = 16; // overrides WIDTH inside u_add endmodule // Or from a completely separate file — even worse: // defparam top.cpu.alu.WIDTH = 32; // buried in a separate .v file
⛔ Why defparam Is Dangerous
The core problem is that a defparam can appear almost anywhere — before, after, or in a completely different file from the instance it modifies. This creates a class of bugs that are very hard to find and a class of tool complexity that is unavoidable:
- A
defparamcan appear before the instance it modifies — the compiler must scan ahead. - A
defparamcan appear after the instance — the compiler must scan backward. - A
defparamcan be in a completely separate file — the compiler cannot know final parameter values until all design files are compiled. - A
defparamcan override a parameter hierarchically — that override may in turn depend on furtherdefparamstatements elsewhere. - Two
defparamstatements can override the same parameter — the result is undefined.
📋 defparam Alternatives
Both alternatives provide all the information at the instantiation site itself — no hunting through other files required.
Deprecated — defparam
// Parameter override buried elsewhere module top; adder u1(...); defparam u1.WIDTH = 16; // separate statement endmodule
Preferred — explicit named override
// All information at the instantiation site module top; adder #(.WIDTH(16)) u1(...); // Verilog-2001 named override // or positional: adder #(16) u1(...); endmodule
| Method | Syntax | Issues |
|---|---|---|
| defparam (deprecated) | defparam inst.PARAM = val; | Can be in any file, any order — unverifiable until all files compiled |
| Implicit positional override | #(val1, val2) | Order-dependent; all parameters up to target must be listed |
| Explicit named override (preferred) | #(.PARAM(val)) | None — self-contained, order-independent, type-checked at instantiation |
📋 Procedural assign / deassign
Verilog has two forms of the assign statement. The distinction matters:
- Continuous assignment — placed outside procedures. Creates a permanent combinational driver active throughout simulation. This form is not deprecated and is the standard way to model combinational logic.
- Procedural continuous assignment (
assigninside analwaysorinitialblock) — becomes active when theassignstatement executes and can be deactivated by adeassignstatement. This form is deprecated.
// ✓ Continuous assignment — NOT deprecated (standard RTL practice) assign y = a & b; // ✗ Procedural continuous assignment — DEPRECATED always @(posedge clk) begin if (hold) assign q = d; // activates a continuous driver on q from inside a procedure else deassign q; // removes the continuous driver end
Why procedural assign/deassign is problematic
- The fact that
assigncan appear both inside and outside procedures creates confusion — designers often do not understand which form they are using or what behaviour to expect. - Procedural continuous assignments create a hidden persistent driver that overrides normal procedural assignments to the same variable. This driver remains active until an explicit
deassign— easy to forget. - The interaction between procedural
assignand regular procedural assignments to the same variable is difficult to predict and tool-specific. - Most practical use cases for procedural
assign/deassigncan be handled more clearly withforce/release— which is always explicit and clearly distinct from normal assignments.
📋 Procedural assign / deassign Alternatives
Deprecated — procedural assign/deassign
always @(posedge clk) if (set) assign out = data; else deassign out;
Preferred — force/release or regular procedural
// Explicit force/release (testbench use) always @(posedge clk) if (set) force out = data; else release out; // Or plain procedural assignment (RTL use) always @(posedge clk) out <= (set) ? data : out;
assign/deassign, which can be confused with continuous assignment, force and release have no other meaning — they always indicate a temporary override of a signal’s value, most commonly used in testbenches. Any code reader immediately understands the intent.
📋 Quick Reference
| Feature | Why deprecated | Preferred alternative |
|---|---|---|
defparam |
Can appear in any file, any order; final parameter values unknown until all files compiled; two defparams on same parameter → undefined | Explicit named override: #(.PARAM(val)) at the instantiation site |
Procedural assign/deassign |
Creates hidden persistent driver inside a procedure; confused with continuous assignment; interaction with normal procedural assignments is unpredictable | force/release for testbench overrides; plain procedural <= or = for RTL |
defparam or procedural assign/deassign will continue to work. But new code should never use them, and existing code should be migrated at the next available opportunity.
