verilog有符号数的乘法

无符号整数的乘法

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
    
    assign  busy    =   out_busy    ;
    assign  enOut   =   out_enOut   ;
    assign  product =   out_product ;
    
    
endmodule

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


module tb_mult_3B(

    );
 
     // clk and rst_
        reg             sys_clk     ;
        reg             sys_rst_n   ;
        reg [7:0]       multiplicand;
        reg [7:0]       multipliter ;
        reg             enIn        ;
        wire            busy        ;
        wire            enOut       ;
        wire [15:0]     product     ;
        
        initial
        begin
            sys_clk         =   1'b0    ;
            sys_rst_n       =   1'b0    ;
            
            multiplicand    =   8'd0    ;
            multipliter     =   8'd0    ;
            enIn            =   1'b0    ;
            
            #100 
            sys_rst_n       =   1'b1      ;
            multiplicand    =   8'd100    ;
            multipliter     =   8'd200    ;
            enIn            =   1'b1      ;
            #10
            enIn            =   1'b0      ;  
            
            #100
            multiplicand    =   8'd10    ;
            multipliter     =   8'd20    ;
            enIn            =   1'b1      ;
            #10
            enIn            =   1'b0      ;  
            
            $finish ;         
        
        end
        
        // sys_clk
        always #5
        begin
            sys_clk = ~sys_clk  ;
        end
    
    mult_3B     mult_3B_inst
    (
        .sys_clk                (sys_clk),
        .sys_rst_n              (sys_rst_n),
        .multiplicand           (multiplicand),
        .multipliter            (multipliter),
        .enIn                   (enIn),
        .busy                   (busy),
        .enOut                  (enOut),
        .product                (product)
    );
    
endmodule

有符号整数的乘法

现实中运算常常涉及到符号位(有符号整数)

1、积的宽度讨论

宽度为 M 和 N 的两个数相乘,结果为 M+N-1 位。

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

原码乘法器

复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/09 14:59:08
// Design Name: 
// Module Name: mults_4A
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module mults_4A
    (
    //clk and rst_n
        input   wire        sys_clk         ,
        input   wire        sys_rst_n       ,
    //mulu figure
        input   wire [7:0]  multiplicand    ,
        input   wire [7:0]  multiplier      ,
    //product
        output  wire [14:0] product
    );
    
    wire        signOfMulA , signOfMulB ;
    wire [6:0]  absMulA , absMulB   ;
    wire        signOfPro           ;
    wire [13:0] absPro              ;

    
    assign  signOfMulA  =   multiplicand[7] ;
    assign  signOfMulB  =   multiplier[7]   ;
    
    assign  absMulA     =   multiplicand[6:0]   ;
    assign  absMulB     =   multiplier[6:0]     ;
    
    assign  signOfPro   =   signOfMulA ^ signOfMulB ;
    assign  absPro      =   absMulA * absMulB   ;
    

    assign  product     =   { signOfPro,absPro }    ;
    
endmodule

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/09 15:08:25
// Design Name: 
// Module Name: tb_mults_4A
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_mults_4A();

        reg                     sys_clk         ;
        reg                     sys_rst_n       ;
        reg  [7:0]              multiplicand    ;
        reg  [7:0]              multiplier      ;
        wire [14:0]             product         ;

    initial
    begin
        sys_clk         =   1'b0            ;
        sys_rst_n       =   1'b0            ;   
        multiplicand    =   8'b0000_0000    ;
        multiplier      =   8'b0000_0000    ;
        

        sys_rst_n       =   1'b1            ;
        multiplicand    =   8'b0000_0011    ;
        multiplier      =   8'b0000_0100    ;
        #1000
        multiplicand    =   8'b1000_0011    ;
        multiplier      =   8'b0000_0100    ;
        #1000
        $finish;
        
    end
    always #5 sys_clk = ~sys_clk    ;

    mults_4A        mults_4A_inst
    (
        .sys_clk                (sys_clk),
        .sys_rst_n              (sys_rst_n),
        .multiplicand           (multiplicand),
        .multiplier             (multiplier),
        .product                (product)
    );

endmodule

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

复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/09 16:19:46
// Design Name: 
// Module Name: mults_4B
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module mults_4B
    (
        input   wire [7:0]  multiplicand        ,
        input   wire [7:0]  multiplier          ,
        
        output  wire [14:0] product
    );
    
    wire [1:0]      signs               ;
    wire [15:0]     modifyA , modifyB   ;
    wire [15:0]     unsignedProduct     ;
    reg  [15:0]     finalProduct        ;
    
    
    assign  signs   =   { multiplicand[7],multiplier[7] }   ;
    assign  modifyA =   { multiplicand,8'b0 }   ;
    assign  modifyB =   { multiplier,8'b0 } ;
    assign  unsignedProduct =   multiplicand * multiplier   ;
    assign  product =  finalProduct[14:0] ; 
    
    always@( signs , modifyA , modifyB , unsignedProduct )
    begin
        case( signs )
            2'b00   :
                begin
                    finalProduct    =   unsignedProduct ;
                end
            2'b01   :
                begin
                    finalProduct    =   unsignedProduct - modifyA ;
                end
            2'b10   :
                begin
                    finalProduct    =   unsignedProduct - modifyB ;
                end
            2'b11   :
                begin
                    finalProduct    =   unsignedProduct - modifyA - modifyB ;
                end
            default :
                begin
                    finalProduct    <=  16'b0   ;
                end
        endcase
    end
    
endmodule

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/09 16:37:34
// Design Name: 
// Module Name: tb_mults_4B
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_mults_4B();

        reg  [7:0]  multiplicand       ; 
        reg  [7:0]  multiplier         ;
        wire [14:0] product            ;
        
    initial
    begin
        multiplicand    =   8'd0    ;
        multiplier      =   8'd0    ;    
        #10
        $display(" simulink start: ")   ;
        multiplicand    =   8'd2    ;
        multiplier      =   8'd40   ;
        #1000
        multiplicand    =   -8'd2   ;
        multiplier      =   8'd40   ;
        #1000
        $display(" simulink end ")   ;       
        $finish ;
        
    end

    mults_4B       mults_4B_inst     
    (
        .multiplicand               (multiplicand)  ,
        .multiplier                 (multiplier)  ,
        .product                    (product)
    );
    
endmodule

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

复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/09 17:05:44
// Design Name: 
// Module Name: mults_5
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module mults_5
    (
    // clk and rst_n
        input   wire        sys_clk         ,
        input   wire        sys_rst_n       ,
    // multiplicand multiplier
        input   wire [7:0]  multiplicand    ,
        input   wire [7:0]  multiplier      ,
        input   wire        enIn            ,
    // product enOut
        output  wire        enOut           ,
        output  wire        busy            ,
        output  wire [15:0] product     
    );
    
    reg [15:0]      out_product ;
    reg             out_busy    ;
    reg             out_enOut   ;
    
    localparam  IDLE    =   1'b0    ;
    localparam  S_CALC  =   1'b1    ;
    
    reg         current_state , next_state  ;
    reg         lockMuls    ;
    reg [15:0]  mulA    ;
    reg         signOfMulB  ;
    reg [7:0]   mulB    ;
    reg         adding , shifting , ending ;
    reg [15:0]  accumulator ;
    
    always@( posedge sys_clk )
    begin
        if( sys_rst_n == 1'b0 )
        begin
            current_state   <=  IDLE    ;
            mulA            <=  16'b0   ;
            signOfMulB      <=  1'b0    ;
            mulB            <=  8'b0    ;
            accumulator     <=  16'b0   ;
            out_enOut       <=  1'b0    ;
            out_product     <=  16'b0   ;
        end
        else
        begin
            current_state  <=  next_state  ;
            // mulA mulB
            if( lockMuls == 1'b1 )
            begin
                mulA        <=  { {8{multiplicand[7]}},multiplicand }   ;
                signOfMulB  <=  multiplicand[7] ;
                mulB        <=  { 1'b1,multiplier[6:0] }    ;
            end
            else if( shifting == 1'b1 )
            begin
                mulA    <=  { mulA[14:0],1'b0 } ;
                mulB    <=  { 1'b0,mulB[7:1] }  ;
            end
            // accumulator
            if( lockMuls == 1'b1 )
            begin
                accumulator <=  16'b0   ;
            end
            else if( adding == 1'b1 )
            begin
                accumulator <=  accumulator + mulA  ;
            end
            //out_enOut
            out_enOut   <=  ending  ;
            //out_product
            if( ending == 1'b1 )
            begin
                if( signOfMulB == 1'b0 )
                begin
                    out_product <=  accumulator ;
                end
                else
                begin
                    out_product <=  accumulator - mulA  ;
                end
            end 
        end
    end
    
    always@( current_state , enIn , mulB )
    begin
        out_busy    <=  1'b0    ;
        lockMuls    <=  1'b0    ;
        adding      <=  1'b0    ;
        shifting    <=  1'b0    ;
        ending      <=  1'b0    ;
        
        case( current_state )
            IDLE    :
                begin
                    if( enIn == 1'b1 )
                    begin
                        next_state  <=  S_CALC  ;
                        lockMuls    <=  1'b1    ;
                    end
                    else
                    begin
                        next_state  <=  IDLE    ;
                    end
                end
            S_CALC  :
                begin
                    out_busy    <=  1'b1    ;
                    shifting    <=  1'b1    ;
                    adding      <=  mulB[0] ;
                    if( mulB == 8'b1 )
                    begin
                        ending      <=  1'b1    ;
                        next_state  <=  IDLE    ;
                    end
                    else
                    begin
                        next_state  <=  S_CALC  ;
                    end
                end
            default :
                begin
                    next_state  <=  IDLE    ;
                end
        endcase
        
    end
       
    assign  product =   out_product ;
    assign  busy    =   out_busy    ;
    assign  enOut   =   out_enOut   ;
    
endmodule

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/04/09 17:40:06
// Design Name: 
// Module Name: tb_mults_5
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module tb_mults_5();

        reg         sys_clk         ;
        reg         sys_rst_n       ;
        reg  [7:0]  multiplicand    ;
        reg  [7:0]  multiplier      ;
        reg         enIn            ;
        wire        enOut           ;
        wire        busy            ;
        wire [15:0] product         ;
    
    initial
    begin
        sys_clk         =   1'b0    ;
        sys_rst_n       =   1'b0    ;
        multiplicand    =   8'b0    ;
        multiplier      =   8'b0    ;
        enIn            =   1'b0    ;
        #100
        sys_rst_n       =   1'b1    ;
        
        multiplicand    =   8'd20   ;    
        multiplier      =   8'd40   ;
        enIn            =   1'b1    ;
        #10
        enIn            =   1'b0    ;
        #1000
        
        multiplicand    =   8'd40   ;    
        multiplier      =   8'd80   ;
        enIn            =   1'b1    ;
        #10
        enIn            =   1'b0    ;
        #1000
        
        multiplicand    =   -8'd20  ;    
        multiplier      =   8'd40   ;
        enIn            =   1'b1    ;
        #10
        enIn            =   1'b0    ;
        #1000
        
        multiplicand    =   -8'd40  ;    
        multiplier      =   8'd80   ;
        enIn            =   1'b1    ;
        #10
        enIn            =   1'b0    ;
        #1000
        
        $finish ;
        
    end    
        
    always #5 sys_clk = ~sys_clk    ;

    mults_5     mults_5_inst
    (
        .sys_clk                (sys_clk),
        .sys_rst_n              (sys_rst_n),
        .multiplicand           (multiplicand),
        .multiplier             (multiplier),
        .enIn                   (enIn),
        .enOut                  (enOut),
        .busy                   (busy),
        .product                (product)
    );

endmodule

测试发现,只能用于无符号乘,负数乘法错误,正数乘法正确

9、补码乘法之BOOTH乘法器

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

相关推荐
szxinmai主板定制专家2 小时前
基于STM32+FPGA的地震数据采集器软件设计,支持RK3568+FPGA平台
arm开发·fpga开发
傻智智爱吃糖6 小时前
Xilinx 7系列fpga在线升级和跳转
fpga开发
hahaha601612 小时前
ARINC818协议(二)
网络·fpga开发
weixin_4672092812 小时前
ZYNQ系列SOC或FPGA常用核心电源方案选型
fpga开发
Seele Vollerei❀1 天前
FPGA-DDS技术的波形发生器
fpga开发
2201_755183711 天前
【FPGA】——DDS信号发生器设计
fpga开发
芯语新源1 天前
designware IP如何被FPGA综合
fpga开发
Born_t0ward1 天前
基于FPGA实现BPSK 调制
fpga开发
且听风吟5671 天前
深度为16,位宽8bit的单端口SRAM——学习记录
学习·fpga开发
鸡精拌饭1 天前
FPAG IP核调用小练习
fpga开发