SystemVerilog Series — SV-26: Deprecated Features — VLSI Trainers
VLSI Trainers SV Series · 42 / 44
SystemVerilog Series · SV-26

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 Verilog compiler cannot determine final parameter values for any instance until every design file has been compiled. This is not a theoretical concern — it is an inherent consequence of the feature’s design. It blocks incremental compilation, makes large designs slow to elaborate, and makes it impossible to check parameter consistency at the point of instantiation.

📋 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
MethodSyntaxIssues
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 — 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

📋 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;
force/release is always explicit. Unlike 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

FeatureWhy deprecatedPreferred alternative
defparamCan appear in any file, any order; final parameter values unknown until all files compiled; two defparams on same parameter → undefinedExplicit named override: #(.PARAM(val)) at the instantiation site
Procedural assign/deassignCreates hidden persistent driver inside a procedure; confused with continuous assignment; interaction with normal procedural assignments is unpredictableforce/release for testbench overrides; plain procedural <= or = for RTL
These features are still supported by tools. Deprecation is a warning, not a removal. Existing code using 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.
Coming next: SV-27 covers the Direct Programming Interface (DPI) — calling C functions from SystemVerilog, calling SV tasks and functions from C, import and export declarations, argument types and passing modes, and the pure/context qualifier rules.
Compiler Directives☰ SV Series IndexDirect Programming Interface (DPI)
Scroll to Top