Global training solutions for engineers creating the world's electronics
Menu

SystemVerilog Interfaces Tutorial

Interfaces are a major new construct in SystemVerilog, created specifically to encapsulate the communication between blocks, allowing a smooth refinement from abstract system-level through successive steps down to lower RTL and structural levels of the design. Interfaces also facilitate design re-use. Interfaces are hierarchical structures that can contain other interfaces.

There are several advantages when using an Interface:
  • They encapsulate connectivity: An interface can be passed as a single item through a port, thus replacing a group of names by a single one. This reduces the amount of code needed to model port connections and improves its maintainability as well as readability.
  • They encapsulate functionality, isolated from the modules that are connected via the interface. So, the level of abstraction and the granularity of the communication protocol can be refined totally independent of the modules.
  • They can contain parameters, constants, variables, functions and tasks, processes and continuous assignments, useful for both system-level modelling and testbench applications.
  • They can help build applications such as functional coverage recording and reporting, protocol checking and assertions.
  • They can be used for port-less access: An interface can be instantiated directly as a static data object within a module. So, the methods used to access internal state information about the interface may be called from different points in the design to share information.
  • Flexibility: An interface may be parameterised in the same way as a module. Also, a module header can be created with an unspecified interface instantiation, called a Generic Interface. This interface can be specified later on, when the module is instantiated.
At its simplest, an interface is a named bundle of wires, similar to a struct, except that an interface is allowed as a module port, while a struct is not.
The following example shows the definition and use of a very simple interface:
// Interface definition
interface Bus;
  logic [7:0] Addr, Data;
  logic RWn;
endinterface

// Using the interface
module TestRAM;
  Bus TheBus();                   // Instance the interface
  logic[7:0] mem[0:7];
  RAM TheRAM (.MemBus(TheBus));   // Connect it

  initial
  begin
    TheBus.RWn = 0;               // Drive and monitor the bus
    TheBus.Addr = 0;
    for (int I=0; I<7; I++)
      TheBus.Addr = TheBus.Addr + 1;
    TheBus.RWn = 1;
    TheBus.Data  = mem[0];
  end
endmodule

module RAM (Bus MemBus);
  logic [7:0] mem[0:255];

  always @*
    if (MemBus.RWn)
      MemBus.Data = mem[MemBus.Addr];
    else
      mem[MemBus.Addr] = MemBus.Data;
endmodule

Interface Ports

An interface can also have input, output or inout ports. Only the variables or nets declared in the port list of an interface can be connected externally by name or position when the interface is instantiated, and therefore can be shared with other interfaces.  The ports are declared using the ANSI-style.
Here is an example showing an interface with a clock port:
interface ClockedBus (input Clk);
  logic[7:0] Addr, Data;
  logic RWn;
endinterface

module RAM (ClockedBus Bus);
  always @(posedge Bus.Clk)
    if (Bus.RWn)
      Bus.Data = mem[Bus.Addr];
    else
      mem[Bus.Addr] = Bus.Data;
endmodule

// Using the interface
module Top;
  reg Clock;

  // Instance the interface with an input, using named connection
  ClockedBus TheBus (.Clk(Clock));
  RAM TheRAM (.Bus(TheBus));
  ...
endmodule

Parameterised Interface

This is a simple example showing a parameterised interface:
interface Channel #(parameter N = 0)
    (input bit Clock, bit Ack, bit Sig);
  bit Buff[N-1:0];
  initial
    for (int i = 0; i < N; i++)
      Buff[i] = 0;
  always @ (posedge Clock)       
   if(Ack = 1)
     Sig = Buff[N-1];
   else
     Sig = 0;
endinterface

// Using the interface
module Top;
  bit Clock, Ack, Sig;
  // Instance the interface. The parameter N is set to 7using named
  // connection while the ports are connected using implicit connection
  Channel #(.N(7)) TheCh (.*);
  TX TheTx (.Ch(TheCh));
  ...
endmodule

Modports in Interfaces

A new construct related to Interface is also added: Modport. This provides direction information for module interface ports and controls the use of tasks and functions within certain modules. The directions of ports are those seen from the module.
This example includes modports, which are used to specify the direction of the signals in the interface. The directions are the ones seen from the module to which the modport is connected, in our case the RAM:
interface MSBus (input Clk);
  logic [7:0] Addr, Data;
  logic RWn;
  modport Slave (input Addr, inout Data);
endinterface

module TestRAM;
  logic Clk;
  MSBus TheBus(.Clk(Clk));
  RAM TheRAM (.MemBus(TheBus.Slave));
  ...
endmodule

module RAM (MSBus.Slave MemBus);
  // MemBus.Addr is an input of RAM
endmodule

Tasks in Interfaces

Tasks and functions can be defined in interfaces, to allow a more abstract level of modelling.
The next example shows two tasks in an interface being used to model bus functionality. The tasks are called inside the testRAM module:
interface MSBus (input Clk);
  logic [7:0] Addr, Data;
  logic RWn;

  task MasterWrite (input logic [7:0] waddr,
                    input logic [7:0] wdata);
    Addr = waddr;
    Data = wdata;
    RWn = 0;
    #10ns RWn = 1;
    Data = 'z;
  endtask

  task MasterRead (input  logic [7:0] raddr,
                   output logic [7:0] rdata);
    Addr = raddr;
    RWn = 1;
    #10ns rdata = Data;
  endtask
endinterface

module TestRAM;
  logic Clk;
  logic [7:0] data;
  MSBus TheBus(.Clk(Clk));
  RAM TheRAM (.MemBus(TheBus));
  initial
  begin
    // Write to the RAM
    for (int i = 0; i<256; i++)
      TheBus.MasterWrite(i[7:0],i[7:0]);

    // Read from the RAM
    for (int i = 0; i<256; i++)
    begin
      TheBus.MasterRead(i[7:0],data);
      ReadCheck : assert (data === i[7:0])
        else $error("memory read error");
    end
  end
endmodule 

Prev Next