通过引用传递到系统Verilog模块或接口

通过引用传递到系统Verilog模块或接口,verilog,system,pass-by-reference,Verilog,System,Pass By Reference,我想创建一个可重用的接口或模块,在这个接口或模块中,外部内存元素的层次结构可以通过引用传递给它。我知道根据LRM不能通过引用传递到模块或接口,但有没有一种方法可以在不使用定义的情况下实现它。请参阅下面的测试用例,其中注释掉的行显示良好的结果将在内存中给出正确的值,但我需要将层次结构传递到一个特定于此示例的接口中,并且不能使该接口更加可重用。我想让badd结果调用工作,但不确定如何做到这一点: ----------------------------Verilog-----------------

我想创建一个可重用的接口或模块,在这个接口或模块中,外部内存元素的层次结构可以通过引用传递给它。我知道根据LRM不能通过引用传递到模块或接口,但有没有一种方法可以在不使用定义的情况下实现它。请参阅下面的测试用例,其中注释掉的行显示良好的结果将在内存中给出正确的值,但我需要将层次结构传递到一个特定于此示例的接口中,并且不能使该接口更加可重用。我想让badd结果调用工作,但不确定如何做到这一点:

----------------------------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

但是您可以通过引用将任何变量传递到端口

interface mem_intf (input clk, input [4:0] add, ref logic [31:0] mem [0:31]);
参见IEEE 1800-2017 LRM中的第23.3.3节端口连接规则


更新 另一个选项是使用bind构造实例化接口,并向上引用内存。所有实例的内存名称必须相同

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);

我试过了,但得到了以下错误:接口mem_intf(输入clk,输入[4:0]add,ref-logic[31:0]mem[0:31]);|xmvlog:*E,CBYREF(test1.sv,46 | 50):目前仅在任务和函数中支持“ref”形式参数方向。不确定这是cadence xcelium模拟器的限制还是LRM限制。当它说“当前[不]支持”时,这是模拟器的问题。谢谢,我在LRM中看到了这一点。有人知道你是否可以将ref传递到其他模拟器的模块和接口中吗?与Questa和EDAPlaygroundLRM上的其他两个模拟器一起工作实际上是允许的。但这是不可合成的。
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);