I am trying to use SystemVerilog to simulate an IP block written in VHDL. As part of the SystemVerilog testbench, I have written a bus functional model to mimic a streaming AXI-4 bus using an interface with modports. I want to reuse the interface in several places within the testbench so the modports define an initiator, target, tb_initiator and tb_target, where the latter two modports import tasks to read and write packets for use as stimulus/validation. The idea is to use one bus functional model for connections between components as well as the external interfaces, where only the external interfaces would be driven by tasks.
interface axi_if();
logic tlast, tvalid, tready;
modport initiator();
modport target();
modport tb_initiator(..., import write_packet);
modport tb_target(..., import read_packet);
task write_packet();
endtask
task read_packet();
endtask
endinterface
module top()
axi_if tb_stim(clk);
axi_if intercomponent(clk);
axi_if tb_verif(clk);
axi_component component1 (.clk(clk), .target(tb_stim), .initiator(intercomponent));
axi_component compotent2 (.clk(clk), .target(intercomponent), .initiator(tb_verif));
endmodule
module axi_component(axi_if.target, axi_if.initiator)
endmodule
I seem to encounter one warning and one error in Questa 10.4 with this approach. Both are related in nature to multiple drivers, where the gist is that the tasks are writing to signals that are also driven externally. Although it is a warning for most cases, it becomes an error when I have to continuously assign a signal externally to the interface. “Variable written by continuous and procedural assignments” Obviously, the intention is not to use a task to drive the signal when the continuous assignment is used as this tends to be between components.
For example, the VHDL component has each signal presented individually on its interface necessitating the need to wire up the interface manually. I have also tried writing a wrapper around the VHDL component so that modports can be used at the top level but to no avail.
A simple solution is to create three separate interfaces; a target and initiator BFM for simulation and a separate BFM for inter-component connections. However, it seems that this should be the point of a modport. Is it possible to write a single interface to cope with the various scenarios? If so, how can the scope of the task be limited to the modports of interest only?