SystemVerilog Series · SV-26

SystemVerilog Series — SV-26: Deprecated Features — VLSI Trainers
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 defparam can appear before the instance it modifies — the compiler must scan ahead.
  • A defparam can appear after the instance — the compiler must scan backward.
  • A defparam can be in a completely separate file — the compiler cannot know final parameter values until all design files are compiled.
  • A defparam can override a parameter hierarchically — that override may in turn depend on further defparam statements elsewhere.
  • Two defparam statements can override the same parameter — the result is undefined.
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 — 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 (assign inside an always or initial block) — becomes active when the assign statement executes and can be deactivated by a deassign statement. 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 assign can 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 assign and regular procedural assignments to the same variable is difficult to predict and tool-specific.
  • Most practical use cases for procedural assign/deassign can be handled more clearly with force/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;
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
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
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.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top