Verilog:在 LHS 上索引信号的替代方法

Verilog: Altenative way for indexing signal on the LHS

我正在使用 Xilinx,它使用 XST 来综合我的设计。当我写 someReg[offest*index+:constant] <= someOtherReg; 这样的东西时,我 运行 遇到了麻烦。给出的错误是 'Variable index is not supported in signal.' 我在网上搜索后了解到,XST 综合工具不支持索引左侧的信号。


我想知道的是如何在不使用该语法的情况下实现对信号进行索引的逻辑。在下面的示例中,我正在创建一个重用 '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 块中的第三行给出了错误 'Variable index is not supported in signal.'

如果 XST 不支持部分-select (+:/-:) 并且您无法升级到符合 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];

我注意到您的 idxAidxB 可能超出范围。评估后更新所有分配了非阻塞 (<=) 的寄存器。这意味着 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

:通过固定索引赋值,部分-select(+:/-:) 可能会起作用,因为设计无法达到越界索引。