2

I'm trying to figure out how to connect multiple UVCs (UVM Verification Components) to the same DUT where the UVC's do not share an interface but do connect to the same signals on the DUT.

The DUT that can operate on different protocols on common signals and can switch between protocols after a receiving a specific sequence. Each protocol was developed independently into is its own UVC; lets call them low-speed and high-speed. Assume the interfaces and DUT are the follows:

interface lowspeed_if( input bit clock, reset );
  logic       a;
  logic       b;
  logic       c;
  logic [7:0] io_drv;  wire  [7:0] io = io_drv;
                       wire        ready;
  initial {a,b,c,io_drv} = 'z;
endinterface : lowspeed_if

interface highspeed_if( input bit clock, clk2, reset );
  logic       a;
  logic       b_drv;   wire        b = b_drv;
  logic [7:0] io_drv;  wire  [7:0] io = io_drv;
                       wire        ready;
  initial {a,b_drv,io_drv} = 'z;
endinterface : highspeed_if

module device_to_test(input a, inout b, input c, inout [7:0] io, output ready);
  /* RTL */
endmodule : device

Because the UVC's were not designed considering the other protocols, the low-speed driver/monitor can only connect with lowspeed_if and the high-speed driver/monitor can only connect with highspeed_if. This means there are two interfaces that need to connect to the same a, b, io, and ready signals.

Is there a way connect these UVCs to the same DUT without changing the original UVCs?

Ross Rogers
  • 23,523
  • 27
  • 108
  • 164
Greg
  • 18,111
  • 5
  • 46
  • 68

2 Answers2

1

At the top level define the connecting signals as wires. Use assign statements for signals that only drive the DUT. Use tran for bi-directional. For signals only monitoring the DUT, use assign statements

bit clock,clk2,reset;
wire a,b,c;
wire ready;
wire [7:0] io;

lowspeed_if  ls_if(.*);
highspeed_if hs_if(.*);
device dut( .* );

assign {a,b,c} = {ls_if.a, ls_if.b, ls_if.c};
tran link_io_ls[7:0](io, ls_if.io);
assign ls_if.ready = ready;

assign a = hs_if.a;
tran link_b_hs(b,hs_if.b);
tran link_io_hs[7:0](io, hs_if.io);
assign hs_if.ready = ready;

ready could have been connected with a tran since it is defined as a wire in the interfaces. Using the assign statement makes the direction explicit and is flexible if a future interface defines the outputs as something other then wire.


I discovered assign {a,a} = {ls_if.a,hs_if.a}; also works for assigning drivers.

Greg
  • 18,111
  • 5
  • 46
  • 68
0

It's a good thing your interfaces have wires to work with - that makes it easy to tie them together and have multiple drivers. You can create a tie module that collapses three wires together into one.

module tie(inout .a(w), .b(w), .c(w));
   wire w;
endmodule

Then your testbench would look like:

module top;

  wire a,b;
  wire [7:0] io;
  wire clk, clk2, reset, ready

  lowspeed_if  ls_if(clk, reset);
  highspeed_if hs_if(clk,clk2,reset);

  tie tie_a(ls_if.a, hs_if.a, a);
  tie tie_b(ls_if.b, hs_if.b, b);
  tie tie_rdy(ls_if.ready, hs_if.ready, ready);
  tie tie_a[7:0](ls_if.io, hs_if.io, io);

  device_to_test DUT(a, b, ls_if.c, io, ready);

endmodule
dave_59
  • 39,096
  • 3
  • 24
  • 63
  • Some of the signals are `logic` in both interfaces and therefore generates errors when connecting to `module tie`. Only a `wire` can connect to a `inout` port. – Greg Nov 07 '13 at 17:28
  • Then you will have to use continuous assignments instead of the tie. For example, the tie_rdy can be replaced with `assign ls_if.ready = ready; assign hs_if.ready = ready;` This works as long as there is only one driver, your DUT in this case. – dave_59 Nov 07 '13 at 18:20
  • Fumbling around with it I came to the same idea of using the `assign` on driving signals. I also decided to use the Verilog primitive `tran` to link bi directional signals. The SystemVerilog keyword `alias` doesn't have a lot of tool support yet, and those that do support it give an error stating the interface signal is a hierarchical reference. – Greg Nov 07 '13 at 19:00