The local and protected access qualifiers both restrict visibility of a class's properties and methods, for the sake of encapsulation. The key difference between them: local members are not visible to subclasses at all, while protected members are visible to (and inheritable by) subclasses — both stay hidden from code outside the class hierarchy entirely.

10 min read | Intermediate Level

What You'll Learn

  • What local and protected both restrict, and the one key difference between them
  • What happens when you try to access a local member from outside its class
  • Why local members stay invisible even to child classes
  • Why protected members, unlike local ones, are visible to child classes

local vs protected at a Glance

QualifierMethods of the same classMethods of a child classOutside the class hierarchy
public (default)YesYesYes
protectedYesYesNo
localYesNoNo

Access Qualifier: local

A member declared local is available only to methods of the same class — not to child classes, and not to code outside the class at all. A method that itself accesses a local member can still be inherited and overridden by a child class, though; it's the member that stays hidden, not necessarily every method that touches it.

Accessing a local Member From Outside the Class


class ABC;
  // By default, all variables are public and for this example,
  // let's create two variables - one public and the other "local"
  byte  	  public_var;  
  local byte local_var;
  
  // This function simply prints these variable contents
  function void display();
    $display ("public_var=0x%0h, local_var=0x%0h", public_var, local_var);
  endfunction
endclass

module tb;
  initial begin
  
    // Create a new class object, and call display method
    ABC abc = new();
    abc.display();
  
    // Public variables can be accessed via the class handle
    $display ("public_var = 0x%0h", abc.public_var);
  
    // However, local variables cannot be accessed from outside
    $display ("local_var = 0x%0h", abc.local_var);
  end
endmodule

Output

Output
    $display ("local_var = 0x%0h", abc.local_var);
                                               |
ncvlog: *E,CLSNLO (testbench.sv,24|47): Access to local member 'local_var' in class 'ABC' is not allowed here.
irun: *E,VLGERR: An error occurred during parsing.  Review the log file for errors with the code *E and fix those identified problems to proceed.  Exiting with code (status 1).

Removing the offending line entirely, local_var is still readable from inside display(), since that method belongs to the same class:


module tb;
  initial begin
  
    ABC abc = new();
  
    // This should be able to print local members of class ABC
    // because display() is a member of ABC also
    abc.display();
  
    // Public variables can always be accessed via the class handle
    $display ("public_var = 0x%0h", abc.public_var);
  end
endmodule

Output

Output
ncsim> run
public_var=0x0, local_var=0x0
public_var = 0x0
ncsim: *W,RNQUIE: Simulation is complete.

Quick Check

Q: If display() were called from a completely unrelated module (not from inside ABC), would it still be able to print local_var?

Show Answer

Yes. What matters is where the method itself is defined, not where it's called from — display() is a method of ABC, so it can access ABC's local members no matter which scope actually calls abc.display().

Accessing a local Member From a Child Class

local members stay invisible even to a class that extends the one declaring them:


// Define a base class and let the variable be "local" to this class
class ABC;
  local byte local_var;
endclass

// Define another class that extends ABC and have a function that tries
// to access the local variable in ABC
class DEF extends ABC;  
  function show();
    $display ("local_var = 0x%0h", local_var);
  endfunction
endclass

module tb;
  initial begin
  
    // Create a new object of the child class, and call the show method
    // This will give a compile time error because child classes cannot access
    // base class "local" variables and methods
    DEF def = new();
    def.show();

  end
endmodule

Output

Output
    $display ("local_var = 0x%0h", local_var);
                                           |
ncvlog: *E,CLSNLO (testbench.sv,10|43): Access to local member 'local_var' in class 'ABC' is not allowed here.
irun: *E,VLGERR: An error occurred during parsing.  Review the log file for errors with the code *E and fix those identified problems to proceed.  Exiting with code (status 1).

DEF inherits from ABC, but its own show() method still can't reach ABC's local_var — inheritance alone doesn't grant access to a base class's local members.

Access Qualifier: protected

protected is a middle ground: more restrictive than public, but less restrictive than local. A protected member is available to methods of the declaring class and to subclasses, but still not visible from outside the class hierarchy at all.

Accessing a protected Member From Outside the Class


class ABC;
  // By default, all variables are public and for this example,
  // let's create two variables - one public and the other "protected"
  byte  	   		public_var;  
  protected byte 	protected_var;
  
  // This function simply prints these variable contents
  function void display();
    $display ("public_var=0x%0h, protected_var=0x%0h", public_var, protected_var);
  endfunction
  
endclass

module tb;
  initial begin
  
    // Create a new class object, and call display method
    ABC abc = new();
    abc.display();
  
    // Public variables can be accessed via the class handle
    $display ("public_var = 0x%0h", abc.public_var);
  
    // However, protected variables cannot be accessed from outside
    $display ("protected_var = 0x%0h", abc.protected_var);
  end
endmodule

Output

Output
 $display ("protected_var = 0x%0h", abc.protected_var);
                                                       |
xmvlog: *E,CLSNPO (testbench.sv,29|55): Access to protected member 'protected_var' in class 'ABC' is not allowed here.

Note the different error code here (CLSNPO, versus local's CLSNLO) — the tool distinguishes exactly which access qualifier was violated.

Accessing a protected Member From a Child Class

This is the one case that behaves differently from local — a child class can reach a protected member of its parent:


// Define a base class and let the variable be "protected" to this class
class ABC;
  protected byte protected_var;
endclass

// Define another class that extends ABC and have a function that tries
// to access the protected variable in ABC
class DEF extends ABC;  
  function show();
    $display ("protected_var = 0x%0h", protected_var);
  endfunction
endclass

module tb;
  initial begin
  
    // Create a new object of the child class, and call the show method
    // This works fine: unlike "local", "protected" members CAN be accessed
    // by methods of a child class
    DEF def = new();
    def.show();

  end
endmodule

Output

Output
xcelium> run
protected_var = 0x0
xmsim: *W,RNQUIE: Simulation is complete.

Same structure as the failing local example earlier — but this one compiles and runs cleanly, since protected_var is exactly the kind of member protected is meant to expose to subclasses.

Quick Check

Q: If DEF in this example were instantiated and def.protected_var were accessed directly from the tb module (not through show()), would that compile?

Show Answer

No. protected only opens access to the class hierarchy itself (the declaring class and its subclasses) — tb is outside that hierarchy entirely, so a direct def.protected_var reference would fail exactly like the earlier "accessed from outside" example did.

Where Are local and protected Used?

Base classes with many subclasses — UVM's component and object base classes are a good example — commonly use protected for internal state that a derived class is expected to read or extend, while reserving local for implementation details that no subclass should ever need to touch directly, no matter how deeply it extends the hierarchy.

Common Beginner Mistakes

Mistake #1: Treating local and protected as interchangeable

Both block access from outside the class hierarchy, which can make them look equivalent at a glance. Why? The difference only shows up with subclasses — protected members are inherited and accessible in a child class, local members are not, no matter how the child class is written.

Mistake #2: Expecting a runtime warning instead of a compile error

Accessing a local or protected member from somewhere it isn't allowed fails at compile time, before simulation ever starts. Why? This is a static, structural rule about the code's scope — there's no scenario where it "usually works" and occasionally fails at run time.

Mistake #3: Assuming local means private to a single method

As the first local example shows, display() can freely read local_var even though it isn't the only method in the class. Why? local restricts visibility to the whole class, not to one specific method — any method belonging to that same class can access it.

Practice Exercise

Challenge: Mix local and protected in One Base Class

Given a base class with both a local byte secret; and a protected byte shared;, write a child class with a method that tries to access both. Which line compiles, and which doesn't?

Hint

Apply the same rule demonstrated in both sections above to each member independently — they don't have to behave the same way just because they're declared in the same class.

Solution

class Base;
  local     byte secret;
  protected byte shared;
endclass

class Derived extends Base;
  function void show();
    $display ("shared = 0x%0h", shared);   // Compiles fine
    $display ("secret = 0x%0h", secret);   // Compile error
  endfunction
endclass

The line accessing shared compiles without any issue, since protected members are visible to subclasses. The line accessing secret fails to compile with the same kind of error shown earlier in this article — local members stay invisible to Derived regardless of the fact that it extends Base.

Summary

In this tutorial, you learned:

  • Both local and protected hide a member from code outside the class hierarchy entirely
  • local members are only accessible from methods of the exact same class — not even a child class can reach them
  • protected members are accessible from methods of the declaring class and any subclass
  • Both restrictions are enforced at compile time, not run time
  • A method that accesses a local or protected member can still itself be inherited and overridden — it's the member's visibility that's restricted, not the method's

Continuing the Advanced Features Chapter

Continue with SystemVerilog Functions.

Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5