How can I resolve virtual interface wire problem?
SystemVerilog requires that only 'wire' can connect with inout.
If I define interface signal with wire property. and I want to drive it in my class task by virtual interface. But This is not supported by simulator.
Please see code below:
interface bidir(input clk); wire dp, dm; endinterface:bidir class usb ; virtual bidir v_if; function new(virtual bidir v_if); this.v_if = v_if; endfunction:new task run(); v_if.dp = 0; v_if.dm = 0; forever begin @(posedge v_if.clk) begin v_if.dp = ~v_if.dp; v_if.dm = v_if.dm; end @(posedge v_if.clk) begin v_if.dp = 'z; v_if.dm = 'z; end end @(posedge v_if.clk) begin v_if.dp = $random; v_if.dm = $random; end endtask:run endclass module submod(/*AUTOARG*/ // Inouts dp, dm ); inout dp, dm; wire dp_i = dp; wire dm_i = dm; bit oe; bit dp_o, dm_o; assign dp = oe ? dp_o : 'z; assign dm = oe ? dm_o : 'z; endmodule module top; bit clk; bidir bidir(clk); submod submod(/*AUTOINST*/ // Inouts .dp (bidir.dp), .dm (bidir.dm)); always #5 clk = ~clk; initial begin usb usb = new(bidir); fork usb.run; join_none $display("================\n**************\n===============\n"); #100 $finish; end endmodule:top
It can't run in Cadence simultor. but it is supported by Synopsys Simultor.
How can I changed the code to run in all simulators.
Your simulator has a bug in it if it allows you to procedurally assign to a wire. How long is the value that is procedurally assigned supposed to stay on the wire? And don't you want to see X's if the submodule output enable is active at the same time as your TB tries to drive a value?
You have two LRM compliant choices when dealing with testbench connections to inouts
- use a continuous assignment in your interface just like in your submodule assign dp =dp_o; If you declare dp_o as a logic, there's no need for a separate oe signal. You just set do_o to 'z when you don't want it to drive.
- If your signals are synchronous, you can use a clocking block. That might not work for you in this case, but it's something to remember.
I have found a method to solve the problem.
Modify Interface as below, add 2 extra signals.
interface bidir(input clk); logic dp; logic dm; wire wire_dp; wire wire_dm; assign wire_dp = dp; assign wire_dm = dm; endinterface:bidir
In class task method(dynamic object), use dp|dm to procedure assignment and use wire_dp|wire_dm to sample.
But the code seems wierd.
In VCS, just define dp/dm as wire type, and procedure assignment and sample both can use the same net dp/dm. The interface is much more like the real environment(only 2 signals, not 4 signals).