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`ifdefbranch 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 widths
Section titled “Connection widths”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.
Quick fixes
Section titled “Quick fixes”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.
Declare missing signals
Section titled “Declare missing signals”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
logicvector (also an implicit type orreg) 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 proceduralassign) is declaredlogic, since only a variable can be assigned there;forceandreleasework on nets and change nothing. After`default_nettypewith another kind thanwire(ornone), 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 noinout. - 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
.dconnectsd. - 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.
Try it
Section titled “Try it”- Open
rtl/top.svfrom the sample project. In the instanceu_counter, delete.rst_n,. The instance name is underlined:Input not connected: 'rst_n'. - 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. - Change
.count(count)to.cont(count):contis marked as an error,Module 'counter' has no port 'cont'. Undo. - Change
logic [7:0] count;tologic [3:0] count;:countin.count(count)is underlined,Port 'count' is 8 bits wide; 'count' is 4 bits. Undo. - Change
.done(done)to.done(finished), put the caret onu_counterand press ⌥Enter (Alt+Enter): Declare ‘finished’ addswire finished;before the instance.