Tristate handling in interface

Hi,

I was not able to find any conclusive answer if it can work this way, so I thought of asking this question here:

I have an interface declared in the top module of DUT (pins). One of the pins declared in that respective interface is inout. Since I do not want to handle the tristate deeper in the hierarchy I thought of this solution:



// interface declaration, 2 modports: one for pins (with inout), one for internal logic (exploded tristate)
interface my_ifc ();
 
    wire [15:0] d;
    logic       d_oe;
    logic       d_in;
    logic       d_out;
 
    modport pins (inout d);
    modport user (input d_in, output d_out, output d_oe);
 
    assign d_out = (d_oe)? d_out : 16'hzzzz;
    assign d_in  = d;
 
endinterface
 
// interface driver with modport "user" -> _in, _out, _oe
module ifc_drv (
    my_ifc.user ifc
);
 
    assign ifc.d    = 16'hcafe;
    assign ifc.d_oe = 1'b1;
 
endmodule
 
// pad (synthesizable) with interface in module declaration
module dut_pad (
    my_ifc.pins ifc
);
 
    ifc_drv drv (
      .ifc(ifc)
    );
endmodule

EDA Playground Project

Since the code above returns modport mismatch error this is not the solution for my problem.
What is the right way to handle tristates in interfaces?

In reply to dipling:

Here while passing the interface to “dut_pad” module from the testbench, you are passing entire interface. While, the “dut_pad” only uses “my_ifc.pins” modport. When it passes the interface to “ifc_drv” module, the same “my_ifc.pins” is passed. While the “ifc_drv” expects “my_ifc.user” in the port list.

You need to make some changes in passing the interface to modules:

// In testbench
  dut_pad i_dut_pad (
    .ifc (ifc) // Pass full interface
  );

// In dut_pad
module dut_pad (
    my_ifc ifc
);
    ifc_drv drv (
      .ifc(ifc.user) // Pass user modport
    );

// In ifc_drv
module ifc_drv (
    my_ifc.user ifc
);

Somehow, you need to pass the correct port types for the “ifc_drv” module.

In reply to sharvil111:

Your proposed solution - declaring the _pad interface without in the dut_pad is something I came accross too. But it is not what I needed because this should be synthesizable code. In my understanding this code exposes all my_ifc signals which become DUT ports. The DUT should only have the signals declared in the .pins modport.