System verilog 多路复用通道中的SystemVerilog错误:实例数组中的非恒定索引

System verilog 多路复用通道中的SystemVerilog错误:实例数组中的非恒定索引,system-verilog,modelsim,quartus,System Verilog,Modelsim,Quartus,我正在设计一个模块,它接受多个通道并输出一个通道。 每个通道由一些宽度的有效信号和数据组成。 如果通道具有有效数据,模块应输出该通道。如果多个通道具有有效数据,则模块应输出其中一个通道(在我的示例中为索引最高的通道),并删除其余通道 我的简单实现如下所示: module test1 #( parameter NUM_CHANNEL = 8, parameter DATA_WIDTH = 512 ) ( input logic [DATA_WIDTH - 1 : 0] data_in

我正在设计一个模块,它接受多个通道并输出一个通道。 每个通道由一些宽度的
有效
信号和
数据
组成。 如果通道具有有效数据,模块应输出该通道。如果多个通道具有有效数据,则模块应输出其中一个通道(在我的示例中为索引最高的通道),并删除其余通道

我的简单实现如下所示:

module test1 #(
  parameter NUM_CHANNEL = 8,
  parameter DATA_WIDTH = 512
) (
  input logic [DATA_WIDTH - 1 : 0] data_in [NUM_CHANNEL],
  input logic valid_in [NUM_CHANNEL],
  output logic [DATA_WIDTH - 1 : 0] data_out,
  output logic valid_out
);

  always_comb begin
    valid_out = 0;
    for (int i = 0; i < NUM_CHANNEL; ++i) begin
      if (valid_in[i]) begin
        valid_out = 1;
        data_out = data_in[i];
      end
    end
  end

endmodule
interface channel #(
  parameter DATA_WIDTH = 512
);

  logic valid;
  logic [DATA_WIDTH - 1 : 0] data;

  modport in (
    input valid,
    input data
  );

  modport out (
    output valid,
    output data
  );

endinterface // sub_csr_if

module test #(
  parameter NUM_CHANNEL = 8,
  parameter DATA_WIDTH = 512
) (
  channel.in in[NUM_CHANNEL],
  channel.out out
);

  always_comb begin
    out.valid = 0;
    for (int i = 0; i < NUM_CHANNEL; ++i) begin
      if (in[i].valid) begin
        out.valid = 1;
        out.data = in[i].data;
      end
    end
  end

endmodule
模块测试1#(
参数NUM_CHANNEL=8,
参数数据_宽度=512
) (
[NUM_CHANNEL]中的输入逻辑[DATA_WIDTH-1:0]DATA_,
[NUM_CHANNEL]中的输入逻辑有效_,
输出逻辑[数据宽度-1:0]数据输出,
输出逻辑有效输出
);
总是从梳子开始
有效_out=0;
对于(int i=0;i
这在模拟和实际电路(FPGA)中都能很好地工作

但是,通道可能是复杂类型,因此我使用了如下界面:

module test1 #(
  parameter NUM_CHANNEL = 8,
  parameter DATA_WIDTH = 512
) (
  input logic [DATA_WIDTH - 1 : 0] data_in [NUM_CHANNEL],
  input logic valid_in [NUM_CHANNEL],
  output logic [DATA_WIDTH - 1 : 0] data_out,
  output logic valid_out
);

  always_comb begin
    valid_out = 0;
    for (int i = 0; i < NUM_CHANNEL; ++i) begin
      if (valid_in[i]) begin
        valid_out = 1;
        data_out = data_in[i];
      end
    end
  end

endmodule
interface channel #(
  parameter DATA_WIDTH = 512
);

  logic valid;
  logic [DATA_WIDTH - 1 : 0] data;

  modport in (
    input valid,
    input data
  );

  modport out (
    output valid,
    output data
  );

endinterface // sub_csr_if

module test #(
  parameter NUM_CHANNEL = 8,
  parameter DATA_WIDTH = 512
) (
  channel.in in[NUM_CHANNEL],
  channel.out out
);

  always_comb begin
    out.valid = 0;
    for (int i = 0; i < NUM_CHANNEL; ++i) begin
      if (in[i].valid) begin
        out.valid = 1;
        out.data = in[i].data;
      end
    end
  end

endmodule
接口通道#(
参数数据_宽度=512
);
逻辑有效;
逻辑[数据宽度-1:0]数据;
莫德波特(
输入有效,
输入数据
);
莫德波特(
输出有效,
输出数据
);
endinterface//sub_csr_if
模块测试#(
参数NUM_CHANNEL=8,
参数数据_宽度=512
) (
在[NUM_channel]中的channel.in,
信道输出
);
总是从梳子开始
out.valid=0;
对于(int i=0;i
然后,此代码将
非恒定索引获取到实例数组“sub_port.”
ModelSim中的错误,并且
i在Quartus中不是常量

如果展开循环,它会工作,但会变成非参数代码。(仅适用于固定数量的信道)

为什么后一种方法不起作用,而第一种方法能完美地工作?

实例数组(模块或接口)不是真正的数组类型。如错误消息所示,您无法选择具有可变索引的特定实例。对于真数组,每个元素都是相同的。由于参数化、defparam和端口连接的工作方式不同,每个实例元素可能存在差异。精化过程本质上是在模拟开始之前将所有层次结构扁平化

您可以使用
generate
构造选择您的实例,如下所示 ;

模块测试#(
参数NUM_CHANNEL=8,
参数数据_宽度=512
) (
在[NUM_channel]中的channel.in,
信道输出
);
逻辑_有效[NUM_通道];
逻辑[DATA_WIDTH-1:0]_数据[NUM_CHANNEL];

对于(genvar ii=0;iiI,我明白了。我开始好奇了;您有一个
的好例子吗?因为参数化、defparam和端口连接的工作方式,每个实例元素都可能有差异。