Verilog生成循环出错:无法绑定线/寄存器/内存

时间:2019-02-01 09:02:34

标签: time-complexity binary-tree verilog fpga multiplication

我正在基于Row Adder Tree(二叉树)体系结构和modified baugh-wooley algorithm构建有符号乘法器Verilog代码。

但是,当我在二叉树的后续层中添加部分乘积时,我面临着generate loop的问题。

你们知道如何摆脱这些错误吗?

edaplayground online code

row adder tree multiplier

使用generate循环是否是唯一可行的方法(给定被乘数和乘数的长度很大),以便跨二叉树的各层进行部分乘积的加法运算?

module multiply(clk, reset, in_valid, out_valid, in_A, in_B, out_C); // C=A*B

parameter A_WIDTH = 16;
parameter B_WIDTH = 16;

input clk, reset;
input in_valid; // to signify that in_A, in_B are valid
input signed [(A_WIDTH-1):0] in_A;
input signed [(B_WIDTH-1):0] in_B;
output reg signed [(A_WIDTH+B_WIDTH-1):0] out_C;
output reg out_valid; // to signify that out_C is valid

/* 
   This multiplier code architecture requires an area of O(N*M*logN) and time O(logN)
   with M being the length or bitwidth of the multiplicand

   see https://i.imgur.com/NaqjC6G.png or 
   Row Adder Tree Multipliers in http://www.andraka.com/multipli.php or
   https://pdfs.semanticscholar.org/415c/d98dafb5c9cb358c94189927e1f3216b7494.pdf#page=10
   regarding the mechanisms within all layers

   In the case of an adder tree, the adders making up the levels closer to the input 
   take up real estate (remember the structure of row adder tree).  As the size of 
   the input multiplicand bitwidth grows, it becomes more and more difficult to find a
   placement that does not use long routes involving multiple switch nodes.  The result
   is the maximum clocking speed degrades quickly as the size of the bitwidth grows.

   For signed multiplication, see also modified baugh-wooley algorithm for trick in 
   skipping sign extension, thus smaller final routed silicon area.

   https://stackoverflow.com/questions/54268192/understanding-modified-baugh-wooley-multiplication-algorithm/

   All layers are pipelined, so throughput = one result for each clock cycle 
   but each multiplication result still have latency = NUM_OF_INTERMEDIATE_LAYERS 
*/


// The multiplication of two numbers is equivalent to adding as many copies of one 
// of them, the multiplicand, as the value of the other one, the multiplier.

localparam SMALLER_WIDTH = (A_WIDTH <= B_WIDTH) ? A_WIDTH : B_WIDTH;
localparam LARGER_WIDTH = (A_WIDTH > B_WIDTH) ? A_WIDTH : B_WIDTH;

wire [(LARGER_WIDTH-1):0] MULTIPLICAND = (A_WIDTH > B_WIDTH) ? in_A : in_B ;
wire [(SMALLER_WIDTH-1):0] MULTIPLIPLIER = (A_WIDTH <= B_WIDTH) ? in_A : in_B ;

localparam NUM_OF_INTERMEDIATE_LAYERS = $clog2(SMALLER_WIDTH);


/*Stage 1: Binary multiplications to generate partial products rows*/

// first layer has "SMALLER_WIDTH" entries of data of width "LARGER_WIDTH"
// This resulted in a binary tree with faster vertical addition processes as we have 
// lesser (NUM_OF_INTERMEDIATE_LAYERS) rows to add
reg [(LARGER_WIDTH-1):0] partial_products [0:(SMALLER_WIDTH-1)];

generate

    genvar first_layer_index; // all partial products rows are in first layer

    for(first_layer_index=0; first_layer_index<SMALLER_WIDTH; first_layer_index=first_layer_index+1) begin: first_layer

        always @(posedge clk, posedge reset)
        begin
            if(reset) partial_products[first_layer_index] <= 0;

            else begin
                partial_products[first_layer_index] <= (MULTIPLICAND & MULTIPLIPLIER[first_layer_index]);  // generation of partial products rows
            end
        end
    end

endgenerate


/*Stage 2 : Intermediate partial products additions*/

// intermediate partial product rows
// Imagine a rhombus of height of "NUM_OF_INTERMEDIATE_LAYERS" 
// and width of "LARGER_WIDTH" being re-arranged into binary row adder tree
// such that additions can be done in O(logN) time

generate

    genvar layer;

    for(layer=1; layer<NUM_OF_INTERMEDIATE_LAYERS; layer=layer+1) begin: middle_layers

        // number of leafs (or children) in each layer within the binary tree
        localparam NUM_OF_PP_ADDITION = (SMALLER_WIDTH >> layer);

        reg [(LARGER_WIDTH+layer-1):0] middle_rows[0:(NUM_OF_PP_ADDITION-1)];

        integer pp_index; // leaf index within each layer of the tree

        always @(posedge clk, posedge reset)
        begin
            if(reset) 
            begin
                for(pp_index=0; pp_index<NUM_OF_PP_ADDITION ; pp_index=pp_index+1)
                    middle_rows[pp_index] <= 0;
            end

            else begin
                for(pp_index=0; pp_index<NUM_OF_PP_ADDITION ; pp_index=pp_index+1)
                    middle_rows[pp_index] <=
                    middle_layers[layer-1].middle_rows[1<<pp_index] +
                    (middle_layers[layer-1].middle_rows[(1<<pp_index) + 1]) << 1;
            end
        end
    end

endgenerate


/*Stage 3 : Adding the final two partial products*/

wire sign_bit = in_A[A_WIDTH-1] ^ in_B[B_WIDTH-1];

always @(posedge clk, posedge reset)
begin
    if(reset) 
    begin
        out_C <= 0;
        out_valid <= 0;
    end

    else out_C <= 0;// {sign_bit, };
end

endmodule

iverilog'-Wall''-g2012'design.sv testbench.sv &&取消缓冲vvp a.out

design.sv:107:错误:无法绑定导线/ reg /内存'middle_layers [(layer)-('sd1)]。middle_rows [('sd1)<<(pp_index) ]”在“ test.mul.middle_layers [1]”中

design.sv:108:错误:无法绑定电线/ reg /内存'middle_layers [(layer)-('sd1)]。middle_rows [(((sdd1)<<(pp_index ))+('sd1)]'在'test.mul.middle_layers [1]'

在制作过程中出现

2个错误

1 个答案:

答案 0 :(得分:0)

您的错误是您的代码中没有名为multiple_layers[0]的块。 您从

开始
for(layer=1; ...) begin: multile_layers 
    reg [(LARGER_WIDTH+layer-1):0] middle_rows;
    always begin
        reset middle rows; 
        for ... multiple_layers [layer - 1] ... 
    end
end

因此,对上一个块的最后引用失败。

我想您将需要类似以下的内容

    for(layer=0; ...) begin: multile_layers 
       reg [(LARGER_WIDTH+layer-1):0] middle_rows;
       if (layer > 1) begin
          always begin 
               reset middle rows
               for ... multiple_layers [layer - 1] ... 
          end
       end
       else begin
          always begin 
               reset middle_rows 
               // no for
          end
       end
    end