多路复用通道中的SystemVerilog错误:非常量索引到实例数组中

问题描述 投票:1回答:1

我正在设计一个接受多个通道并输出一个通道的模块。每个通道由valid信号和一些宽度的data组成。如果通道具有有效数据,则模块应输出该通道。如果多个通道具有有效数据,则模块应输出其中一个(在我的情况下,具有最高索引的通道)并且将丢弃休止符。

我的简单实现如下所示:

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

这在仿真和实际电路(FPGA)中都能很好地工作。

但是,通道可以是复杂类型,所以我使用这样的接口:

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

然后,此代码在ModelSim中获取Nonconstant index into instance array 'sub_port'.错误,在Quartus中获取i is not a constant错误。

如果我展开循环,它可以工作但它变成非参数代码。 (仅适用于固定的NUM_CHANNEL)

为什么后者不起作用,而第一个完美无缺?

system-verilog modelsim quartus
1个回答
3
投票

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

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

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

logic                     _valid[NUM_CHANNEL];
logic [DATA_WIDTH - 1 : 0] _data[NUM_CHANNEL];

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

endmodule
© www.soinside.com 2019 - 2024. All rights reserved.