01-Interfaces Markup v4 200312111
01-Interfaces Markup v4 200312111
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.
Additional power of the interface comes from its ability to encapsulate functionality as well as
connectivity, making an interface, at its highest level, more like a class template. An interface can have
parameters, constants, variables, functions and tasks. The types of elements in an interface can be declared,
or the types can be passed in as parameters. The member variables and functions are referenced relative to
the instance name of the interface as instance.member. Thus, modules that are connected via an interface
can simply call the task/ function members of that interface to drive the communication. With the
functionality thus encapsulated in the interface, and isolated from the module, the abstraction level and/or
granularity of the communication protocol can be easily changed by replacing the interface with a different
interface containing the same members but implemented at a different level of abstraction. The modules
connected via the interface don’t need to change at all.
To provide direction information for module ports and to control the use of tasks and functions within
particular modules, the modport construct is provided. As the name indicates, the directions are those seen
from the module.
In addition to task/function methods, an interface can also contain processes (i.e. initial or always blocks)
and continuous assignments, which are useful for system-level modeling and testbench applications. This
allows the interface to include, for example, its own protocol checker that automatically verifies that all
modules connected via the interface conform to the specified protocol. Other applications, such as
functional coverage recording and reporting, protocol checking and assertions can also be built into the
interface.
The methods can be abstract, i.e. defined in one module and called in another, using the export and import
constructs. This could be coded using hierarchical path names, but this would impede re-use because the
names would be design-specific. A better way is to declare the task and function names in the interface, and
to use local hierarchical names from the interface instance for both definition and call. Broadcast
communication is modeled by fork-join tasks, which can be defined in more than one module and executed
concurrently.
Page 202
19.2 Interface syntax
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 portsimposing 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
Page 203
task and function prototypes (see section 19.5.1) 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:
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].
Interfaces can be declared and instantiated in modules (either flat or hierarchical) but modules can neither
be declared nor instantiated in interfaces.
The simplest use of an interface is to bundle wires, as is illustrated in the examples below.
This example shows a simple bus implemented without interfaces. Note that the logic type can replace wire
and reg if no resolution of multiple drivers is needed.
module top;
logic req, gnt, start, rdy; // req is logic not bit here
logic clk = 0;
logic [1:0] mode;
logic [7:0] addr;
wire [7:0] data;
Page 204
memMod mem(req, clk, start, mode, addr, data, gnt, rdy);
cpuMod cpu(clk, gnt, rdy, data, req, start, addr, mode);
endmodule
Page 205
19.2.2 Interface example using a named bundle
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
portsaccess, 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.
module top;
logic clk = 0;
In the preceding example, if the same identifier, sb_intf, had been used to name the simple_bus interface in
the memMod and cpuMod module headers, then implicit port declarations also could have been used to
instantiate the memMod and cpuMod modules into the top module, as shown below.
module top;
logic clk = 0;
simple_bus sb_intf();
Page 206
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 portreference.
This generic interface referenceport can only be declared by using the list of port declaration style port
declaration styleof reference. It shall be illegal to declare such a generic interface referenceport 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.
module top;
logic clk = 0;
An implicit port cannot be used to connect toreference a generic interface. A named port must be used to
connect reference to a generic interface, as shown below.
module top;
logic clk = 0;
simple_bus sb_intf();
Page 207
19.3 Ports in interfaces
One limitation of simple interfaces is that the nets and variables declared within the interface are only used
to connect to a port with the same nets and variables. To share an external net or variable, one that makes a
connection from outside of the interface as well as forming a common connection to all module ports that
instantiate the interface, an interface port declaration is required. The difference between nets or variables
in the interface port list and other nets or variables within the interface is that only those in the port list can
be connected externally by name or position when the interface is instantiated.
The wires a, b and c can be individually connected to the interface and thus shared with other interfaces.
The following example shows how to specify an interface with inputs, allowing a wire to be shared
between two instances of the interface.
module top;
logic clk = 0;
simple_bus sb_intf1(clk); // Instantiate the interface
simple_bus sb_intf2(clk); // Instantiate the interface
Note: Because the instantiated interface names do not match the interface names used in the memMod and
cpuMod modules, implicit port connections cannot be used for this example.
Page 208
19.4 Modports
To bundle module portsrestrict signal 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 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 typewhere the interface name selects an interface and the
modport name selects the appropriate directional information for the interface signals accessed in the
module header.
module top;
i2 i();
m u1 (.i(i));
s u2 (.i(i));
endmodule
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 top;
i2 i();
m u1 (.i(i.master));
s u2 (.i(i.slave));
endmodule
In a hierarchically nested interface, the directions in a modport declaration can themselves be modport plus
name.
interface i1;
interface i3;
Page 209
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 The modports and 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 upward scoped
hierarchical references shall be permitted within a modport.
interface i;
wire x, y;
interface illegal_i;
wire a, b, c, d; // x, y not declared by this interface
modport master (input a, b, x, output c, d, y);
modport slave (input a, b, x, output c, d, y);
endinterface : illegal_i
interface illegal_i;
// a, b, c, d not declared by this interface
modport master (input a, b, output c, d);
modport slave (output a, b, output c, d);
endinterface : illegal_i
Note that if no modport is specified in the module header or in the port connection, then all the nets and
variables in the interface are accessible with direction inout or ref, as in the examples above.
This interface example shows how to use modports to control signal directions as in port declarations. It
uses the modport name in the module definition.
Page 210
always @(posedge a.clk) // the clk signal from the interface
a.gnt <= a.req & avail; // the gnt and req signal in the interface endmodule
module top;
logic clk = 0;
This interface example shows how to use modports to control signal directionsrestrict signal interface
access. It uses the modport name in the module instantiation.
module top;
logic clk = 0; simple_bus sb_intf(clk); // Instantiate the interface
Page 211