
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