Reputation: 77
I would like to create a reusable interface or module where the hierarchy of a memory element outside it can be passed to it by reference. I know passing by reference cannot be done to a module or an interface as per LRM but is there a way to achieve it without using defines. Please see the testcase below where the line that is commented out shows good results will give the right value in memory but I will need to pass the hierachy into an interface that is specific to this example and cant make the interface more reusable. I would like to make the badd results call work but not sure how to do this:
----------------------------Verilog----------------------------------
module t1_tb();
reg clk;
reg write;
reg [4:0] address;
reg [31:0] data_in;
wire [31:0] data_out;
mem_model mem_model (clk, write, address, data_in, data_out);
mem_intf mem_intf(clk, address, mem_model.memory);
initial
begin
clk = 0;
write = 0;
address = 0;
for (int i = 0; i < 32; i++)
mem_model.memory[i] = 32'haaaaaaaa;
forever clk = #5 ~clk;
end
initial
begin
#200;
$display ("memory locations are %h and %h \n", mem_model.memory[0], mem_model.memory[1]);
$finish;
end
endmodule
module mem_model(input clk, input write, input [4:0] address, input [31:0] data_in, output [31:0] data_out);
reg [31:0] memory [0:31];
assign data_out = memory[address];
always @(posedge clk)
if (write)
memory[address] <= data_in;
endmodule
interface mem_intf (input clk, input [4:0] add, input logic [31:0] mem [0:31]);
import "DPI-C" context send_int = function void send_int_c ();
export "DPI-C" clks_delay = task clks_delay;
task clks_delay(input int unsigned usecs);
for (int i = 0; i < (int'(usecs/3.33) * 1000); ++i)
@(posedge clk);
endtask
task automatic mem_acc( input [4:0] add, ref reg [31:0] memory1 [0:31] );
#10;
memory1[add] = '1;
#10;
$display ("memory locations are %h and %h and add is %h\n", memory1[0], memory1[1], add);
endtask
task monitor_interrupts (input [6:0] interrupts);
send_int_c();
endtask
initial
begin
#100;
mem_acc(0, mem); //bad results
//mem_acc(0, t1_tb.mem_model.memory); // good results
end
endinterface
-------------------C Functions-----------------
void send_int(void)
{
printf("From C Sending Interrupt..\n");
}
extern void clks_delay(int seconds);
void clks_delay(int seconds)
{
printk("From C clocks_delay: %uld\n", seconds);
}
Upvotes: 0
Views: 3289
Reputation: 42673
But you can pass any variable by reference to a port.
interface mem_intf (input clk, input [4:0] add, ref logic [31:0] mem [0:31]);
See section 23.3.3 Port connection rules in the IEEE 1800-2017 LRM
Another option is using the bind construct to instantiate the interface, and upwards reference the memory. The name of the memory would have to be the same for all instances.
interface mem_intf (input clk, input [4:0] add);
...
initial
begin
#100;
mem_acc(0, memory); //upward reference
end
endinterface
module t1_tb();
mem_model mem_model1 (clk, write, address, data_in, data_out);
bind mem_model: mem_model1 mem_intf mem_intf(clk, address);
Upvotes: 1