verilog有符号数的乘法

发布于:2025-04-09 ⋅ 阅读:(40) ⋅ 点赞:(0)

1、单周期乘法器

        对于低速要求的乘法器,可以简单的使用 * 实现。

module    Mult
            (
                input    wire [7:0]    multiplicand    ,
                input    wire [7:0]    multipliter     ,

                output   wire [7:0]    product
            );

    assign    product = multiplicand    *    multipliter     ;

endmodule

        下面例子为按照 加性分解 的思路

module    Mul
            (
                input    wire [7:0]    multiplicand    ,
                input    wire [7:0]    multiplier      ,

                output   wire [7:0]    product
            );

    wire [15:0]    adder0 , adder1 , adder2 ,adder3 , adder4 , adder5 , adder6 , adder7 ;

    assign    adder0    =    ( multiplier[0] == 1'b1 )?{8'd0,multiplicand }:15'b0    ;    
    assign    adder1    =    ( multiplier[1] == 1'b1 )?{7'd0,multiplicand,1'b0}:15'b0   ;  
    assign    adder2    =    ( multiplier[2] == 1'b1 )?{6'd0,multiplicand,2'b0}:15'b0    ;  
    assign    adder3    =    ( multiplier[3] == 1'b1 )?{5'd0,multiplicand,3'b0}:15'b0    ;  
    assign    adder4    =    ( multiplier[4] == 1'b1 )?{4'd0,multiplicand,4'b0}:15'b0    ;  
    assign    adder5    =    ( multiplier[5] == 1'b1 )?{3'd0,multiplicand,5'b0}:15'b0    ;  
    assign    adder6    =    ( multiplier[6] == 1'b1 )?{2'd0,multiplicand,6'b0}:15'b0    ;  
    assign    adder7    =    ( multiplier[7] == 1'b1 )?{1'd0,multiplicand,7'b0}:15'b0    ;     

    assign    product    =    adder0 + adder1 + adder2 + adder3 + adder4 + adder5 + adder6 + adder7    ;

endmodule

        高吞吐改进型

        经常会出现高吞吐的数据处理类型,组合逻辑实现延迟较大,需要用流水线思路.

        采样流水线的乘法器,虽然不能一个clk计算完成,但是可以提高运算吞吐量

`timescale 1ns / 1ps



module mult
    (
        input   wire        clk             ,
        
        input   wire [7:0]  multiplicand    ,
        input   wire [7:0]  multiplier      ,
        
        output  wire [15:0] product
        
    );
    
    reg [15:0]      model_product   ;
    
    reg [15:0]      adder0 , adder1 , adder2 , adder3 , adder4 , adder5 , adder6 , adder7   ;
    reg [15:0]      t1a ,t1b , t1c , t1d ;
    reg [15:0]      t2a , t2b   ;
    
    always@( posedge clk )
    begin
    
        if( multiplier[0] == 1'b1 )
        begin
            adder0  <=  { 8'b0,multiplicand }   ;
        end
        else
        begin
            adder0  <=  15'b0   ;
        end
        
        if( multiplier[1] == 1'b1 )
        begin
            adder1  <=  { 7'b0,multiplicand,1'b0 }   ;
        end
        else
        begin
            adder1  <=  15'b0   ;
        end
        
        if( multiplier[2] == 1'b1 )
        begin
            adder2  <=  { 6'b0,multiplicand,2'b0 }   ;
        end
        else
        begin
            adder2  <=  15'b0   ;
        end
        
        if( multiplier[3] == 1'b1 )
        begin
            adder3  <=  { 5'b0,multiplicand,3'b0 }   ;
        end
        else
        begin
            adder3  <=  15'b0   ;
        end
        
        if( multiplier[4] == 1'b1 )
        begin
            adder4  <=  { 4'b0,multiplicand,4'b0 }   ;
        end
        else
        begin
            adder4  <=  15'b0   ;
        end
        
        if( multiplier[5] == 1'b1 )
        begin
            adder5  <=  { 3'b0,multiplicand,5'b0 }   ;
        end
        else
        begin
            adder5  <=  15'b0   ;
        end
        
        if( multiplier[6] == 1'b1 )
        begin
            adder6  <=  { 2'b0,multiplicand,6'b0 }   ;
        end
        else
        begin
            adder6  <=  15'b0   ;
        end
        
        if( multiplier[7] == 1'b1 )
        begin
            adder7  <=  { 1'b0,multiplicand,7'b0 }   ;
        end
        else
        begin
            adder7  <=  15'b0   ;
        end
        
        t1a =   adder0  +   adder1  ;
        t1b =   adder2  +   adder3  ;
        t1c =   adder4  +   adder5  ;
        t1d =   adder6  +   adder7  ;
        
        t2a =   t1a +   t1b ;
        t2b =   t1c +   t1d ;
        
        model_product   =   t2a +   t2b ;
        
    end
    
    assign product  =   model_product   ;
    
endmodule

`timescale 1ns / 1ps


module tb_mult();

    reg         clk ;
    
    reg [7:0]   multiplicand    ;
    reg [7:0]   multiplier      ;
    
    wire [15:0]     product     ;
    
    initial
    begin
        clk =   1'b0    ;
        #100
        multiplicand    =   8'd50   ;
        multiplier      =   8'd20   ;
        #100
        multiplicand    =   8'd100   ;
        multiplier      =   8'd5     ;       
        
        $finish ;
    end

    
    always #2.5 clk = ~clk  ;

    mult        mult_inst
    (
        .clk                    (clk),
                                
        .multiplicand           (multiplicand),
        .multiplier             (multiplier),
        
        .product                (product)
        
    );

endmodule

         可变系数乘法实现方式-----基于减性分解

        实现乘法器的另一种思路是按照减性分解

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/28 16:02:59
// Design Name: 
// Module Name: mult_3
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module mult_3
    (
        input   wire        clk             ,
        input   wire        rst_n           ,
        
        input   wire        enIn            ,
        input   wire [7:0]  multiplicand    ,
        input   wire [7:0]  multiplier      ,
        
        output  wire        busy            ,
        output  wire        enOut           ,
        output  wire [15:0] product
        
        
    );
    
    reg [15:0]      out_product ;
    reg             out_busy    ;
    reg             out_enOut   ;
    
    parameter   IDLE    =   0   ;
    parameter   S_CALE  =   1   ;
    
    reg         state,next_state    ;
    reg         lockMuls            ;
    reg  [15:0] mulA                ;
    reg  [9:0]  mulB                ;
    wire [1:0]  oriBits             ;
    reg         adding , shifting , subbing , ending ;
    reg [15:0]  calculator ;
    reg         out_busy    ;
    
    assign  busy    =   out_busy    ;
    assign  enOut   =   out_enOut   ;
    assign  product =   out_product ;
    
    always@( posedge clk )
    begin
        if( rst_n == 1'b0 )
        begin
            state   <=  IDLE    ;
            mulA    <=  15'd0   ;
            mulB    <=  10'd0   ;
            calculator  <=  16'd0   ;
            out_enOut   <=  1'b0    ;
            out_product <=  16'd0   ;
        end
        else
        begin
            state   <=  next_state  ;
            //mulA mulB
            if( lockMuls == 1'b1 )
            begin
                mulA    <=  { 8'b0,multiplicand }   ;
                mulB    <=  { 1'b0,multiplier,1'b0 }    ;  
            end
            else if( shifting == 1'b1 )
            begin
                mulA    <=  { mulA[14:0],1'b0 } ;
                mulB    <=  { 1'b0,mulB[9:1] }  ;
            end
            //calculator
            if( lockMuls == 1'b1 )
            begin
                calculator <=  16'b0   ;
            end
            else if( adding == 1'b1 )
            begin
                calculator  <=  calculator + mulA   ;
            end
            else if( subbing == 1'b1 )
            begin
                calculator  <=  calculator - mulA   ;               
            end
            //out_enOut
            out_enOut   <=  ending  ;
            //out_product
            if( ending == 1'b1 )
            begin
                out_product <=  calculator  ;
            end
        end
    end
    
    assign  oriBits =   mulB[1:0]   ;
    
    always@( state,enIn,oriBits,mulB )
    begin
        out_busy <=  1'b0    ;
        lockMuls <=  1'b0    ;
        adding   <=  1'b0    ;
        shifting <=  1'b0    ;
        subbing  <=  1'b0    ;
        ending   <=  1'b0    ;  
        
        case( state )
            IDLE    :
                begin
                    if( enIn == 1'b1 )
                    begin
                        next_state  <=  S_CALE  ;
                        lockMuls    <=  1'b1    ;
                    end
                    else
                    begin
                        next_state  <=  IDLE  ;                    
                    end
                end
            S_CALE  :
                begin
                    out_busy    <=  1'b1    ;
                    shifting    <=  1'b1    ;
                    
                    case( oriBits )
                        2'b01   :
                            begin
                                adding  <= 1'b1  ;
                            end
                        2'b10   :
                            begin
                                subbing <= 1'b1  ;
                            end
                    endcase
                    if( mulB == 10'b0 )
                    begin
                        ending  <=   1'b1    ;
                        next_state  <=  IDLE   ; 
                    end
                    else
                    begin
                        next_state  <=   S_CALE  ;
                    end  
                end
            default :
                begin
                    next_state  <=  IDLE    ;
                end
        endcase
    end  
endmodule
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/28 15:37:12
// Design Name: 
// Module Name: tb_mult
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_mult();

    reg         clk ;
    reg         rst_n   ;
    reg         enIn    ;
    reg [7:0]   multiplicand    ;
    reg [7:0]   multiplier      ;
    wire        busy            ;
    wire        enOut           ;
    wire [15:0]     product     ;
    
    initial
    begin
      clk   =   1'b0    ;
      rst_n =   1'b0    ;
      enIn  =   1'b0    ;
      
      multiplicand  =   8'd1000    ;
      multiplier    =   8'd20      ;
      
      #50
      rst_n =   1'b1    ;
      enIn  =   1'b1    ;      
      
      
    end

    
    always #2.5 clk = ~clk  ;

    mult_3  mult_3_inst
    (
        .clk                        (clk)      ,
        .rst_n                      (rst_n)      ,
                                          
        .enIn                       (enIn)      ,
        .multiplicand               (multiplicand)      ,
        .multiplier                 (multiplier)      ,
                                         
        .busy                       (busy)      ,
        .enOut                      (enOut)      ,
        .product                    (product)
    );

endmodule

  按照减性分解的改进

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/08 17:13:19
// Design Name: 
// Module Name: mult_3B
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module mult_3B
    (
    // clk and rst_
        input   wire        sys_clk         ,
        input   wire        sys_rst_n       ,
    // input multipilicand and multipliter
        input   wire [7:0]  multiplicand   ,
        input   wire [7:0]  multipliter     ,
        input   wire        enIn            ,
    // output product
        output  wire        busy            ,
        output  wire        enOut           ,
        output  wire [15:0] product  
    );
    
    localparam  IDLE    =   1'b0    ;
    localparam  S_CALE  =   1'b1    ;
    
    reg         current_state       ;
    reg         next_state          ;
    
    reg         lockMuls            ;
    reg  [15:0] mulA                ;
    reg  [10:0] mulB                ;
    
    wire [2:0]  oriBits             ;
    
    reg         adding1 , adding2 ,shifting , subbing1 , subbing2 , ending ;
    reg [15:0]  calculator          ;
    
    reg         out_busy             ;
    reg         out_enOut            ;
    reg [15:0]  out_product          ;
    
    always@( posedge sys_clk )
    begin
        if( sys_rst_n == 1'b0 )
        begin
            current_state   <=  IDLE    ;
            mulA            <=  16'b0   ;
            mulB            <=  11'b0   ;
            calculator      <=  16'b0   ;
            out_enOut       <=  1'b0    ;
            out_product     <=  16'd0   ;
        end
        else
        begin
            current_state   <=  next_state  ;
            // mulA mulB
            if( lockMuls == 1'b1 )
            begin
                mulA    <=  { 8'b0,multiplicand }       ;
                mulB    <=  { 2'b0,multiplicand,1'b0 }  ;
            end
            else if( shifting == 1'b1 )
            begin
                mulA    <=  { mulA[13:0],2'b0 } ;
                mulB    <=  { 2'b0,mulB[10:2] } ;
            end
            // calculator
            if( lockMuls == 1'b1 )
            begin
                calculator  <=  16'd0   ;
            end
            else if( adding1 == 1'b1 )
            begin
                calculator  <=  calculator + mulA   ;
            end
            else if( adding2 == 1'b1 )
            begin
               calculator  <=  calculator + (mulA<<1)   ; 
            end
            else if( subbing1 == 1'b1 )
            begin
                calculator  <=  calculator - mulA   ;
            end
            else if( subbing2 == 1'b1 )
            begin
                calculator  <=  calculator - (mulA<<1)   ;
            end
            
            out_enOut   <=  ending  ;
            // out_product
            if( ending == 1'b1 )
            begin
                out_product <=  calculator  ;
            end   
        end
    end   
    // oriBits
    assign  oriBits = mulB[2:0] ;
    
    always@( current_state,enIn,oriBits,mulB )
    begin
        out_busy    <=  1'b0    ;
        lockMuls    <=  1'b0    ;
        adding1     <=  1'b0    ;
        adding2     <=  1'b0    ;
        shifting    <=  1'b0    ;
        subbing1    <=  1'b0    ;
        subbing2    <=  1'b0    ;
        ending      <=  1'b0    ;
        
        case( current_state )
            IDLE    :
                begin
                    if( enIn == 1'b1 )
                    begin
                        next_state  <=  S_CALE  ;
                        lockMuls    <=  1'b1    ;
                    end
                    else
                    begin
                        next_state  <=  IDLE  ;
                    end
                end
            S_CALE  :
                begin
                    out_busy    <=  1'b1    ;
                    shifting    <=  1'b1    ;
                    // adding1 adding2 subbing1 subbing2 
                    case( oriBits )
                        3'b001,3'b010   :
                            begin
                                adding1 <=  1'b1    ;
                            end
                        3'b101,3'b110   :
                            begin
                                subbing1 <=  1'b1    ;
                            end
                        3'b011          :
                            begin
                                adding2 <=  1'b1    ;
                            end
                        3'b100          :
                            begin
                                subbing2 <=  1'b1    ;
                            end
                        default         :
                            begin
                            end
                    endcase
                    
                    if( mulB == 11'b0 )
                    begin
                        ending  <=  1'b1    ;
                        next_state  <=  IDLE    ;
                    end
                    else
                    begin
                        next_state  <=  S_CALE  ;
                    end
                    
                end
            default :
                begin
                    next_state  <=  IDLE    ;
                end
        endcase
        
    end
    
    
endmodule

1、积的宽度讨论

2、基于无符号乘法器的原码乘法器

3、基于无符号乘法器的补码乘法器

4、补码乘法之 “ 正被乘数 ” 乘以 “ 正乘数 ”

5、补码乘法之 “ 负被乘数 ” 乘以 “ 正乘数 ”

6、补码乘法之 “ 正被乘数 ” 乘以 “ 负乘数 ”

7、补码乘法之 “ 负被乘数 ” 乘以 “ 负乘数 ”

8、补码乘法之加性分解乘法器

9、补码乘法之BOOTH乘法器

10、利用特殊资源实现整数乘法