The communication between
blocks of a digital system is a critical area that can affect everything from
ease of RTL coding, to hardware-software partitioning to performance analysis
to bus implementation choices and protocol checking. The interface construct in
SystemVerilog was created specifically created to encapsulate the communication between
blocks, allowing a smooth migration from abstract system-level design through successive
refinement down to lower-level register-transfer and structural views of the
design. By encapsulating the communication between blocks, the interface
construct also facilitates design re-use. The inclusion of interface capabilities
is one of the major advantages of SystemVerilog.
At its lowest level, an
interface is a named bundle of nets or variables. The interface is instantiated
in a design and can be passed accessed through a port as a single item, and the
component nets or variables referenced where needed. A significant proportion
of a Verilog design often consists of port lists and
port connection lists, which are just repetitions of names. The ability to
replace a group of names by a single name can significantly reduce the size of
a description and improve its maintainability.
modport_tf_port ::=
task named_task_proto { , named_task_proto }
| function named_function_proto { , named_function_proto }
| task_or_function_identifier tf_identifier { , task_or_function_identifier tf_identifier }
interface_instantiation ::= // from Annex A.4.1.2
interface_identifier [ parameter_value_assignment
] module_instance hierarchical_instance { , module_instance hierarchical_instance } ;
The interface
construct provides a new hierarchical structure. It can contain smaller
interfaces and can be passed accessed through ports.
The aim of
interfaces is to encapsulate communication. At the lower level, this means
bundling variables and wires in interfaces, and bundling ports may impose access restrictions with port directions in modports.
The modules can be made generic so that the interfaces can be changed. The
following examples show these features. At a higher level of abstraction, communication
can be done by tasks and functions. Interfaces can include task and function
definitions, or just task and function prototypes (see section 19.6.1 An
example of using tasks in an interface) with the definition in one module (server/slave) and the call in
another (client/master).
A simple interface
declaration is as follows (see Syntax 19-1 for the complete syntax):
interface
identifier;
...
interface_items
...
endinterface
[ : identifier ]
An interface can be
instantiated hierarchically like a module, with or without ports. For example:
myinterface
#(100) scalar1, vector[9:0];
In
this example, 11 instances of the interface of type "myinterface"
have been instantiated and the first parameter within each interface is changed
to 100. One myinterface instance is instantiated with
the name "scalar1", and an array of 10 myinterface
interfaces are instantiated with instance names vector[9]
to vector[0].
The simplest form of a
SystemVerilog interface is a bundled collection of variables or nets. When an
interface is used referenced as a port, the variables and nets in it are assumed to be have
ref and inout
ports access, respectively.
The following interface example shows the basic syntax for defining,
instantiating and connecting an interface. Usage of the SystemVerilog interface
capability can significantly reduce the amount of code required to model port
connections.
interface
simple_bus; // Define the
interface
logic
req, gnt;
logic
[7:0] addr, data;
logic
[1:0] mode;
logic
start, rdy;
endinterface: simple_bus
module
memMod(simple_bus
a, // Use Access
the simple_bus interface
input
bit clk);
logic
avail;
// When memMod is instantiated in module top, a.req is the req
// signal in the sb_intf instance of the ’simple_bus’
interface
always
@(posedge
clk) a.gnt
<= a.req & avail;
endmodule
A module header can be
created with an unspecified interface instantiation
reference as a place-holder for an interface to
be selected when the module itself is instantiated. The unspecified interface
is referred to as a “generic” interface port
reference.
This generic interface port reference can
only be declared by using the list of port declaration style port declaration
style of reference. It shall be illegal to
declare such a generic interface port reference using the old Verilog-1995 list of port
style.
The following interface
example shows how to specify a generic interface port
reference in a module definition.
// memMod and cpuMod can use any interface
module
memMod (interface
a, input bit clk);
...
endmodule
module
cpuMod(interface
b, input bit clk);
...
endmodule
interface
simple_bus; // Define the
interface
logic
req, gnt;
logic
[7:0] addr, data;
logic
[1:0] mode;
logic
start, rdy;
endinterface: simple_bus
module
top;
logic
clk = 0;
simple_bus sb_intf();
// Instantiate the interface
// Connect
Reference the sb_intf
instance of the simple_bus
// interface to
from the generic interfaces of the
// memMod and cpuMod modules
memMod mem (.a(sb_intf), .clk(clk));
cpuMod cpu (.b(sb_intf), .clk(clk));
endmodule
An implicit port cannot be
used to connect to reference a generic interface. A named port must be
used to connect to reference a generic interface, as shown below.
module
top;
logic
clk = 0;
simple_bus sb_intf1(clk); // Instantiate the
interface
simple_bus sb_intf2(clk); // Instantiate the
interface
memMod
mem1(.a(sb_intf1)); // Connect Reference simple bus 1 to memory 1
cpuMod
cpu1(.b(sb_intf1));
memMod
mem2(.a(sb_intf2)); // Connect Reference simple bus 2 to memory 2
cpuMod
cpu2(.b(sb_intf2));
endmodule
To bundle module ports restrict
interface access within a module, there are modport
lists with directions declared within
the interface. The keyword modport
indicates that the directions are
declared as if inside the module.
interface
i2;
wire
a, b, c, d;
modport
master (input a, b, output
c, d);
modport
slave (output a, b, input
c, d);
endinterface
The In this example, the modport
list name (master or slave) can be
specified in the module header, where the modport name
acts as a direction and the interface name as a type interface name selects an interface and the modport
name
selects the appropriate directional information for the interface signals
accessed in the module header.
module
m (i2.master i);
...
endmodule
module
s (i2.slave i);
...
endmodule
module
top;
i2 i();
m u1(.i(i));
s u2(.i(i));
endmodule
The syntax of interface_name.modport_name reference_name gives a local name for a
hierarchical reference. Note that this can be generalized to any interface with
a given modport name by writing interface.modport_name reference_name.
The modport
list name (master or slave) can also
be specified in the port connection with the module instance, where the modport
name is hierarchical from the
interface instance.
module
m (i2 i);
...
endmodule
module
s (i2 i);
...
endmodule
module
top;
i2 i();
m u1(.i(i.master));
s u2(.i(i.slave));
endmodule
The syntax of interface_name.modport_name instance_name is really a hierarchical type followed by an
instance. Note that this can be generalized to any interface with a given modport name by
writing interface.modport_name instance_name.
In a hierarchically nested interface, the directions
in a modport
declaration can themselves be modport
plus name.
interface i1;
interface i3;
wire a, b, c, d;
modport master (input a, b, output c, d);
modport slave (output a, b, input c, d);
endinterface
i3 ch1(),
ch2();
modport master2 (ch1.master, ch2.master);
endinterface
All of the names used in a modport declaration shall be declared by the same
interface as is the modport itself. In particular,
the names used shall not be those declared by another enclosing interface, and
a modport declaration shall not implicitly declare
new ports. No hierarchical references shall be permitted
within a modport.
This interface example
shows how to use modports to control signal directions restrict
interface signal access and control their direction. It uses the modport name in the module instantiation.
EDITOR’S NOTE: I made several
minor editorial changes in the following paragraphs, which are indicated by
strike-through text with the replacement text immediately following the
strike-through text.