How to assign inout port into the interface of Systemverilog?

I can send the data through the inout port but can’t read it. the signal line goes to ‘x’ when it is time to respond.


module my_dut (
      CMD,
      ...
);

inout CMD;
  reg m_CMD;
  assign CMD = m_CMD;
...
endmodule

Here’s interface.


interface my_if(
    inout wire w_my_command,
    ...
);

logic my_command = 'bz;
      assign w_my_command = my_command;
...
endinterface

Here’s the my_top module.


module my_top;

wire w_top_my_command;

my_if   u_my_if(
               .w_my_command(w_top_my_command),
               ...
               );

my_dut  u_my_dut(
               .CMD(w_top_my_command),
               ...
                ); 
initial begin
  uvm_config_db #(virtual my_if)::set(null, "*", "my_vif", u_my_if);
end

endmodule

In the driver,


class my_master_driver extends uvm_driver;

   virtual my_if my_msater_vif;
   ...
   uvm_config_db#(virtual my_if)::get(this, "", "my_vif", my_master_vif)
   ...

   //Send INOUT port
   my_master_vif.my_command <= 1'b1;


endclass

After send the control signal through the inout port (my_master_vif.my_command <= 1’b1;), I expected that the respond signal from inout port(my_master_vif.my_command). But my_master_vif.my_command has only ‘x’.

How to assign inout port into the interface of Systemverilog?

In reply to UVM_LOVE:

When using inout ports, you need to ensure that there is only one active driver at a time. Your my_dut is continuously driving CMD, which causes contention when your agent is attempting to drive it at the same time.

In my_dut, you should have an output enable to know when to drive:


module my_dut (
      CMD,
      ...
);
 
  inout CMD;
  reg m_CMD;
  reg m_CMD_OE;
  assign CMD = m_CMD_OE ? m_CMD : 1'bz;
...
endmodule

In reply to cgales:

Thanks reply cgales.
But even if I modified with

module my_dut (
      CMD,
      ...
);
 
  inout CMD;
  reg m_CMD;
  reg m_CMD_OE;
  assign CMD = m_CMD_OE ? m_CMD : 1'bz;
...
endmodule

Still does not work.

Originally, the code has been controlled as the below

module myTb;
import uvm_pkg::*;

reg clk, cmd;
wire m_cmd = cmd;
pullup i1(m_cmd);

//cmd control
cmd = 1;

my_dut u_dut(m_cmd, clk, ....)
...
endmodule

I changed it to the interface as the below.

interface my_if(
    inout wire w_my_command,
    ...
);
 
logic my_command = 'bz;
      assign w_my_command = my_command;
...
endinterface

Command send no problem working good but when it responds from DUT, command port goes to ‘x’.
Any clue please.

In reply to UVM_LOVE:

When you want to read the output from your DUT, you need to set the interface inout to 'z so that you aren’t conflicting with the DUT. Do you do that? Your code only shows setting it to 1’b1.

It would be beneficial to provide a complete example which shows your issue so that someone can provide a solution.

In reply to cgales:

Here’s a method developed with a certain FPGA vendor that is also synthesizable (I use it connect top level inout ports to an interface containing such ports)

Use the primitive tran:



module top
(
  inout wire [ 31 : 0 ] foo_bidi_port
);

my_if some_if();  // some_if contains a wire foo_wire which is intended to be inout

tran foo_connect[ 31 : 0 ]( foo_bidi_port, some_if.foo_wire );
endmodule

You can use the same to connect up within your testbench.