A module that accepts an interface as a port can reference that interface in one of two ways: by naming the exact interface type it expects, or by using a generic placeholder that accepts any interface passed to it. Which one you reach for depends on whether the module needs to work with one specific interface definition, or stay flexible as that definition evolves.
6 min read | Intermediate Level
What You'll Learn
- The difference between a named interface bundle and a generic interface bundle in a module's port list
- Why a generic interface bundle is useful when interface definitions change over time
- The ANSI-style port declaration restriction that applies to generic interface ports
- How partial implicit port connections (
.*) work alongside a generic interface port
Named vs Generic Interface Bundles
There are two ways a design can accept an interface:
- By using an existing interface name, to specifically require only that one interface
- By using a generic interface handle, to which any interface can be passed
The generic method works best when interface definitions get updated to newer versions under a different name, while older designs still need to keep working against whatever interface they were built for.
Example Using a Named Bundle
Here, the design references the actual interface name to access its signals. Both myDesign and yourDesign declare a port in their port list called if0, of type myInterface:
module myDesign ( myInterface if0,
input logic clk);
always @ (posedge clk)
if (a.ack)
if0.gnt <= 1;
...
endmodule
module yourDesign ( myInterface if0,
input logic clk);
...
endmodule
module tb;
logic clk = 0;
myInterface _if;
myDesign md0 (_if, clk);
yourDesign yd0 (_if, clk);
endmodule
The condition inside myDesign checks a.ack, but the interface port declared in this module's port list is named if0, not a — a is never declared anywhere in this module, so this line as written wouldn't compile. It should read if0.ack, matching the port name used on the very next line (if0.gnt). Whatever name you give the interface port is the name you must use everywhere inside the module body to access its signals.
Example Using a Generic Bundle
Here, the design uses the interface keyword itself as a placeholder for the actual interface type. Both myDesign and yourDesign use that placeholder handle to reference signals, and the actual interface is passed in during module instantiation. A generic interface reference like this can only be declared using ANSI-style port declaration syntax — it's illegal otherwise:
module myDesign ( interface a,
input logic clk);
always @ (posedge clk)
if (if0.ack)
if0.gnt <= 1;
...
endmodule
module yourDesign ( interface b,
input logic clk);
...
endmodule
module tb;
logic clk = 0;
myInterface _if;
myDesign md0 ( .*, .a(_if)); // use partial implicit port connections
yourDesign yd0 ( .*, .b(_if));
endmodule
This time the port is declared as a (the generic interface placeholder), but the body references if0.ack and if0.gnt — there's no port named if0 here at all. It should read a.ack and a.gnt, matching the port name a that the instantiation below (.a(_if)) actually connects to.
In the testbench, md0 uses .* to implicitly connect any port whose name matches a same-named local signal — here, clk — while explicitly connecting the generic interface port a to the local interface instance _if with .a(_if), since _if and a don't share the same name for .* to match automatically.
Quick Check
Q: Why can't .* alone connect the generic interface port in the example above, without also writing .a(_if)?
Show Answer
Even setting naming aside, .* can never connect a generic interface port at all — the language flatly requires an explicit named connection for any generic interface port. So the .a(_if) connection would still be required here even if the port happened to be named _if to match the local instance exactly.
Where Are Generic Interface Bundles Used?
Generic bundles are useful when a reusable checker or monitor module needs to work against more than one version of an interface — for example, supporting both an older protocol interface and its newer revision without maintaining two nearly-identical copies of the same module, one per interface name.
Common Beginner Mistakes
Mistake #1: Referencing a different name than the one declared in the port list
As both examples above illustrate, the interface port's declared name is the only name you can use to access its signals inside that module. Why? It's an easy copy-paste mistake when adapting a named-bundle example into a generic one (or vice versa) — always double-check that every signal reference inside the module body matches the exact port name declared at the top.
Mistake #2: Declaring a generic interface port with non-ANSI syntax
A generic interface port can only be declared using ANSI-style port declarations (directly in the module's port list, as shown above). Why? Older, non-ANSI Verilog-style port declarations (separate input/output statements in the module body) simply aren't legal for a generic interface port — this is a hard restriction in the language, not a style preference.
Mistake #3: Assuming .* connects every port, including a generic interface port
.* is convenient, but it's not a catch-all. Why? For an ordinary port, a name that doesn't exactly match a visible local signal still needs its own explicit connection. A generic interface port is stricter still: the language disallows connecting one implicitly at all, so it always needs an explicit named connection — even on the rare occasion its name happens to match a local signal.
Practice Exercise
Challenge: Write a Correct Generic Bundle Module
Write a module called checker that accepts a generic interface port named chk_if and a clk input, and drives chk_if.gnt high whenever chk_if.ack is high on a clock edge — without the naming mismatch shown in the examples above.
Hint
Whatever you name the generic interface port in the port list is exactly the name you must use every time you access its signals inside the module body.
Solution
module checker ( interface chk_if,
input logic clk);
always @ (posedge clk)
if (chk_if.ack)
chk_if.gnt <= 1;
endmodule
module tb;
logic clk = 0;
myInterface _if;
checker chk0 ( .*, .chk_if(_if) );
endmodule
Every reference inside checker uses chk_if, matching the port name declared in the port list exactly — there's no stray reference to a name that was never declared, unlike both examples earlier in this article.
Summary
In this tutorial, you learned:
- A module can accept an interface either by naming the exact interface type, or through a generic
interfaceplaceholder that accepts any interface passed to it - A generic interface bundle is useful when an interface definition changes over time, letting one module support multiple interface versions
- A generic interface port can only be declared using ANSI-style port syntax
- Whatever name is declared for an interface port in the port list must be used consistently everywhere that port's signals are accessed inside the module
.*only auto-connects ports whose names exactly match a visible local signal; a generic interface port needs an explicit named connection unconditionally, even on the rare occasion its name happens to match
Continuing the Interfaces & Modports Chapter
Continue with SystemVerilog Clocking Blocks.