Driving a single signal with multiple interfaces

Hello all,

In my UVM testbench, I would like to have multiple interfaces containing different tasks that may drive the same signal at different times. I am looking for a way to arbitrate between the interfaces, so that the signal going to the DUT always reflects the most recently updated value.

To make things clearer, here is an example:

interface int_1();

// blah blah

task drive_x(logic val);
  x = val;
endtask 

endinterface

interface int_2();

// blah blah

task drive_x(logic val);
  x = val;
endtask 

endinterface


module test(input logic clk, int_1 i1, int_2 i2);
  i1.drive_x(1);
  @(posedge clk);
  i2.drive_x(0);
  @(posdedge clk);
  i1.drive_x(1);
  @(posedge clk);
endmodule


module dut(input logic x);
  // blah blah
endmodule

My goal is that the x input to the DUT goes 1 to 0 to 1 again, i.e. int_1 drives it to a 1, then int_2 drives it to a 0, then int_1 drives it to a 1 again.

Is there any accepted way to do this? I have tried several different solutions, but all have had pretty significant drawbacks.

In reply to jms8:

Firstly, your example does not look like a UVM testbench, because og your module test.
Using a real UVM environment you can easily drive the same port of the DUT by different interfaces.
In the toplevel module of your UVM environment you have instances of all your interfaces connected to different agents. In a concurrent assignment you can drive a port of the DUT by signals of different interfaces.

In reply to chr_sue:

Sorry about that. I was trying to simplify my sample code as much as possible, and I guess I simplified too much. Hopefully it didn’t cause too much confusion. Really what would happen is I would have two agents, with each one driving one of the two different interfaces. So I would send a sequence to agent 1 that would drive interface1 which would drive dut port x, then I would send a different sequence to agent 2 which would drive interface 2 which would drive dut port x to a different value.

I don’t really understand your statement, “Using a real UVM environment you can easily drive the same port of the DUT by different interfaces.” I’ve been working on this for a while now, and it doesn’t seem to be that simple. Would you mind giving an example of how both interfaces would be connected to the DUT? I want to have a signal x in both interface1 and interface2, with the most recently changed driving the port x on the dut. Ideally, I would like to be able to drive x in interface1 and interface2 as if the other interface didn’t exist.

In reply to jms8:

How it works is a question of your protocol. It has to guarantee that never more than 1 driver is active.
A good example is the WideIO2 standard.

In reply to chr_sue:

Now I understand. Having two (or more) drivers active at once is actually what I am trying to do. I am looking for the best way to arbitrate between the various active drivers driving the same signal. Is there any kind of UVM way of doing this? Any tips would be appreciated.

In reply to jms8:
In order to have multiple drivers driving the same signal, you need to establish a protocol that prevents them from driving simultaneously. This needs to be done before anyone can show you how to write the code that implements it.

In reply to jms8:

This is not a question of UVM. It is a common modelling question, independent of the implementation language. You can doi this in VHDL, Verilog, SystemVerilog, SystemC etc.
The behavior of your DUT should give you the protocol, because each functional interface has such a protocol. This might be quite simple or more complicated.

Both of those are good points. Regardless, I think it’s clear that there is not an already established way of dealing with this particular problem, which is what I was hoping for, so I don’t think I will pursue it further here. I will continue doing experiments on my own.
Thank you both very much for your help!