How do I connect inout ports?

I have an inout port named sent_line, and this is how it is declared:

Inside the module: inout sent_line;
Inside the interface:


interface my_sigs_if();
  logic sent_line;

  modport drv (inout sent_line);
endinterface

So now I’m having an error saying that “port connections to inout ports must be nets”.

So I changed the data type of sent_line in the interface from logic to “wire logic” but the new error says that my driver is illegally driving the sent_line.

sigs_if.drv.sent_line = 1;

So what should I do to fix this?

In reply to Reuben:

interface my_sigs_if();
  wire sent_line;
  logic sent_line_drv;
  assign sent_line = sent_line_drv;

  modport drv (inout sent_line);
endinterface

In the driver drive using sigs_if.sent_line_drv, In the top level connect sigs_if.sent_line to the DUT inout port.

See my DVCon paper about connecting bidirectional signals to the testebench:

https://verificationacademy.com/resources/technical-papers/the-missing-link-the-testbench-to-dut-connection

In reply to dave_59:

Dave, Can i assign a value to a net(which is inside) from a class based testbench?


interface a2b;
wire w1; // w1 is a bi-directional signal
endinterface

class a2b_dr;
  virtual a2b inf;
  ....
  
  task dr;
     inf.w1 <= 1'b1;
  endtask
endclass

Currently this is allowed in vcs. I would like to understand the reason for not using this kind of code? (When class is not driving the signal the default value of net is “z”. and from the class we can drive “z” on this w1 signal)

Every time there is a change on one of the drivers, the function is called to produce a resolved value. The function is created at elaboration (before simulation starts) and is based on the kind of net type, wand, wor, tri1, etc.

The above statement means that tool will not be able to consider the dynamic assignment(which is created during simulation) for value resolution?

In reply to Naven8:

The problem is that the statement

inf.w1 <= 1'b1;

is a non-blocking procedural assignment to a wire, it is not a continuous driver to the wire. A procedural assignment has no duration to it; you are depositing the value of the expression on the RHS of the ‘<=’ to the variable on the LHS. The variable stores the value until there is another procedural assignment that replaces the old value with a new one. The execution of the procedural assignment is part of a sequential thread of procedural statements that usually starts with an initial or always block construct.

A continuous assignment

assign w1 = w2;

is structural, not procedural. You are driving the value of the expression on the RHS to the net on the LHS, for all time. A change at anytime on the RHS expression cause a new value to be driven on the LHS.

It seems that VCS allows procedural assignments to wires, and that seems to work as long as there are no other continuous assignments to the wire. In that case, you treat the wire the same as you would a variable. The problem comes in when you try to mix the two kinds of assignments. Let’s say the DUT is continuously driving a 1’b1, and the testbench makes a procedural assignment to 1’b0. Does the procedural assignment replace the value being driven with 1’b0, like any other procedural assignment. Or does it try to do wire resolution and make the wire go to 1’bx. I suppose the LRM could define an answer for this, but Verilog was designed as a description language to show more intent. As an analogy, you could define an array with fixed size 10 elements and allow the 11th element to be assigned by growing the array by one element when that happens, but then what was the point of declaring a 10 element array in the first place?

In reply to ranga_smile:

I have done the same way as u specified , but in waveform my net connection to dut is not having value driven by logic data type.

In reply to dave_59:

Hi Dave, could you look into my question here please: Simulate OpenDrain line | Verification Academy

I read your paper but I haven’t found much usefull in my situation. I think it is due to the fact I am trying to simulate Xilinx’ IOB, so that means I don’t have the I/O/T signals, I therefore only have the inout port from the IOB… so as far as I know I can’t do anything like:

assign sig = T ? 'z : O;

In reply to arquer:

Connecting up a SystemVerilog interface to bidi signals is a bit tricky. But in fact there’s a way to accomplish it that works in both simulation and synthesis (it works under Xilinx for Vivado at least). It requires a few extra steps but works reliably.

We create a “bidi_feedthru” module:

module bidi_feedthru
#(
  parameter WIDTH = 64
) 
(
  inout wire [ WIDTH - 1 : 0 ] p0,
  inout wire [ WIDTH - 1 : 0 ] p1
);
  tran t1[ WIDTH - 1 : 0 ]( p1, p0 );
endmodule

Now, at the top-level of our design, we have a standard “wire” bidi bus:


inout wire [  7 : 0 ] DRAM_DQS,
inout wire [ 63 : 0 ] DRAM_DQ

We wish to hookup the bidi wires to an interface “ddr_if”. Do so like thus:


bidi_feedthru #( .WIDTH(  8 ) ) dqs_alias( DRAM_DQS, ddr_if.dqs );
bidi_feedthru #( .WIDTH( 64 ) ) dq_alias( DRAM_DQ, ddr_if.dq );

As the instance name implies, what we’re looking for here is a (non-existing SystemVerilog feature) of a “net alias” that works with interface members. This trick fills the language hole with a few extra steps.

The above will connect up your bidi signals to the interface - and it works both in simulation and synthesis (at least for Vivado)

Regards,

Mark

In reply to dave_59:

Hi Dave,
The link " http://events.dvcon.org/2012/proceedings/papers/01P_3.pdf" seems broken.
Could you please provide working link for this paper

In reply to suman_vip:

Sorry, DVCon lost it’s proceedings website and is still recovering. Here is an alternate source: The Missing Link: The Testbench to DUT Connection | Technical Paper | Verification Academy

In reply to dave_59:

Thanks Dave …