verilog生成循环出错:无法绑定wire / reg / memory

问题描述 投票:0回答:1

我正在构建一个基于Row Adder Tree(二叉树)架构和modified baugh-wooley algorithm的带符号乘数verilog代码。

但是,当我在二叉树的后续层添加部分产品时,我面临生成循环的问题。

你们有任何想法如何摆脱这些错误吗?

edaplayground online code

使用生成循环是唯一可行的方法(给定大量的被乘数和乘数)来跨二叉树的层添加部分乘积?

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 && unbuffer vvp a.out

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

design.sv:108:错误:无法绑定wire / reg / memory'interm_layers [(layer) - ('sd1)]。middle_rows [(('sd1)<<(pp_index))+('sd1)]'in 'test.mul.middle_layers [1]'

精心制作期间出现2个错误。

time-complexity binary-tree verilog fpga multiplication
1个回答
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
© www.soinside.com 2019 - 2024. All rights reserved.