What is the need for a modport ?
Nets declared within a simple interface is
inout by default and hence any module connected to the same net, can either drive values or take values from it. In simple words, there are no restrictions on direction of value propagation. You could end up with an X on the net because both the testbench and the design are driving two different values to the same interface net. Special care should be taken by the testbench writer to ensure that such a situation does not happen.
This can be inherently avoided by the use of modports. Modport lists with directions are defined in an interface to impose certain restrictions on interface access within a module. The keyword
modport indicates that the directions are declared as if inside the module.
modport [identifier] ( input [port_list], output [port_list] );
Let's see an example where two designs have their directions defined using modports.
interface myInterface; logic ack; logic gnt; logic sel; logic irq0; // ack and sel are inputs to the dut0, while gnt and irq0 are outputs modport dut0 ( input ack, sel, output gnt, irq0 ); // ack and sel are outputs from dut1, while gnt and irq0 are inputs modport dut1 ( input gnt, irq0, output ack, sel ); endinterface
Style 1: Modport connection with DUT
In this style, the design will take the required correct modport definition from the interface object as mentioned in its port list. The testbench only needs to provide the whole interface object to the design.
module dut0 ( myinterface.dut0 _if); ... endmodule module dut1 ( myInterface.dut1 _if); ... endmodule module tb; myInterface _if; dut0 d0 ( .* ); dut1 d1 ( .* ); endmodule
Style 2: Modport connection with DUT
In this style, the design simply accepts whatever directional information is given to it. Hence testbench is responsible to provide the correct modport values to the design.
module dut0 ( myinterface _if); ... endmodule module dut1 ( myInterface _if); ... endmodule module tb; myInterface _if; dut0 d0 ( ._if (_if.dut0)); dut1 d1 ( ._if (_if.dut1)); endmodule