【问题标题】:How to uniquely parameterize an array of interfaces?如何唯一地参数化一组接口?
【发布时间】:2021-03-19 22:34:19
【问题描述】:

我正在尝试为要传递给模块的数组中的接口提供唯一 ID:

     1  // Test case for SO question on SystemVerilog array parameterization.
     2  //
     3  // Original author: David Banas <david@luminouscomputing.com>
     4  // Original date:   March 19, 2021
     5
     6  interface intf
     7    #( parameter ID = 0
     8     ) ();
     9
    10    logic data;
    11  endinterface
    12
    13  module foo
    14    #( parameter N_IFS = 1
    15     )( intf ifs[N_IFS]
    16      );
    17
    18    initial begin
    19      $display($sformatf("ID of last interface: %0d.", ifs[N_IFS-1].ID));
    20    end
    21  endmodule : foo
    22
    23  module top;
    24    localparam N_IFS = 2;
    25
    26    intf ifs[N_IFS]();
    27
    28    genvar i;
    29    generate
    30      for(i=0; i<N_IFS; i++)
    31        defparam ifs[i].ID = i;
    32    endgenerate
    33
    34    foo #(.N_IFS(N_IFS)) u_foo(.ifs(ifs));
    35  endmodule : top

我的 SystemVerilog 编译器出现了这个错误:

Error-[SVDOGH] Invalid defparam on a parameter
/home/david/tmp/array_params.sv, 31
  Defparam on a parameter outside the generated hierarchy.
  Reference to 'ID' in defparam in instance 'top.ifs[0]' at
  /home/david/tmp/array_params.sv, 31 is invalid.
  Target parameter 'ID' must resolve in the generated hierarchy
  'top.genblk1[0]' starting at /home/david/tmp/array_params.sv, 30.

我怎样才能做到这一点?

【问题讨论】:

    标签: parameters system-verilog


    【解决方案1】:

    您尝试使用的是一个 arrayed instance 接口,它本身只是 generate 块的另一个版本。如果数组实例中的所有元素都具有相同的参数签名,则您可以将其用作端口连接中的数组。但是,在这种情况下,您不能修改它们的参数。阵列实例需要使用可能难以组织和管理的某些类型的端口。我还没有在实践中看到过这种结构的使用。

    另外,'defparam' 是一个过时的结构,不鼓励使用它。系统 verilog 标准可能会在未来贬低它。

    在您的情况下,您可以使用更简单的构造来实例化接口并连接每个实例。

    interface intf
       #( parameter ID = 0
        ) ();
    
       logic data;
     endinterface
    
     module foo
       #( parameter N_IFS = 1
        )( intf ifs);
    
       initial begin
         $display($sformatf("ID of last interface: %0d.", ifs.ID));
       end
     endmodule : foo
    
     module top;
       localparam N_IFS = 2;
       for(genvar i=0; i<N_IFS; i++) begin: loop
           intf #(.ID(i)) ifs();  // << instantiate with id
           foo u_foo(.ifs(ifs));  // << instantiat foo and connect to the interface instance
        end
     endmodule : top
    

    在上面的示例中,接口被实例化在一个类似数组的“循环”中,具有不同的 ID。 'foo' 模块在同一个生成块中实例化,并连接到接口的正确实例。

    【讨论】:

    • 这并不完全正确。你可以有一个接口数组,只是每个实例去一个数组必须有相同的类型。这就是数组的定义。如果您尝试为它们提供唯一的参数化,它们将不再是同一类型。
    • @dave_59 像往常一样,你是对的 :-),我更新了我的答案。
    • 谢谢,@Serge!我认为当模块“foo”和接口“intf”之间存在 1:1 对应关系时,您提出的解决方案是有效的。不幸的是,在我的实际情况中,我需要等效的“foo”来接受一个 intfs 数组,并且该数组的大小是可参数化的,因此我的代码可以在几个不同的*项目中使用。