Tasks and Functions in Interface
You can define a task or a function inside an interface pretty much
the same way that you define a task or a function inside a module.
Moreover, a task or a function defined within an interface can be
called from anywhere. This implies three different possibilities of
how a task or function can be defined and called.
(a) Defining a task or function within an interface and
calling it from a module: For example, a task associated with
a connection (e.g. to send or receive data) can be defined within
the interface that represents that connection. A module, without
any implicit knowledge of the connection or the task, can simply
call the task to perform the operation on the connection.
This is shown in the example below. Here, the interface intf_AB
contains the task send_data(). This task is called by moduleA
that sends data through the connection.
interface intf_AB (input bit clk);
logic ack;
logic ready;
logic send;
logic [31:0] data;
task send_data (input logic send_signal,
input logic [31:0] data_bus);
... // actual task definition
endtask
... // rest of the interface definition here
endinterface
module moduleA (interface xyz);
...
xyz.send_data(send);
...
endmodule
The rest of the definitions for moduleB and top remain
unchanged.
(b) Defining a task or function for a modport and calling it
from a module: In case a module uses a special modport of an
interface, tasks can be imported into that modport and then the
module can call the task in the same way as above. This is shown
in the following example where the module moduleA uses
the modport source of the interface intf_AB. The
modport source imports the task send_data() for this
purpose. Once the task is imported, the rest of the code remains
unchanged from (a) above.
interface intf_AB (input bit clk);
logic ack;
logic ready;
logic send;
logic [31:0] data;
modport source ( input ack, ready,
output send, data
import task send_data());
...
task send_data (input logic send_signal,
input logic [31:0] data_bus);
... // actual task definition
endtask
...
endinterface
(c) Defining the task and calling it from a module:
In this case, the task is declared inside an interface as an
extern or inside a modport as an export. The actual
task definition is located inside a module using hierarchical
path. Then the task can also be called from this module (or another)
using the same hierarchical path. The following example shows
this. Here, the task send_data() is declared as an export
inside the modport source (had this been declared inside the
interface intf_AB but outside the modports, it would have been
declared as an extern). The task send_data() itself
has been defined inside the module moduleA by the full
hierarchical path.
interface intf_AB (input bit clk);
logic ack;
logic ready;
logic send;
logic [31:0] data;
modport source ( input ack, ready,
output send, data
export task send_data());
...
endinterface
module moduleA(interface xyz);
...
task xyz.send_data (input logic send_signal,
input logic [31:0] data_bus);
... // actual task definition
endtask
...
// somewhere within the module this task is being called
xyz.send_data(send, mydata);
...
endmodule
module top;
...
moduleA AA (intf_AB.source);
...
endmodule
One more way to customize an interface is through the use
of parameters. We will see how this is done in the next page.
Prev: Instantiating Interfaces
| Next: parameterized Interfaces