タイムシェアリング多重シフト加算乗算器

4041 ワード

きほんアルゴリズム
シフト加算は日常的に使用される手算アルゴリズムであり、シフト加算の説明は以下の通りである.
  • 積の初期値を0
  • とする.
  • 乗数の最低位が0であると積は変わらず、そうでないと積算被乗数
  • となる.
  • 乗数の1番目のビットが0である場合、積は変わらず、そうでない場合、左に1ビットシフトされた被乗数
  • を加算.
  • ...
  • 乗数のn番目のビット(最上位)が0の場合、積は変わらない、そうでない場合、左にシフトn番目の乗数
  • が加算される.
    RTLコード
    module serial_shiftadder_multipcation # (
        parameter WIDTH = 4
    )(
        input clk,    // Clock
        input rst_n,  // Asynchronous reset active low
    
        input multiplier_valid,
        input [WIDTH - 1:0]multiplier1,
        input [WIDTH - 1:0]multiplier2,
    
        output reg product_valid,
        output reg [2 * WIDTH - 1:0]product
    );
    

    インタフェース定義部は、パラメトリック設計を採用し、WIDTHは乗数/被乗数のビット幅、multiplier_validが高くなると入力が有効で計算が開始されます.product_validが引き上げられた場合は計算が完了し、現在の出力が有効であることを示します
    /*****************buffer and shift*******************/
    reg [WIDTH - 1:0]min_mult;
    reg [2 * WIDTH - 1:0]max_mult;
    always @ (posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            {max_mult,min_mult} <= 'b0;
        end else if(multiplier_valid == 1'b1) begin
            if(multiplier1 > multiplier2) begin
                max_mult <= '{multiplier1};
                min_mult <= multiplier2;
            end else begin
                max_mult <= '{multiplier2};
                min_mult <= multiplier1;
            end
        end else if(min_mult != 'b0) begin
            max_mult <= max_mult << 1;
            min_mult <= min_mult >> 1;
        end else begin
            max_mult <= max_mult;
            min_mult <= min_mult;
        end
    end
    

    シフト部は,入力がある場合に2つの入力の大きさを比較し,小さな数で反復数を制御し,時間消費を低減する.小さい乗数が0でなければ、大きい数を左にシフトし、小さい数を右にシフトする.
    /******************adder********************/
    always @ (posedge clk or negedge rst_n) begin
        if(~rst_n) begin
            {product_valid,product} <= 'b0;
        end else if(min_mult[0] == 1'b1) begin
            product <= product + max_mult;
            product_valid <= 1'b0;
        end else if(min_mult != 'b0) begin
            product <= product;
            product_valid <= 1'b0;
        end else if(multiplier_valid == 1'b1) begin
            product <= 'b0;
            product_valid <= 1'b0;
        end else begin
            product <= product;
            product_valid <= 1'b1;
        end
    end
    
    endmodule
    

    累加部は、より小さい乗数が最低位が0である場合、積を一定に保つ.そうしないと、現在の大乗数を累加し、小乗数が0である場合、演算が終了したことを示し、出力が有効に高くなる.
    テスト
    自動化テストを使用して、上位レベルのメソッドを使用して積を計算し、出力と比較して等しいかどうかを確認します.
    module mult_tb (
    );
    
    parameter WIDTH = 4;
    
    logic clk,rst_n;
    logic multiplier_valid;
    logic [WIDTH - 1:0]multiplier1;
    logic [WIDTH - 1:0]multiplier2;
    
    logic product_valid;
    logic [2 * WIDTH - 1:0]product;
    
    serial_shiftadder_multipcation # (
        .WIDTH(WIDTH)
    ) dut (
        .clk(clk),    // Clock
        .rst_n(rst_n),  // Asynchronous reset active low
    
        .multiplier_valid(multiplier_valid),
        .multiplier1(multiplier1),
        .multiplier2(multiplier2),
    
        .product_valid(product_valid),
        .product(product)
    );
    
    initial begin
        clk = 1'b0;
        forever begin
            #50 clk = ~clk;
        end
    end
    
    initial begin
        rst_n = 1'b1;
        #5 rst_n = 1'b0;
        #10 rst_n = 1'b1;
    end
    
    initial begin
        {multiplier_valid,multiplier1,multiplier2} = 'b0;
        forever begin
            @(negedge clk);
            if(product_valid == 1'b1) begin
                multiplier1 = (WIDTH)'($urandom_range(0,2 ** WIDTH));
                multiplier2 = (WIDTH)'($urandom_range(0,2 ** WIDTH));
                multiplier_valid = 1'b1;
            end else begin
                multiplier_valid = 1'b0;
            end
        end
    end
    
    logic [2 * WIDTH - 1:0]exp;
    initial begin
        forever begin
            @(posedge product_valid);
            exp = multiplier1 * multiplier2;
            if(exp == product) begin
                $display("successfully, mult1=%d mult2=%d product=%d",multiplier1,multiplier2,product);
            end else begin
                $display("failed,mult1=%d mult2=%d product=%d exp=%d",multiplier1,multiplier2,product,exp);
            end
        end
    end
    
    endmodule