Ports, Module Instances, Port Rules & Name Spaces
SV port declaration enhancements — any data type through ports, named port expressions, direction/type inheritance; four module instantiation styles from positional to .*; extended port connection rules for variables, nets, interfaces and arrays; eight name spaces; and hierarchical names.
📋 Port Declarations
In Verilog-2001 only nets, regs, integers, and times could pass through module ports. SystemVerilog removes this restriction — any variable data type can appear on a port, including arrays, structs, unions, reals, and interfaces.
// Any SV data type is legal as a port type typedef struct { bit isfloat; union { int i; shortreal f; } n; } tagged_st; module mh1(input int in1, input shortreal in2, output tagged_st out); endmodule // Interface ports — generic (any type) or named (specific type) module cpuMod(interface d, interface j); // generic interface ports endmodule
📋 Direction and Type Inheritance
In the ANSI port list style, direction and type are inherited from the previous port when omitted.
| What is omitted | What is inherited / defaulted |
|---|---|
| Both direction and type (first port) | It is treated as a port list member — direction and type declared separately after the port list (Verilog-1995 compatible style) |
| Both direction and type (subsequent port) | Both inherited from the previous port |
| Direction only (type given) | Direction inherited from the previous port |
| Type only (direction given) | Type defaults to wire (or 'default_nettype) |
| First port has type but no direction | Direction defaults to inout |
| First port has direction but no type | Type defaults to wire |
// Both inherited: b has same direction (input) and type (byte) as a module mh3(input byte a, b); endmodule // Mixed: explicit output with type, then inherited module mh5(input clk, input logic[7:0] a, b, output logic[7:0] y, z); // clk: input wire (type defaults to wire) // a: input logic [7:0] (explicit) // b: input logic [7:0] (inherits from a) // y: output logic [7:0] (explicit) // z: output logic [7:0] (inherits from y) endmodule // Verilog-1995 style: first port has neither direction nor type // → all declarations must follow port list module mh4(x, y); wire x; tri0 y; endmodule
📋 Named Port Expressions
SV adds explicitly named port expressions to the ANSI style, allowing array slices, struct members, concatenations, and other aggregate expressions to be exposed as a single named port.
module mymod( output .P1(r[3:0]), // port name P1 maps to bits [3:0] of internal r output .P2(r[7:4]), // port name P2 maps to bits [7:4] of internal r ref .Y(x), // port name Y is a ref port connected to int x input bit R // normal ANSI port ); logic [7:0] r; // internal — split across P1 and P2 int x; // internal — referenced by ref port Y endmodule // Rules for named port expressions: // — Port identifier namespace is separate per port list // — Self-determined type of the expression becomes the port type // — Aggregate expressions require a cast (self-determined aggregates not allowed) // — Port expression is optional: a port can be declared without an internal connection
🕐 Time Unit and Precision
timeunit and timeprecision are module-bound declarations, replacing `timescale with a portable, file-order-independent mechanism.
module fast_dut; timeunit 100ps; // time unit for this module timeprecision 10fs; // precision for this module // Both declarations must come BEFORE any other items in this time scope endmodule // Combined single-line form (legal) timeunit 1ns; timeprecision 1ps; // Precedence for unspecified time unit (in order): // 1. Nested: inherit from enclosing module/interface // 2. 'timescale directive previously seen in this compilation unit // 3. timeunit declaration in the compilation-unit scope // 4. Tool default // // Global time precision = minimum of all timeprecision declarations // and the smallest 'timescale precision in the design. // The 'step' time unit equals the global time precision.
🔄 Module Instances — Four Connection Styles
SV adds two new shorthand forms (.name and .*) to Verilog-2001’s positional and named styles. All four can be mixed in the same parent module.
(Verilog-2001)
(Verilog-2001)
(SV new)
(SV new)
Each new style reduces boilerplate while still requiring explicit naming for exceptions (size mismatches, different names, unconnected ports).
📋 Positional Port Connections
module alu_accum1(...); wire [7:0] alu_out; // Positional: connect by declaration order; skip zero with empty comma alu alu (alu_out, , ain, bin, opcode); // zero port skipped accum accum (dataout[7:0], alu_out, clk, rst_n); xtend xtend (dataout[15:8], alu_out[7], clk, rst_n); endmodule
📋 Named Port Connections
module alu_accum2(...); wire [7:0] alu_out; // Named: any order; .zero() leaves the port unconnected alu alu (.alu_out(alu_out), .zero(), .ain(ain), .bin(bin), .opcode(opcode)); accum accum (.dataout(dataout[7:0]), .datain(alu_out), .clk(clk), .rst_n(rst_n)); xtend xtend (.dout(dataout[15:8]), .din(alu_out[7]), .clk(clk), .rst_n(rst_n)); endmodule
📋 .name Implicit Connections
.port_name (without parentheses) is shorthand for .port_name(port_name) when the external signal name and port name are identical and the same size. Still lists every port explicitly — good for documentation.
module alu_accum3(...); wire [7:0] alu_out; // .alu_out → .alu_out(alu_out) (name and size match) // .zero() → explicit: unconnected // .ain, .bin, .opcode → implicit .name (all match) // .dataout(dataout[7:0]) → explicit: size mismatch (8-bit vs 16-bit) // .datain(alu_out) → explicit: different name // .clk, .rst_n → implicit .name alu alu (.alu_out, .zero(), .ain, .bin, .opcode); accum accum (.dataout(dataout[7:0]), .datain(alu_out), .clk, .rst_n); xtend xtend (.dout(dataout[15:8]), .din(alu_out[7]), .clk, .rst_n); endmodule
.name connection rules
- Port and external signal must have the same name and same size.
- Does not create an implicit wire declaration (unlike Verilog named connections with undeclared signals).
- Implicit cast is illegal — no truncation or padding allowed.
- 2-state ↔ 4-state conversion of the same bit length is a legitimate cast (allowed).
- Net-type ↔ variable-type connection of same bit length is a legitimate cast (allowed).
- Dissimilar net types that would generate a Verilog-2001 warning are errors with
.name.
📋 .* Implicit Connections
.* automatically connects all ports whose name and size match an external signal in the enclosing scope. Only exception ports need to be listed explicitly. Ideal for rapid testbench generation.
module alu_accum4(...); wire [7:0] alu_out; // .* connects: ain, bin, opcode, alu_out, clk, rst_n automatically // Explicit overrides are listed for exceptions: // .zero() → unconnected // .dataout(dataout[7:0]) → size mismatch: explicit // .datain(alu_out) → different name: explicit // .dout/.din → different names: explicit alu alu (.*, .zero()); accum accum (.*, .dataout(dataout[7:0]), .datain(alu_out)); xtend xtend (.*, .dout(dataout[15:8]), .din(alu_out[7])); endmodule
.* override or unconnect specific ports. Same restrictions as .name for type compatibility.
📋 Mixed Connection Styles
module alu_accum5(...); wire [7:0] alu_out; // mix of named and .name alu alu (.ain(ain), .bin(bin), .alu_out, .zero(), .opcode); // positional accum accum (dataout[7:0], alu_out, clk, rst_n); // mix of named and .* xtend xtend (.dout(dataout[15:8]), .*, .din(alu_out[7])); endmodule // All four styles can coexist in the same parent module (but not in one instance)
📋 Port Connection Rules — Variables
When a port is declared as a variable data type (not a net), SV implies a continuous assignment at the connection boundary.
| Port direction | Can connect to | Implied behaviour | Restrictions |
|---|---|---|---|
input variable |
Any expression of compatible type | Continuous assignment into the port | Assigning to the input variable inside the module is illegal |
output variable |
Variable or concatenation (compatible type); or a net | Continuous assignment from port to connected variable | No procedural or continuous assignment to the connected variable from outside |
inout variable |
Variable type is not permitted on either side of an inout port | ||
ref variable |
Equivalent variable type only | Hierarchical reference — no copy; changes visible immediately | Cannot be left unconnected; types must be equivalent |
ref port creates a hierarchical reference to the connected variable — it is not a copy. Any change through the port variable is immediately visible at the connection site. This is the module-port equivalent of a function’s ref argument.
📋 Port Connection Rules — Nets
When a port is declared as a net type (wire is the default), standard Verilog-2001 net-resolution rules apply with one SV addition: outputs can now connect to compatible variable types.
| Port direction | Can connect to | Unconnected value |
|---|---|---|
input net | Any expression of compatible data type | 'z |
output net | Net type (or concatenation of nets); or compatible variable type | — |
inout net | Net type (or concatenation of nets) only — not variable types | Can be left unconnected |
📋 Port Connection Rules — Interfaces
- An interface port instance must always be connected to an interface instance or a higher-level interface port. It cannot be left unconnected.
- A generic interface port (
interface portname) accepts an interface instance of any type. - A named interface port (
specific_ifc portname) must connect to an interface instance of exactly that type.
📋 Unpacked Array Ports and Arrays of Instances
- Unpacked array port: the connected array must have the same number of unpacked dimensions and each dimension must be the same size.
- Array of instances — scalar connection: if the port connection size and type match a single instance port, the same connection is made to every instance in the array.
- Array of instances — unpacked array connection: dimensions must match exactly; elements paired left-to-left, right-to-right.
- Array of instances — packed array connection: each instance gets a consecutive part-select; right-most dimension iterated first. Too many or too few bits is an error.
// Array of 4 instances, each with a 1-bit port 'p' — scalar connection wire scalar_sig; mymod arr[3:0] (.p(scalar_sig)); // scalar_sig connected to ALL 4 instances // Array of 4 instances — packed array sliced per instance wire [3:0] bus; mymod arr2[3:0] (.p(bus)); // arr2[3].p←bus[3], arr2[2].p←bus[2], etc.
📋 Eight Name Spaces
SV has 8 distinct name spaces. Two are global across all compilation units, two are global within a compilation unit, and four are local.
📋 Hierarchical Names
Hierarchical names (nested identifiers) are sequences of instance names separated by dots. An instance name can include an array element index.
// Absolute path using $root $root.mymodule.u1 // unambiguous: always refers to top-level path // Relative paths (u1 must be visible locally or upward in hierarchy) u1.struct1.field1 adder1[5].sum // array element instance // Hierarchical names can be: // — read in expressions // — written in assignments or task/function calls // — used as trigger targets in event expressions (@hier_name) // — used as task or function names (call into another scope)
A.B.C is ambiguous when both a local scope and the top level contain an instance named A — the local one wins. $root.A.B.C always refers to the top-level path, bypassing local precedence.
📋 Quick Reference
Four port connection styles compared
| Style | Syntax | Requirement | Verbosity |
|---|---|---|---|
| Positional | inst(a, b, c) | Order must match port list; empty comma skips | Least documentation |
| Named | inst(.p(a), .q(b)) | Order independent; any size/name combination | Explicit, verbose |
| .name | inst(.p, .q) | Name and size must match; no implicit wire | Concise, still lists all ports |
| .* | inst(.*, .p(x)) | Name and size must match for auto-connected ports | Least boilerplate; exceptions explicit |
Port variable connection rules at a glance
inputvariable: any compatible expression → continuous assignment into port; no assignment inside module.outputvariable: connect to variable (continuous assignment out) or net (multiple drivers OK).inout: variable type not permitted on either side.ref: hierarchical reference, no copy; equivalent type required; cannot be unconnected.inoutnet: can only connect to net types — not variable types.
Eight name spaces (2 global, 2 unit-global, 4 local)
- Global (all units): Definitions (modules/primitives/programs/interfaces), Package.
- Unit-global: Compilation-unit scope, Text macro.
- Local: Module, Block, Port, Attribute.
