I’m trying to implement a BFM using an abstract class and a concrete interface. It was assumed that the interface would contain one set of signals for the write (for the driver) and read (for the monitor) methods that the class implements.
An abstract class and a concrete interface look like this:
package pkgAbsBFM;
virtual class AbsPktBFM;
pure virtual task write(bit [7:0] pkt []);
pure virtual task read(output bit [7:0] pkt []);
endclass
endpackage: pkgAbsBFM
interface someintfPktBFM #(parameter DATA_WIDTH = 8)(input bit rst, input bit clk);
import pkgAbsBFM::*;
bit sop, eop, val;
bit [DATA_WIDTH-1:0][7:0] data;
int pad;
bit grant, ready;
clocking cb_driver@(posedge clk);
output sop, eop, val, data, pad, ready;
input grant;
endclocking: cb_driver
clocking cb_monitor@(posedge clk);
input sop, eop, val, data, pad, ready;
output grant;
endclocking: cb_monitor
modport mp_driver (clocking cb_driver);
modport mp_monitor (clocking cb_monitor);
class PktBFM_someintf #(parameter DATA_WIDTH = DATA_WIDTH) extends AbsPktBFM;
task write(bit [7:0] pkt []);
cb_driver.data <= ...
...
endtask: write
task read(output bit [7:0] pkt []);
... <= cb_monitor.data;
...
end
endtask: read
endclass: PktBFM_someintf
PktBFM_someintf BFM = new;
endinterface: someintfPktBFM
The top level looks like this:
module top;
import pkgAbsBFM::*;
someintfPktBFM someintfPktDriver (rst, clk_125MHz);
someintfPktBFM someintfPktMonitor (rst, clk_125MHz);
AbsPktBFM BFM_driver, BFM_monitor;
initial begin
BFM_driver = someintfPktDriver.BFM;
BFM_driver.write(tx_pkt);
end
initial begin
BFM_monitor = someintfPktMonitor.BFM;
BFM_monitor.read(rx_pkt);
end
dut dut (
.iclk(clk_125MHz),
.irst(rst),
.isop(someintfPktDriver.sop),
.ieop(someintfPktDriver.eop),
.ival(someintfPktDriver.val),
.idata(someintfPktDriver.data),
.ipad(someintfPktDriver.pad),
.grant(someintfPktDriver.grant),
.ready(someintfPktDriver.ready),
.osop(someintfPktMonitor.sop),
.oeop(someintfPktMonitor.eop),
.oval(someintfPktMonitor.val),
.odata(someintfPktMonitor.data),
.opad(someintfPktMonitor.pad)
);
endmodule
As a result, I got an error (despite the fact that I used one interface instance for the driver and the other for the monitor):
# ** Error (suppressible): (vsim-3839) Variable '/testbench/someintfPktMonitor/data', driven via a port connection, is multiply driven.
Do I understand correctly that I need to implement a separate abstract class and a separate concrete interface for both the driver and the monitor?
I wanted to avoid duplication of descriptions and implement methods within one unit. But I don’t quite understand how. I did not use the modport and clocking block, because, as I understood, they will not solve this problem. Or am I wrong?
Thanks.