Skip to content

Instance connections

Two inspections (Settings | Editor | Inspections | SystemVerilog) check each instance of a module, interface or program against the unit it instantiates, as you type. Instance connections reports what a tool would reject; Unconnected instance inputs reports inputs left out. Each has its own level in the inspection profile.

Reported Example Level
A port the unit does not have .d(1) — Module 'sub' has no port 'd' Error
A port connected twice .clk(a), .clk(b) Error
More positional connections than ports sub u(a, b, c, d) for three ports Error
An interface port left out u(.c(1'b0)) — Interface port 'bus' is not connected Error
A parameter the unit does not have, or a local parameter #(.X(2)), #(.H(2)) — 'H' cannot be overridden: it is a local parameter Error
A parameter set twice #(.N(1), .N(2)) Error
More parameter values than the unit lets you set #(4, 1, 7) for two Error
A parameter without a default that is not set #(.W(4)) when N has no default Error
Inputs left out (Unconnected instance inputs) u(.clk(1'b0), .q()) — Input not connected: 'rst' Warning

These are not reported:

  • Outputs left out (they stay open), ports listed with an empty connection such as .rst(), and ports that .* connects.
  • An input with a default value (input logic en = 1'b1), which may be left out.
  • A parameter without a default that a defparam u.N = …; in the same file sets.
  • A list with a macro in it (u(`PORTS), #(`P)): the macro may expand to any connections, so the list is not counted and no port or parameter is reported missing.
  • Names and counts, when an item of the unit’s own port or parameter list is a macro or an `include (module sub(input clk, `EXTRA_PORTS);, #(parameter N = 1, `MORE), #(`include "params.vh")) or sits in an `ifdef branch the IDE sees as inactive (`ifdef USE_POWER_PINS inout vccd1, `endif): the list may have ports or parameters the IDE cannot see. For a unit without a #(…) list the same holds for a macro or an inactive branch among its body items. A macro inside an item — a width such as [`W-1:0], a type, a default, a procedural block — changes nothing. Known inputs left out of a named list, a port connected or a parameter set twice, and a parameter without a default when no value is given by position are still reported.
  • Names and counts, when the unit’s header does not parse (for example a macro used as an operator in a default, B = A `PLUS 1, or a header still being typed): what it declares is not known.
  • Instances of units the IDE cannot find, gates and UDPs, and units defined more than once in other files (a definition in the instance’s own file is the one checked against).

A non-ANSI header names the ports an instance connects: module ex(.a(x), .b(y)) has ports a and b, and a port such as {a, b} has no name, so it can be connected by position only and is not reported when a named list leaves it out.

Connection width mismatch warns when a port and the signal connected to it differ in width — legal (the value is truncated or extended, IEEE 1800 §23.3.3.7) but rarely meant: .d(a) for input logic [7:0] d and logic [3:0] a reads Port 'd' is 8 bits wide; 'a' is 4 bits. A signal, a select of one (a[3:0], a[i], a[i +: 4]) and a concatenation of those ({a, b}) are compared, by name or by position.

Widths are compared only where both are constants: ranges of literals, local and package parameters (localparam int L = 4;, pkg::W), $clog2, and the parameters of the instantiated module as the instance sets them (#(.W(4)), else their defaults). Nothing is reported when a width depends on a parameter of the module you are in that its own instances may set (parameter W of the enclosing module), on a macro, on a type other than a bit vector or an integer type (a typedef, a struct), on a parameter a defparam in the file sets, or when the signal is an array. Values have the width of their type: a parameter or an expression whose value would be truncated (localparam bit [3:0] A = 16;) is not taken as a constant. An array of instances (sub u[3:0](.d(bus))) is not compared: each instance takes a slice of the signal. An interconnect port or net, which has no data type of its own, is not compared either. A signal’s width is read where the signal is declared.

Press ⌥Enter (Alt+Enter) on a problem for its quick fix:

  • Connect missing ports (on the instance’s name) adds a named connection for every port left out, after the existing ones and in their layout: one per line if they are one per line, a comment at the end of the last line kept on its line. It connects .rst(rst) where a signal of the same name is visible and fits the port (the same rules as code completion in a port connection), else .rst().
  • Remove connection removes a connection the unit has no port or parameter for, or a repeated one, with its comma. Comments around it stay, and a line it leaves blank is removed.

Only the text added or removed changes: the rest of the statement, comments and `ifdef lines included, is left as written.

On an instance, ⌥Enter (Alt+Enter) offers Declare ‘x’ (or Declare missing signals for several) when it connects names that are not declared yet. Each gets a declaration with the type of the port it is connected to — for input logic [W-1:0] d in sub #(.W(4)) u(.d(din)), wire [4-1:0] din;:

  • A logic vector (also an implicit type or reg) is declared a net, wire, as the undeclared name was (an implicit net): any number of drivers stays legal. A name the module assigns in procedural code (x = …, x <= …, x++, a procedural assign) is declared logic, since only a variable can be assigned there; force and release work on nets and change nothing. After `default_nettype with another kind than wire (or none), the action is not offered: the name was a net of that kind.
  • Another type (bit, int, a typedef) gives a variable, which may have only one driver: it is declared only when the instance statement is all that uses the name, drives it at most once and connects it to no inout.
  • The instantiated module’s parameters are replaced by what the instance sets them to, as written (#(.W(W)) gives [W-1:0]), else by their defaults; a type parameter by its type.
  • A name the module sees through a package it imports is qualified with the package (p::t), also when the instance’s own scope declares one of the same name. If the port’s type uses a name the module sees at file level in another file, nothing is declared: that file’s declarations may not be visible here.
  • Unpacked dimensions follow the name. A name connected to several ports is declared once, with the type of the first; every instance of the statement counts, and an implicit .d connects d.
  • The declarations go before the first statement that uses one of the names (else that use would declare an implicit net), and before an attribute such as (* keep *) that belongs to it; if the instance shares its line with code before it, it moves to a line of its own. If that would put them above a declaration they use, the action is not offered.

Only plain names are declared: expressions, constants and selects are left alone, as are names connected to an interface port, an interconnect or a non-ANSI port that is part of a signal (.e(f[3:0])), a name that already names a type, and names an array of instances (sub u[1:0](…)) connects anywhere in the scope — each element takes a slice. A generate … endgenerate region is not a scope: uses around it count. It is not offered for an instance that is the body of an if, for or case generate without begin: a declaration there would change what the construct contains. In a generate block, a name the enclosing module also uses is not declared: declared in the block it would be another signal.

  1. Open rtl/top.sv from the sample project. In the instance u_counter, delete .rst_n, . The instance name is underlined: Input not connected: 'rst_n'.
  2. Put the caret on u_counter, press ⌥Enter (Alt+Enter) and choose Connect missing ports: .rst_n(rst_n) is added at the end of the list.
  3. Change .count(count) to .cont(count): cont is marked as an error, Module 'counter' has no port 'cont'. Undo.
  4. Change logic [7:0] count; to logic [3:0] count;: count in .count(count) is underlined, Port 'count' is 8 bits wide; 'count' is 4 bits. Undo.
  5. Change .done(done) to .done(finished), put the caret on u_counter and press ⌥Enter (Alt+Enter): Declare ‘finished’ adds wire finished; before the instance.