Ошибка в цикле создания verilog: невозможно связать провод / регистр / память - PullRequest
0 голосов
/ 01 февраля 2019

Я строю код Verilog с множителем со знаком на основе Архитектура сумматора строк (двоичное дерево) и модифицированного алгоритма Боу-Вули .

Однако яКогда я добавляю частичные продукты в последующий слой двоичного дерева, возникает проблема с циклом генерации.

У вас есть какие-нибудь идеи, как избежать этой ошибки?

Онлайн-код edaplayground

row adder tree multiplier

Использует цикл создания единственно возможным способом (учитывая большую длину умножения и множителя) для добавления частичных произведений в слои двоичного файлаtree?

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.

   /10753315/ponimanie-modifitsirovannogo-algoritma-umnozheniya-bougli

   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: ошибка: Невозможнодля связывания wire / reg / memory 'middle_layers [(layer) - (' sd1)]. middle_rows [('sd1) << (pp_index)]' in 'test.mul.middle_layers [1]' </p>

design.sv: 108: ошибка: Невозможно связать wire / reg / memory 'middle_layers [(layer) - (' sd1)]. middle_rows [(('sd1) << (pp_index)) + (' sd1)] 'in' test.mul.middle_layers [1] '</p>

2 ошибка (s) во время разработки.

1 Ответ

0 голосов
/ 01 февраля 2019

ваша ошибка в том, что в вашем коде нет блока с именем 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
...