To manage the mutability of class properties, SystemVerilog provides the const keyword, allowing properties to be made read-only. Due to the dynamic nature of class objects, this manifests in two distinct forms: global constant class properties and instance constant class properties.

9 min read | Intermediate Level

What You'll Learn

  • The difference between a global constant class property and an instance constant class property
  • Why global constants are commonly declared static, and why instance constants never can be
  • Why an instance constant can only ever be assigned inside the constructor
  • What happens if you try to assign either kind of constant from outside its class

Global Constant Class Properties

A global constant class property is a read-only data member assigned its value as part of its own declaration. Like other const variables in SystemVerilog, its value can't be changed anywhere else after that initial declaration. A common practice is to declare global constants static as well, meaning every object of the class shares the exact same constant value:


class Jumbo_Packet;
  // max_size is a global constant, same for all Jumbo_Packet instances
  const int max_size = 5 * 10;

  byte payload [];

  function new(int size);
    // payload size is limited by the global constant max_size
    payload = new[ size > max_size ? max_size : size ];
  endfunction
endclass

module tb;
  Jumbo_Packet 	m_pkt;
  
  initial begin
    m_pkt = new(100);
  
    $display("size=%d", m_pkt.payload.size());
  end
endmodule

Output

Output
xcelium> run
size=         50
xmsim: *W,RNQUIE: Simulation is complete.

max_size evaluates to 50 at declaration time. Since the requested size (100) exceeds it, the constructor clamps payload's actual size down to max_size instead.

Quick Check

Q: If a second object were created with new(30) instead, what would its payload size be?

Show Answer

30. Since 30 doesn't exceed max_size (50), the ternary in the constructor takes the requested size as-is, with no clamping needed.

Instance Constant Class Properties

An instance constant class property doesn't include an initial value in its declaration — only the const qualifier. It can be assigned a value exactly once at run time, and that assignment must happen inside the class's own constructor. Unlike global constants, instance constants can never be declared static, since that would prevent them from being assigned per-object inside the constructor at all — their entire purpose is to differ from one object to the next:


class Big_Packet;
  // size is an instance constant, determined at object creation
  const int size;

  byte payload [];

  function new();
    // The instance constant 'size' is assigned its value once in the constructor
    size = $urandom % 10;
    payload = new[ size ];
  endfunction
endclass

module tb;
  Big_Packet 	m_pkt;
  
  initial begin
    m_pkt = new();  
  
    $display("size=%d", m_pkt.payload.size());
  
    // This will result in a compilation error
    // xmvlog: *E,CLSCON (testbench.sv,23|13): Instance constant class properties cannot be assigned outside of a constructor.
    // m_pkt.size = 50;
  end
endmodule

Output

Output
xcelium> run
size=          4
xmsim: *W,RNQUIE: Simulation is complete.

size is assigned once, inside new(), and its exact value here depends on the simulation's random seed — a different seed would produce a different (but still fixed, once assigned) value for that specific object.

Here's that commented-out line demonstrated directly, as its own standalone example:


class Big_Packet;
  const int size;
  byte payload [];

  function new();
    size = $urandom % 10;
    payload = new[ size ];
  endfunction
endclass

module tb;
  Big_Packet m_pkt;

  initial begin
    m_pkt = new();
    m_pkt.size = 50;    // Attempting to reassign the instance constant from outside its constructor
  end
endmodule

Output

Output
xmvlog: *E,CLSCON (testbench.sv,23|13): Instance constant class properties cannot be assigned outside of a constructor.

Quick Check

Q: Does m_pkt.size = 50; fail at compile time or run time?

Show Answer

Compile time — note the ncvlog/xmvlog prefix on the error, which is the compiler's own analysis stage, not the simulator actually running anything. The restriction is checked before simulation ever starts.

Difference Between Global and Instance

Global constantInstance constant
Initial valueGiven at declarationNone at declaration
When assignedOnce, at declarationOnce, inside the constructor
Can be staticYesNo
Value across objectsSame for every instanceCan differ per instance

Where Are Const Class Properties Used?

A global constant fits a protocol-wide fixed limit that's genuinely the same for every object — a maximum burst length, or a maximum payload size shared across every transaction. An instance constant fits a value that's fixed once an object is created but is meant to vary between objects — like a uniquely assigned (and then immutable) transaction ID.

Common Beginner Mistakes

Mistake #1: Trying to assign an instance constant outside its constructor

As the standalone CLSCON example shows, this is always a compile-time error, no matter where outside the constructor the attempt happens. Why? An instance constant's entire point is to be fixed exactly once, at construction — allowing any later assignment would defeat that guarantee entirely.

Mistake #2: Declaring an instance constant as static

This isn't allowed. Why? static means one shared value across every object, but an instance constant exists specifically to let each object have its own distinct value, assigned individually inside its own constructor call — the two ideas are directly incompatible.

Mistake #3: Confusing global and instance constants' assignment timing

A global constant's value is fixed once for the entire class, computed at declaration — it can't be recalculated per object the way an instance constant can. Why? If a value genuinely needs to vary between objects (like a random per-object ID), it has to be an instance constant, assigned in the constructor — a global constant simply can't do that.

Mistake #4: Assuming a const property without static means "per instance" automatically

A non-static const property still needs to actually declare an initial value or be assigned in the constructor to be either a global or instance constant, respectively — the static keyword itself isn't what determines which kind it is. Why? The real distinguishing factor is whether the value is given at declaration (global) or left for the constructor to assign (instance), not the presence or absence of static alone — though static is only ever legal on the global kind.

Practice Exercise

Challenge: Combine Both Kinds of Constant

Write a class Transaction with a global constant static const int MAX_ID = 100; and an instance constant const int id;. In the constructor, accept a requested_id argument, and assign id to whichever is smaller: requested_id or MAX_ID. Create two objects — one with a requested ID under the limit, one over it — and display both.

Hint

The clamping logic here is the same ternary pattern used in the Jumbo_Packet example — just applied to an instance constant instead of a plain property.

Solution

class Transaction;
  static const int MAX_ID = 100;
  const int id;

  function new (int requested_id);
    id = (requested_id > MAX_ID) ? MAX_ID : requested_id;
  endfunction
endclass

module tb;
  initial begin
    Transaction t1 = new (50);
    Transaction t2 = new (150);
    $display ("t1.id=%0d, t2.id=%0d", t1.id, t2.id);
  end
endmodule

This prints t1.id=50, t2.id=100. t1's requested ID (50) is under the shared limit, so it's used as-is; t2's requested ID (150) exceeds MAX_ID, so it's clamped down to 100 — each object's id is fixed permanently the moment its constructor finishes.

Summary

In this tutorial, you learned:

  • A global constant class property is assigned its value at declaration, and typically declared static so every object shares it
  • An instance constant class property has no initial value at declaration, and is assigned exactly once, inside the constructor — letting each object have its own distinct value
  • An instance constant can never be declared static, since that would conflict with assigning it per-object
  • Assigning either kind of constant outside its allowed point — declaration for global, constructor for instance — is a compile-time error, not a run-time one
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5