Verilog: альтернативный способ индексирования сигнала на LHS

Я использую Xilinx, который использует XST для синтеза моего дизайна. У меня проблемы, когда я пишу что-то вроде someReg[offest*index+:constant] <= someOtherReg;. Приведена ошибка: «Индекс переменной не поддерживается в сигнале». После поиска в Интернете я понял, что индексирование сигнала, расположенного слева, не поддерживается инструментом синтеза XST.


Мне интересно, как реализовать эту логику индексации сигнала без использования этого синтаксиса. В приведенном ниже примере я создаю множитель Matrix, который повторно использует множитель rowByColumn.


Обычно при каждом нарастающем фронте тактового сигнала я загружаю новые значения на вход множителя rowByColumn, а при следующем нарастающем фронте тактового сигнала я сохраняю результат в новом регистре. Сохранение результата в новом регистре - основная моя проблема.


Вот код, который дает ошибку. Не могли бы вы предложить способы решения или обхода проблемы.

module MatrixSeq(clk,A,B,C);
    // param
    parameter WIDTH = 32;
    parameter ROW_A  = 2;
    parameter COL_A  = 2;
    parameter ROW_B  = 2;
    parameter COL_B  = 2;
    //ports
    input clk;
    input [WIDTH*COL_A*ROW_A-1:0] A;
    input [WIDTH*COL_B*ROW_B-1:0] B;
    output [WIDTH*ROW_A*COL_B-1:0] C;

    // inputs to rowBycol 
    reg signed [WIDTH*COL_A-1:0] currentRowA;
    reg signed [WIDTH*ROW_B-1:0] currentColB;
    reg signed [WIDTH-1:0] rowByColOut;
    wire signed [WIDTH-1:0] rowByColOutWire; // wire to connet to rowByColOut

    // A,B matrix holders
    reg signed [WIDTH*COL_A*ROW_A-1:0] AsigHolder;
    reg signed [WIDTH*COL_B*ROW_B-1:0] BsigHolder;
    reg signed [WIDTH*ROW_A*ROW_B-1:0] CsigHolder; // C = A*B

    // reg signed [WIDTH-1:0] count;
    integer idxA = 0;       // iterates through the rows of A
    integer idxB = 0;       // iterates through the 'rows' of B

    // Indexing Syntax:
    //  signalAdd[some_expression +: some_range];
    //  Resolves to
    //  signalAdd[some_expression + (some_range - 1) : some_expression];

    always @(posedge clk) begin     // assume we have the transpose of matrix B
        currentRowA <= AsigHolder[WIDTH*COL_A*idxA+:WIDTH*COL_A];
        currentColB <= BsigHolder[WIDTH*COL_B+idxB+:WIDTH*COL_B];
        CsigHolder[WIDTH*(idxA*ROW_A+idxB)+:WIDTH] <= rowByColOut;  // Error: 'Variable index is not supported in signal.'
        idxB <= idxB +1;
        if(idxB == ROW_B) begin     // multiply each row of A with every 'row' B
            idxA <= idxA + 1;
            idxB <= 0;
        end else if(idxA == ROW_A) begin
            idxA <= 0;
            idxB <= 0;
        end
    end
    assign rowByColOutWire = rowByColOut;
    rowBycol rowMultColumn (.CLK(clk), .a(currentRowA), .b(currentColB), .y(rowByColOutWire));  // row by column multiplier
    assign C = CsigHolder;

endmodule

Чтобы прояснить ситуацию, проблема заключается в третьей строке внутри блока always, которая выдает ошибку «Индекс переменной не поддерживается в сигнале».


person user3697625    schedule 09.03.2016    source источник


Ответы (1)


Если XST не поддерживает частичный выбор (_1 _ / _ 2_) и вы не можете выполнить обновление до чего-то, что не соответствует стандарту IEEE Std 1364-2001, тогда вам нужно будет сделать это методом 1995 года; присвоение битов:

for(bit_idx = 0; bit_idx < WIDTH*COL_A; bit_idx=bit_idx+1) begin
  currentRowA[idx] <= AsigHolder[WIDTH*COL_A*idxA + bit_idx];
end

Или двухмерные массивы:

reg signed [WIDTH*COL_A-1:0] AsigHolder [0:ROW_A-1];
...

always @(posedge clk) begin     // assume we have the transpose of matrix B
  currentRowA <= AsigHolder[idxA];

Я заметил, что ваши idxA и idxB могут выходить за пределы диапазона. Все регистры, которым назначена неблокирующая функция (<=), обновляются после оценки. Это означает, что idxB==ROW_B будет оцениваться перед обновлением idxB <= idxB +1.
У вас должно получиться что-то вроде следующего:

if (idxB < ROW_B-1) begin
  idxB <= idxB + 1;
end
else begin
  idxB <= 0;
  if (idxA < ROW_A-1) begin
    idxA <= idxA + 1;
  end
  else begin
    idxA <= 0;
  end
end

Примечание: исправив назначения индекса, можно использовать частичный выбор (_11 _ / _ 12_), поскольку дизайн не может достичь индекса, выходящего за границы.

person Greg    schedule 09.03.2016
comment
Благодарим за уведомление о том, что idxA и idxB могут выйти за пределы допустимого диапазона. XST жалуется только на эту строку CsigHolder[WIDTH*(idxA*ROW_A+idxB)+:WIDTH] <= rowByColOut;. Я попробую использовать «двумерный» массив и посмотрю, систематизируется ли он. - person user3697625; 10.03.2016
comment
Я определил CsigHolder так reg signed [WIDTH-1:0] CsigHolder [0:ROW_A*COL_B-1];. XST выдает ошибку, когда я пытаюсь подключить провод C к CsigHolder с помощью оператора assign, подобного этому assign C = CsigHolder;. Как мне подключить C к CsigHolder? - person user3697625; 10.03.2016