SystemVerilog: упаковка и последующая распаковка с помощью потокового оператора выдает ОШИБКУ: «неправильный тип элемента в конкатенации распакованного массива» в Vivado

#hdl #vivado

#hdl #vivado

Вопрос:

Я пытаюсь упаковать 2D распакованный массив, передать его через оболочку Verilog и распаковать его в другой модуль (или тестовый стенд). Простейший код выглядит следующим образом:

 module a_tb();
  timeunit 10ns;
  timeprecision 1ns;

  localparam N     = 4;
  localparam WIDTH = 8;

  logic [N*N*WIDTH-1:0] A_flat_1;
  logic [WIDTH-1:0] A_1 [N][N];

  logic [N*N*WIDTH-1:0] A_flat_2;
  logic [WIDTH-1:0] A_2 [N][N];

  assign {<<{A_flat_1}} = A_1;
  assign A_flat_2 = A_flat_1;
  assign A_2 = {<<{A_flat_2}};    // Line 13

  initial begin
    foreach (A_1[i,j]) begin
      A_1[i][j] = 10*i j;
    end

    #10;
    $display("%p", A_1);
    $display("%p", A_2);
    assert(A_1==A_2);
  end
endmodule

  

И я получаю следующую ошибку в симуляторе Vivado 2018.2:

 ERROR: [VRFC 10-1571] wrong element type in unpacked array concatenation [U:/path/array_test.tb.sv:13]
  

Из того, что я понимаю о потоковых операторах, это должно сработать. Может ли это быть ошибкой инструмента?

Комментарии:

1. Это может быть ошибка инструмента. Попробуйте свой код с другим симулятором на www.EDAplayground.com

2. @dave_59 Это ошибка инструмента. это работает в VCS. Большое спасибо. Я опубликовал ответ с обходным решением, которое работает в обоих случаях.

Ответ №1:

Это ошибка в симуляторе Vivado. Синтаксис работает в Synposis VCS (EDA playground).

После нескольких дней экспериментов я обнаружил, что в Vivado Simulator {<<{A_flat_2}} просто переворачивает биты, сохраняя их упакованными, следовательно, возвращает logic [N*N*WIDTH-1:0] вектор.

В качестве обходного пути я выяснил, что {>>{{<<{A_flat_2}}}} возвращает распакованный вектор типа logic [WIDTH-1:0] A_2 [N][N] .

Обходной путь (работает как в VCS, так и в Vivado)

 module a_tb();
  timeunit 10ns;
  timeprecision 1ns;
  
  localparam N     = 4;
  localparam WIDTH = 8;

  logic [N*N*WIDTH-1:0] A_flat_1;
  logic [WIDTH-1:0] A_1 [N][N];
  logic [N*N*WIDTH-1:0] A_flat_2;
  logic [WIDTH-1:0] A_2 [N][N];

  assign {<<{A_flat_1}} = A_1;
  assign A_flat_2 = A_flat_1;
  assign A_2 = {>>{{<<{A_flat_2}}}};

  initial begin
    foreach (A_1[i,j]) begin
      A_1[i][j] = 10*i j;
    end
    #10;
    $display("%p", A_1);
    $display("%p", A_2);
    assert(A_1==A_2);
  end
endmodule