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
localandprotectedboth restrict, and the one key difference between them - What happens when you try to access a
localmember from outside its class - Why
localmembers stay invisible even to child classes - Why
protectedmembers, unlikelocalones, are visible to child classes
local vs protected at a Glance
| Qualifier | Methods of the same class | Methods of a child class | Outside the class hierarchy |
|---|---|---|---|
| public (default) | Yes | Yes | Yes |
| protected | Yes | Yes | No |
| local | Yes | No | No |
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
$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
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
$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
$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
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
localandprotectedhide a member from code outside the class hierarchy entirely localmembers are only accessible from methods of the exact same class — not even a child class can reach themprotectedmembers 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
localorprotectedmember 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.