SystemVerilog Interfaces

Prev: Instantiating Interfaces | Next: parameterized Interfaces

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

Share/Save/Bookmark



Verification Management
Join Verification Management Group


Shop Amazon - Contract Cell Phones & Service Plans

Book of the Month