Если testbench и test являются верхними модулями, как передать экземпляр интерфейса внутри testbench в тест

Я предпочитаю писать тестовую среду и тесты в виде модулей верхнего уровня, чтобы я мог скомпилировать их все и разработать/оптимизировать тестовую среду и тесты, которые мне нужно запустить. Однако я не уверен, как я могу передать экземпляр интерфейса в тестовом стенде в тест. В приведенном ниже примере dut_tb — это тестовая среда верхнего уровня, а dut_tb_intf — интерфейс, созданный в тестовой среде. Тест dut_tb_test использует функции в интерфейсе, на которые я могу ссылаться, используя полный путь, но мне было интересно, могу ли я передать экземпляр интерфейса в dut_tb тесту или лучший способ сделать это.

См. пример ниже.

module dut(input data, input clk, input rst_n, output logic inv_data);
  logic inv_data_d;
  assign inv_data_d = ~data;

  always_ff @(posedge clk or negedge rst_n)
      if (~rst_n)
        inv_data <= '0;
      else
        inv_data <= inv_data_d;
endmodule

package dut_tb_pkg;
logic clk;
logic rst_n;
logic data;
logic inv_data;
endpackage

module dut_tb();

  import dut_tb_pkg::*;

  dut_tb_intf dut_tb_intf();

  //logic data;
  //logic inv_data;

  assign data = dut_tb_intf.data_i;
  assign dut_tb_intf.data_inv = inv_data;
  assign clk = dut_tb_intf.aclk;

  initial
    begin
       rst_n = '0;
       @(posedge clk);
       rst_n = '1;
    end

  dut dut (.clk (clk), .rst_n(rst_n), .data (data), .inv_data(inv_data));

endmodule

//module dut_tb_test( dut_tb.dut_tb_intf intf_inst); // DOES NOT WORK**
module dut_tb_test();

  import dut_tb_pkg::*;

  logic in, out;

  initial 
    begin
    @(posedge clk);
     #30;
    @(posedge clk);
     in = 1'b0;
     dut_tb.dut_tb_intf.inv_data (in, out);

     //intf_inst.inv_data (in, out); // DOES NOT WORK**

   end  
  initial 
    begin
    @(posedge clk);
    @(posedge clk);
     $display ("INFO_0: in is %b and out is %b\n", in, out);
     #300;
     $display ("INFO_1: in is %b and out is %b\n", in, out);
     #100;
     $finish;
    end

endmodule

interface dut_tb_intf; 

logic aclk; 
logic data_i;
logic data_inv;

   initial
     begin
        aclk = '0;
        forever #5 aclk = ~aclk;
     end

task inv_data(input i, output logic d);

 data_i = i;;
 @(posedge aclk);
 @(posedge aclk);
 d = data_inv;

endtask

modport utils (import inv_data);

endinterface

person user9906612    schedule 23.01.2021    source источник


Ответы (1)


В вашем подходе вы не можете не передавать интерфейс между двумя модулями. Интерфейсы передаются модулям через порты инстанцирования. В классическом подходе Verilog вам нужен еще один модуль top для создания экземпляра всего этого:

module tb(MyInterface i);
...
endmodule 

module test(MyInteface i);
...
endmodule

interface MyInterface;
...
endinterface

module top();
   MyInterface myIntf;
   tb tb(myIntf);
   test test(myIntf);
endmodule

Можно пойти немного некрасиво и создать экземпляр вашего интерфейса внутри tb и передать его тесту следующим образом.

module top();
    tb tb();
    test test (tb.myIntf);
endmodule

Другой подход заключается в создании экземпляра вашего теста в тестовом стенде. Это избавит вас от всех вышеперечисленных проблем, и вы можете, естественно, передать ему интерфейс:

module test...

module tb();
   MyInterface myIf;
   test test(myIf);
   ...
endmodule

Или, что еще лучше, в системном verilog вы можете создать свой тест как класс и передавать виртуальные интерфейсы.

person Serge    schedule 23.01.2021
comment
Спасибо, я пытался избежать еще одной инкапсуляции верхнего уровня. Я не думал о разработке теста как класса - изучу его. Итак, я полагаю, вы имеете в виду, что каждый экземпляр теста может получить виртуальный интерфейс, и любая конкретная настройка теста будет происходить вне класса. Если есть пример, на который вы можете указать мне, было бы здорово. Спасибо - person user9906612; 23.01.2021