Передача по ссылке в системный модуль Verilog или интерфейс - PullRequest
0 голосов
/ 12 апреля 2019

Я хотел бы создать повторно используемый интерфейс или модуль, в котором иерархия элемента памяти вне его может быть передана ему по ссылке.Я знаю, что передача по ссылке не может быть выполнена для модуля или интерфейса согласно 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

------------------- Функции C -----------------

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

1 Ответ

0 голосов
/ 12 апреля 2019

Но вы можете передать любую переменную по ссылке на порт.

interface mem_intf (input clk, input [4:0] add, ref logic [31:0] mem [0:31]);

См. Раздел 23.3.3 Правила подключения портов в IEEE 1800-2017 LRM


Обновление

Другой вариант - использовать конструкцию 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);
...