SystemVerilog Interface :

Interface with Modports
Interface

SystemVerilog Interface is a convenient method of communication between 2 design blocks. Interface encapsulates information about signals such ports, clocks, defines, parameters and directionality into a single entity. This entity, then, can be accessed at very low level for e.g Register access or to a very high level for E.g Virtual Interface.

Additionally, we can also define Tasks, Functions inside an Interface along with Assertion and SVA Checks. This encapsulation provides portability to Design that can use same interface to communicate differently depending on the type of use. This is achieved by defining Modports and Clocking blocks inside Interface.

Similarly, same design module may use different Interfaces communicate differently if the two interface have same Task or Functions defined.

Here’s an simple example of an Interface :

interface example_inter;
  logic [7:0] data_load;
  logic [7:0] data_read;
  logic rd_en;
  logic wr_en;
endinterface

module primary(example_inter example_if, input clock, reset);
 logic [7:0] data_storage;

 always_ff @(posedge clock) begin
   if(reset)
     data_storage <= '0;
   else
     data_storage <= example_if.data_load;
 end 

 assign example_if.data_read = example_if.rd_en ? data_storage : '0;  
endmodule


module top;
  logic clock;
  logic reset;
  
   example_inter example_if ();
   primary       primary_if 
 (.example_if(example_if), .clock(clock), .reset(reset));  
   
endmodule

Here’s an example of Interface using Modport :

interface example_inter;
  logic [7:0] data_load;
  logic [7:0] data_read;
  logic rd_en;
  logic wr_en;

 modport generator_m (output rd_en, output wr_en, output data_load);
 modport receiver_m 
 (input rd_en, input wr_en, input data_load, output data_read);  

endinterface

module generator (example_inter.generator_m gen_i);
// generator Module code
...
..
endmodule

module receiver (example_inter.receiver_m rec_i);
// receiver Module Code
...
..
endmodule

module top;
 example_inter inter_inst();
 
 generator gen_inst (.gen_i(inter_inst));
 receiver  rec_inst (.rec_i(inter_inst));
endmodule 

Task inside Interface :

Task defined inside interface can be used by different Modules by defining the Task inside Interface. This method allows same Task to be used by different Modules by providing unique values. For E.g. Below, one Task ‘Timer‘ can be used by different Modules for counting purposes by providing unique values of threshold on interface.

interface example_inter;
 logic [2:0] count_value;
 logic [2:0] threshold;

task timer (input logic [2:0] count_value);
//Counter Code to count till count_value
... 
..
endtask

endinterface

module example_delay (example_inter ifc);
logic [2:0] final_count;
assign final_count = ifc.threshold;

// count till Threshold
ifc.timer(final_count); 

endmodule

Published by

tachyonyear

Silicon Design Enthusiast.