Ошибка SystemVerilog в каналах мультиплексирования: непостоянный индекс в массиве экземпляров - PullRequest
1 голос
/ 21 марта 2019

Я разрабатываю модуль, который принимает несколько каналов и выводит один канал. Каждый канал состоит из сигнала 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

Затем этот код получает ошибку Nonconstant index into instance array 'sub_port'. в ModelSim и ошибку i is not a constant в Quartus.

Если я разверну цикл, он будет работать, но станет непараметрическим кодом. (работает только для фиксированной NUM_CHANNEL)

Почему последний не работает, а первый работает безупречно?

1 Ответ

3 голосов
/ 21 марта 2019

Массив экземпляров (модуль или интерфейс) не является истинным типом массива.Как показывает ваше сообщение об ошибке, вы не можете выбрать конкретный экземпляр с индексом переменной.С истинным массивом каждый элемент идентичен.Из-за того, как работают параметризация, 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
...