Group: comp.lang.verilog


Subject: Doubt about SystemVerilog tasks in interfaces
From: Andreas Ehliar
Date: 10/11/2007 10:07:22 AM
I am playing around a little bit with SystemVerilog but I have encountered a problem which I don't really know how to solve. My scenario is as follows: I have created an interface for a certain bus. Two modports, one for a bus master and one for a bus slave. There is also tasks in the interface that allows the testbench to perform read and write transactions on the bus. My problem is that the assignments I have to make procedurally inside the task in order to read/write conflicts with continuous assignments made in another part of the design (even though I never even use that task anywhere). The source code included below will give the following error message in ModelSim 6.3c: # ** Fatal: (vsim-3838) argh.sv(12): Variable '/argh2/thebus/adr' written by continuous and procedural assignments. See argh.sv(49). Is this really the correct behavior? If so it seems like tasks in interfaces aren't as useful as I initially thought. Is there any sort of workaround for my problem? I have looked at various tutorials on the web but never seen this problem mentioned or any ways around it. /Andreas --------------------------------------------- argh.sv follows below: --------------------------------------------- `timescale 1ns / 10ps module testmod3( output reg [31:0] address_o); assign address_o = 32'hdeadbeef; endmodule // testmod3 module testmod2(bus.master thebus); testmod3 foo(.address_o(thebus.adr)); endmodule // testmod2 module argh2; reg clk; bus thebus(clk); testmod2 uut(.*); endmodule // argh2 interface bus(input clk); typedef reg [31:0] adr_t; typedef reg [31:0] dat_t; adr_t adr; // address bus dat_t dat_o; // write data bus dat_t dat_i; // read data bus reg stb; // strobe reg we; // indicates write transfer reg ack; // normal termination modport master( output adr, dat_o, stb, we, input clk, dat_i, ack); modport slave( input clk, adr, dat_o, stb, we, output dat_i, ack); task read(input adr_t radr, output dat_t rdat); begin adr = radr; stb = 1'b1; we = 1'b0; while (!ack) begin @(posedge clk); end stb = 1'b0; we = 1'b0; rdat = dat_i; end endtask endinterface // bus

Subject: Doubt about SystemVerilog tasks in interfaces
From: Andreas Ehliar
Date: 10/12/2007 6:30:28 AM
On 2007-10-11, Jonathan Bromley <jonathan.bromley@MYCOMPANY.com> wrote: > Andreas, does the following work for you? > > Make the modport drive a stub variable, which is > then copied on to the real "adr" variable: > > interface foo; > // adr is the real thing, master_adr is a stub > reg [...] adr, master_adr; > modport slave (input adr); > modport master (output master_adr); // driven by master > // Procedural copy, will do nothing if master not connected > always @master_adr adr = master_adr; > // Drive from task, will do nothing if task not called > task set_adr(reg [...] A); adr = a; endtask > endinterface > > I agree that it's a tiresome mess. Hi, it seems to work for me. But as you said, it is tiresome. I have been thinking about this and have another possible solution. I'm removing the task from the interface altogether and putting the task into a regular module instead: module bus_tasks(bus.master thebus); task read(input [31:0] radr, output reg [31:0] rdat); begin @(posedge thebus.clk); thebus.adr <= radr; thebus.stb <= 1'b1; thebus.we <= 1'b0; while (!thebus.ack) begin @(posedge thebus.clk); end thebus.stb <= 1'b0; thebus.we <= 1'b0; rdat = thebus.dat_i; end endtask endmodule Inside my testbench I can then do something like this: bus thebus(clk); bus_tasks bt(thebus); reg [31:0] dat; initial begin // reset stuff ... ... bt.read(32'hfffffffc0,dat); $display("Read %08x",dat); end What do you think about this solution? Does it have any hidden pitfalls that I'm not aware of? /Andreas