Skip to content

Go to Declaration

Click inside a name (the blinking text cursor is called the caret) and choose Navigate | Declaration or Usages (⌘B on macOS, Ctrl+B on Windows/Linux), or hold ⌘ (Ctrl) and click the name. The editor opens the declaration, in whichever file it is. On the declaration itself the IDE shows its usages instead (see Find Usages). Use it to find where a module, parameter, function or class member is defined without searching by hand.

What the video shows
  1. top.sv instantiates the module counter.
  2. Go to Declaration (⌘B / Ctrl+B) opens its definition in counter.sv.
  3. Find Usages (⌥F7 / Alt+F7) lists every usage, including the end label endmodule : counter.
  4. Names are colored by what they are (shown in the SystemVerilog Studio Dark color scheme).

Names are resolved the way a SystemVerilog tool resolves them: inner scopes first, then enclosing scopes, base classes, imported packages and finally the whole project. Two things with the same name in different scopes are never confused: a signal data in two modules, or two classes item in two packages. (A scope is a module, class, function or begin … end block.) See How names are resolved for details.

You are on… You go to…
The module name in an instantiation counter u1(...) The module declaration
.clk(...) in a named port connection The port of the instantiated module
.MAX(...) in a parameter override #(.MAX(20)) The parameter
An interface type (my_if bus, virtual my_if vif) or a modport (bus_if.mp) The interface or modport
A class name in a declaration, extends, implements, #(my_item) or my_item::type_id The class
pkg::item, or an item imported with import pkg::*; or import pkg::item; The item in the package
A function or task call, including methods inherited from a base class and super.f() The function or task
obj.x, this.x, q[i].x, chains like env.agt.drv.vif The class member
vif.req, u1.sig, g_lane[0].busy, vif.cb.req The interface signal, instance signal, generate-block signal or clocking item
An enum member, typedef, struct field (s.inner.field) Its declaration
An end label (endmodule : counter, end : seq) The block or design element it closes

For example, counter below uses my_item, a class of the package my_pkg, without importing it:

module counter;
my_item x; // warning: my_pkg is not imported
endmodule

With import my_pkg::*; added inside the module, the warning goes away (Try it, steps 7 and 8). In general, a name declared in a package is visible only where that package is imported (import my_pkg::*; or import my_pkg::my_item;) or when you write it qualified (my_pkg::my_item). If you use it without either, simulators report it as undeclared, and the plugin:

  • underlines it with the warning ‘my_item’ is declared in package ‘my_pkg’, which is not imported here;
  • offers the quick fix Import my_pkg::* (⌥⏎ / Alt+Enter). It adds the import after the module’s other imports, or after the module header. When the name is used in the module’s parameter or port list, or in a class outside any package, the import goes at file level (after the file’s imports, or right before the module or class). Applying the fix to several usages adds the import once;
  • still navigates: Go to Declaration opens the package member (if several packages declare the name, you choose).

There is no warning when the name may be visible after all: in a file that another file includes (`include "my_item.svh", typically inside a package — names that package declares or imports are visible there), or in a class whose base class is not in the project or is a typedef or type parameter (the name may be inherited from it, as with uvm_driver when UVM is not attached), or where the scope imports a package the project does not have (a package generated at build time, such as a register package: the name may come from it). Packages that re-export names (export other_pkg::*;) are followed, so names reached through them are visible, not reported.

Find Usages and Rename do not count such a usage until the package is imported: after a rename of my_item, this usage keeps the old name, so add the import first. You can turn the warning off in Settings | Editor | Inspections | SystemVerilog | Name declared in a package that is not imported.

Open the sample project and wait until indexing has finished (the progress bar at the bottom right disappears).

  1. Open rtl/top.sv. ⌘-click (Ctrl-click) the first word counter (not u_counter) in counter #(.MAX(20)) u_counter. rtl/counter.sv opens at module counter.
  2. Back in rtl/top.sv, ⌘-click MAX in #(.MAX(20)). You land on parameter int MAX = 10 in rtl/counter.sv.
  3. In rtl/counter.sv, ⌘-click IDLE in state <= IDLE;. rtl/counter_pkg.sv opens at the enum member IDLE — the name comes from import counter_pkg::*;.
  4. In rtl/counter.sv, ⌘-click is_done in assign done = is_done(state);. You land on the function in rtl/counter_pkg.sv.
  5. In rtl/top.sv, ⌘-click busy in $display(g_lane[0].busy);. You land on logic busy; inside the generate loop.
  6. In uvm/my_pkg.sv, find agt.drv.vif = null; in class my_env and ⌘-click vif. You land on virtual my_if vif; in class my_driver: the chain agt → my_agent, drv → my_driver was followed (agt is declared as my_agent agt; and drv as my_driver drv;, a few lines above).
  7. In rtl/counter.sv, add the line my_item x; after state_t state;. my_item gets a wavy warning underline (hover it for the message): it is a class in my_pkg, which counter does not import. No underline? Wait for indexing to finish, and check that the inspection Name declared in a package that is not imported is enabled (see the end of the section above). (my_pkg.sv is found although sim.f does not list it: the whole project is searched.) ⌘-click it: uvm/my_pkg.sv opens at class my_item.
  8. Back in rtl/counter.sv, put the caret on my_item, press ⌥⏎ (Alt+Enter) and choose Import my_pkg::*. The line import my_pkg::*; is added after import counter_pkg::*; and the warning goes away.

To restore the sample project, undo both edits in rtl/counter.sv with Edit | Undo (⌘Z / Ctrl+Z) or delete the two lines my_item x; and import my_pkg::*;. If a step does not land where it should, see If it doesn’t work.

  • Macro names and the names passed to a macro are navigable (see Macros). Names that a macro declares are navigable only when the macro is called among a class’s items; elsewhere they are not.
  • See Known limitations for the complete list.
You see Likely cause What to do
Nothing happens, or no target is found, right after opening Indexing has not finished Wait for the progress bar at the bottom right
A UVM name such as uvm_driver finds nothing The UVM library is not in the project See Known limitations
A name in greyed-out code finds nothing Its `ifdef branch is inactive See Conditional compilation
A list of usages opens instead of a jump You were on the declaration itself Use Find Usages for the list; Go to Declaration is for names that are uses
The key does nothing Your keymap differs Use the menu Navigate | Declaration or Usages