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 interface placeholder 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.

Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5