为端口元素的可选数组参数化 SystemVerilog 接口

问题描述

我想填写正确的信号声明和 modport 声明,以便我的界面和所需的代码示例用例在 Vivado 中编译。我在 SystemVerilog 中使用 .sv 文件扩展名。我想要“if 语句”不同的信号声明的原因是,我的接口的实例化和使用更加优雅。我不希望用户必须键入 many [0] 来指定第一维的单个元素数组中的单个元素,其中 1 维和第二维宽度为 1。

请耐心等待,我不得不在我的工作中删除代码应用程序的所有元素。我已将其裁剪为一个非常简单的示例。

如果第一个维度或数组为 1 且数组的第二个维度为 1,我不希望有人需要选择第 0 个和第 0 个元素。

例如,我希望用户能够执行以下操作,但它无法编译。这是我的基本问题。我如何实现能够像以下代码段一样优雅的代码?:

MyInterface # ( .DATA_WIDTH( 8 ),.ADDR_WIDTH( 8 ),.A1D( 1 ),.A2D( 1 ) ) my_signal () ;

assign my_signal.bus.data = 8'h20 ;

错误是:

[Synth 8-6038] cannot resolve hierarchical name for the item 'data' [".../File.sv":21]

相反,我发现用户必须对总共 1 个元素的特定信号执行此操作(以下内容没有错误):

MyInterface # ( .DATA_WIDTH( 8 ),.A2D( 1 ) ) my_signal () ;

assign my_signal.bus[0][0].data = 8'h20 ;

我觉得这样的事情应该可以通过以下代码实现:

interface MyInterface #(int DATA_W,ADDR_W,A1D,A2D) () ;

  typedef struct packed
    { logic                valid
    ; logic [ADDR_W-1:0]   addr
    ; logic [DATA_W-1:0]   data
    ; } SimpleStruct;

  if ( A1D == 1 ) begin
    SimpleStruct bus;
    logic ready;
  end
  else begin
    if ( A2D == 1 ) begin
      SimpleStruct [A1D-1:0] bus;
      logic        [A1D-1:0] ready;
    end
    else begin
      SimpleStruct [A1D-1:0][A2D-1:0] bus;
      logic        [A1D-1:0][A2D-1:0] ready;
    end
  end
  
  modport SNK (input  bus,output ready);
  modport SRC (output bus,input  ready);

endinterface

这没有编译,因为 bus 和 ready 是“未声明”的......所以我改成了一个不太优雅的(我尝试在 generate 中进行猜测,但这没有帮助):

interface MyInterface #(int DATA_W,A2D) () ;

  typedef struct packed
    { logic                valid
    ; logic [ADDR_W-1:0]   addr
    ; logic [DATA_W-1:0]   data
    ; } SimpleStruct;

  if ( A1D == 1 ) begin
    SimpleStruct bus;
    logic ready;

    modport SNK (input  bus,output ready);
    modport SRC (output bus,input  ready);
  end
  else begin
    if ( A2D == 1 ) begin
      SimpleStruct [A1D-1:0] bus;
      logic        [A1D-1:0] ready;
  
      modport SNK (input  bus,output ready);
      modport SRC (output bus,input  ready);
    end
    else begin
      SimpleStruct [A1D-1:0][A2D-1:0] bus;
      logic        [A1D-1:0][A2D-1:0] ready;
  
      modport SNK (input  bus,input  ready);
    end
  end

endinterface

同样的愿望适用于用户想要使用长度 > 1 的单维数组的情况。例如: 恕我直言:

MyInterface # ( .DATA_WIDTH( 8 ),.A1D( 3 ),.A2D( 1 ) ) my_signal () ;

assign my_signal.bus.data[0] = 8'h20 ;
assign my_signal.bus.data[1] = 8'h21 ;
assign my_signal.bus.data[2] = 8'h22 ;

我认为上面的代码比下面的代码更好看。我尝试或选择使用接口的重点是代码的可重用性和优雅性。我不希望用户不断与“我想要一个元素,但会得到部分模棱两可的错误,很难找出解决方案”:
恕我直言 不可取:

MyInterface # ( .DATA_WIDTH( 8 ),.A2D( 1 ) ) my_signal () ;

assign my_signal.bus.data[0][0] = 8'h20 ;
assign my_signal.bus.data[1][0] = 8'h21 ;
assign my_signal.bus.data[2][0] = 8'h22 ;

我的愿望是让用户编写他们需要的代码来完成他们想要的元素的复杂性。单个元素的用途最多,元素的一维数组有一些用途,元素的二维数组的用途很少。由于我希望定义一个接口,因此我必须允许所有用途。我不想仅仅因为我希望界面支持 2D 而需要优雅的代码,而用户只需要一个元素来实现他们的特定实例化和代码

解决方法

我想执行您所描述的操作的最佳方法是使用类型参数并在接口之外定义类型。这是一个例子。

df.D.iloc[-1:-3:-1] # to get last two value but reversed