动态

详情 返回 返回

verilog實現32位有符號流水乘法器 - 动态 详情

verilog實現32位有符號流水乘法器

1.4bit乘法流程

1.無符號X無符號二進制乘法器

以下為4bit乘法器流程(2X6)

	0 0 0 0 0 0 1 0     (2)
X	0 0 0 0 0 1 1 0     (6)
    --------------------- 
	0 0 0 0 0 0 0 0     (0)
	0 0 0 0 0 1 0 0     (4)
	0 0 0 0 1 0 0 0     (8)
	0 0 0 0 0 0 0 0     (0)
	0 0 0 0 0 0 0 0     (0)
	0 0 0 0 0 0 0 0     (0)
	0 0 0 0 0 0 0 0     (0)
	0 0 0 0 0 0 0 0     (0)
    ---------------------	
	0 0 0 0 1 1 0 0     (12)
注:4bit乘4bit的乘法器,其最大結果位寬為8,即4+4,所用在計算的時候,需要將乘數和被乘數通過符號位擴展到8bit,當然,對於無符號乘法來説,擴展的沒有作用,但是對於有符號來説,是必須的,設計的模塊為有符號和無符號通用的寄存器,所用建議無符號也進行位寬擴展。

2.有符號X有符號二進制乘法器

以下為4bit乘法器流程(-2 X -6)

	1 1 1 1 1 1 1 0     (-2)
 X	1 1 1 1 1 0 1 0     (-6)
    --------------------- 
	0 0 0 0 0 0 0 0		
	1 1 1 1 1 1 0 0		
	0 0 0 0 0 0 0 0		
	1 1 1 1 0 0 0 0		
	1 1 1 0 0 0 0 0     
	1 1 0 0 0 0 0 0     
	1 0 0 0 0 0 0 0     
	0 0 0 0 0 0 0 0     
    ---------------------	
	0 0 0 0 1 1 0 0     (12) 

3.有符號X無符號二進制乘法器

 	1 1 1 1 1 1 1 0     (-2)
 X	0 0 0 0 0 1 1 0     (6)
    --------------------- 
	0 0 0 0 0 0 0 0		
 	1 1 1 1 1 1 0 0		
	1 1 1 1 1 0 0 0		
	0 0 0 0 0 0 0 0		
	0 0 0 0 0 0 0 0     
	0 0 0 0 0 0 0 0     
	0 0 0 0 0 0 0 0     
	0 0 0 0 0 0 0 0     
    ---------------------	
	1 1 1 1 0 1 0 0     (-12)

4.無符號X有符號二進制乘法器

 	0 0 0 0 0 0 1 0     (2)
 X	1 1 1 1 1 0 1 0     (-6)
    --------------------- 
	0 0 0 0 0 0 0 0		
 	0 0 0 0 0 1 0 0		
	0 0 0 0 0 0 0 0		
	0 0 0 1 0 0 0 0		
	0 0 1 0 0 0 0 0     
	0 1 0 0 0 0 0 0     
	1 0 0 0 0 0 0 0     
	0 0 0 0 0 0 0 0     
    ---------------------	
	1 1 1 1 0 1 0 0     (-12)

2.流程簡化

由上面4種情況可以總結出一個規律,符號不影響計算流程,隻影響截位位置。

​ 例如無符號X有符號二進制乘法器為例:bin(00000010) = dec(2),但是對於bin(11111010)將其當作有符號數來説為dec(-6),當作無符號來説為dec(250),即dec(2)*dec(250)的結果只取低8位的話,當作有符號數即為bin(11110100) = dec(-12)。那麼以為着計算有符號數乘法的時候,只需要將其當作無符號數進行計算,最後控制截位位置就可以計算有符號計算器。

那麼以下將對16bit乘法進行簡化,以-1000 X -1200

1.位寬擴展

dec(-1000) = bin(11111111111111111111110000011000) = dec(4294966296)
dec(-1200) = bin(11111111111111111111101101010000) = dec(4294966096)

2.乘數指數分解

dec(4294966096) = 1*2^31 + 1*2^30 + 1*2^29 + 1*2^28 + 
1*2^27 + 1*2^26 + 1*2^25 + 1*2^24 + 1*2^23 + 1*2^22 + 
1*2^21 + 1*2^20 + 1*2^19 + 1*2^18 + 1*2^17 + 1*2^16 + 
1*2^15 + 1*2^14 + 1*2^13 + 1*2^12 + 1*2^11 + 0*2^10 + 
1*2^9 + 1*2^8 + 0*2^7 + 1*2^6 + 0*2^5 + 1*2^4 + 0*2^3 + 
0*2^2 + 0*2^1 + 0*2^0
則:
dec(4294966296) * dec(4294966096) = dec(4294966296)*2^31 + dec(4294966296)*2^30 + 
dec(4294966296)*2^29 + dec(4294966296)*2^28 + dec(4294966296)*2^27 +
dec(4294966296)*2^26 + dec(4294966296)*2^25 + dec(4294966296)*2^24 + 
dec(4294966296)*2^23 + dec(4294966296)*2^22 + dec(4294966296)*2^21 + 
dec(4294966296)*2^20 + dec(4294966296)*2^19 + dec(4294966296)*2^18 + 
dec(4294966296)*2^17 + dec(4294966296)*2^16 + dec(4294966296)*2^15 + 
dec(4294966296)*2^14 + dec(4294966296)*2^13 + dec(4294966296)*2^12 + 
dec(4294966296)*2^11 + 0*2^10 + dec(4294966296)*2^9 + dec(4294966296)*2^8 + 
0*2^7 + dec(4294966296)*2^6 + 0*2^5 + dec(4294966296)*2^4 + 0*2^3 + 
0*2^2 + 0*2^1 + 0*2^0

這公式看着複雜一大堆,但是如果把指數看作左移運算符,那麼,乘法就轉化為左移和加法了。

3.流水線加法

假設num = a + b + c + d + e + f + g + h,將其轉化為流水線加法

a
a
b
b
c
c
d
d
e
e
f
f
g
g
h
h
dig0
dig0
dig1
dig1
dig2
dig2
dig3
dig3
dig4
dig4
dig5
dig5
dig6
dig6
num
num
Text is not SVG - cannot display

4.按需截位

dec(4294966296) * dec(4294966096) = hex(FFFFF76800124F80)
其中16bit乘16bit的乘法器,最大位寬為32bit,取後32bit,即
hex(00124F80) = dec(1200000)

一個完整的乘法流程就算完成了。

3.verilog實現

16位有符號乘法器代碼

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/28 22:54:41
// Design Name: 
// Module Name: multiplier_16
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 16位有符號乘法器
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module multiplier_16
#(  
    parameter A_WIDTH  = 16 ,//數據A的位寬
    parameter A_SIGNED = 1  ,//數據A是否有符號
    parameter B_WIDTH  = 16 ,//數據B的位寬
    parameter B_SIGNED = 1  //數據B是否有符號
)
(
    input       clk ,
    input       rst ,
    input   [A_WIDTH-1:0]   A,
    input   [B_WIDTH-1:0]   B,
    output  [A_WIDTH + B_WIDTH - 1:0]   P
    );
    wire [32-1:0]    C;
    wire [32-1:0]    D;
    assign C = A_SIGNED?{{32-A_WIDTH{A[A_WIDTH-1]}},A}:{{32-A_WIDTH{1'b0}},A};
    assign D = B_SIGNED?{{32-B_WIDTH{B[B_WIDTH-1]}},B}:{{32-B_WIDTH{1'b0}},B};
//*************************************************
    genvar  i0;
    reg [31:0]  sum0 [15:0];
    generate
        for (i0 = 0;i0<=15 ;i0=i0+1 ) begin
            always @(posedge clk)begin
                if(rst)begin
                    sum0[i0]    <= 0;
                end
                else begin
                    case({D[2*i0+1],D[2*i0]})
                        2'b00:begin
                            sum0[i0]    <= 0 <<  (2*i0);
                        end
                        2'b01:begin
                            sum0[i0]    <= (0 + C)  <<  (2*i0);
                        end
                        2'b10:begin
                            sum0[i0]    <= ({C[30:0],1'b0} + 0)  <<  (2*i0);
                        end
                        2'b11:begin
                            sum0[i0]    <= ({C[30:0],1'b0} + C)  <<  (2*i0);
                        end                        
                    endcase
                end
            end
        end       
    endgenerate
    genvar  i1;
    reg [31:0]  sum1 [7:0];
    generate
        for (i1 = 0;i1<=7 ;i1=i1+1 ) begin
            always @(posedge clk)begin
                if(rst)begin
                    sum1[i1]    <= 0;
                end
                else begin
                    sum1[i1]    <= sum0[2*i1] + sum0[2*i1+1];
                end
            end
        end       
    endgenerate
    genvar  i2;
    reg [31:0]  sum2 [3:0];
    generate
        for (i2 = 0;i2<=3 ;i2=i2+1 ) begin
            always @(posedge clk)begin
                if(rst)begin
                    sum2[i2]    <= 0;
                end
                else begin
                    sum2[i2]    <= sum1[2*i2] + sum1[2*i2+1];
                end
            end
        end       
    endgenerate
    genvar  i3;
    reg [31:0]  sum3 [1:0];
    generate
        for (i3 = 0;i3<=1 ;i3=i3+1 ) begin
            always @(posedge clk)begin
                if(rst)begin
                    sum3[i3]    <= 0;
                end
                else begin
                    sum3[i3]    <= sum2[2*i3] + sum2[2*i3+1];
                end
            end
        end       
    endgenerate
    reg [31:0]  sum4;
    always @(posedge clk)begin
        if(rst)begin
            sum4    <= 0;
        end
        else begin
            sum4    <= sum3[0] + sum3[1];
        end
    end
    assign P = sum4;
endmodule
32位有符號乘法器代碼

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/09/11 22:21:12
// Design Name: 
// Module Name: multiplier_pp
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
module multiplier
#(  
    parameter A_WIDTH  = 32 ,//數據A的位寬
    parameter A_SIGNED = 1  ,//數據A是否有符號
    parameter B_WIDTH  = 32 ,//數據B的位寬
    parameter B_SIGNED = 1  //數據B是否有符號
)
(
    input       clk ,
    input       rst ,
    input   [A_WIDTH-1:0]   A,
    input   [B_WIDTH-1:0]   B,
    output  [A_WIDTH + B_WIDTH - 1:0]   P
    );
    wire [64-1:0]    C;
    wire [64-1:0]    D;
    assign C = A_SIGNED?{{64-A_WIDTH{A[A_WIDTH-1]}},A}:{{64-A_WIDTH{1'b0}},A};
    assign D = B_SIGNED?{{64-B_WIDTH{B[B_WIDTH-1]}},B}:{{64-B_WIDTH{1'b0}},B};
//*************************************************
    genvar  i0;
    reg [63:0]  sum0 [31:0];
    generate
        for (i0 = 0;i0<=31 ;i0=i0+1 ) begin
            always @(posedge clk)begin
                if(rst)begin
                    sum0[i0]    <= 0;
                end
                else begin
                    case({D[2*i0+1],D[2*i0]})
                        2'b00:begin
                            sum0[i0]    <= 0 <<  (2*i0);
                        end
                        2'b01:begin
                            sum0[i0]    <= (0 + C)  <<  (2*i0);
                        end
                        2'b10:begin
                            sum0[i0]    <= ({C[62:0],1'b0} + 0)  <<  (2*i0);
                        end
                        2'b11:begin
                            sum0[i0]    <= ({C[62:0],1'b0} + C)  <<  (2*i0);
                        end                        
                    endcase
                end
            end
        end       
    endgenerate
    genvar  i1;
    reg [63:0]  sum1 [15:0];
    generate
        for (i1 = 0;i1<=15 ;i1=i1+1 ) begin
            always @(posedge clk)begin
                if(rst)begin
                    sum1[i1]    <= 0;
                end
                else begin
                    sum1[i1]    <= sum0[2*i1] + sum0[2*i1+1];
                end
            end
        end       
    endgenerate
    genvar  i2;
    reg [63:0]  sum2 [7:0];
    generate
        for (i2 = 0;i2<=7 ;i2=i2+1 ) begin
            always @(posedge clk)begin
                if(rst)begin
                    sum2[i2]    <= 0;
                end
                else begin
                    sum2[i2]    <= sum1[2*i2] + sum1[2*i2+1];
                end
            end
        end       
    endgenerate
    genvar  i3;
    reg [63:0]  sum3 [3:0];
    generate
        for (i3 = 0;i3<=3 ;i3=i3+1 ) begin
            always @(posedge clk)begin
                if(rst)begin
                    sum3[i3]    <= 0;
                end
                else begin
                    sum3[i3]    <= sum2[2*i3] + sum2[2*i3+1];
                end
            end
        end       
    endgenerate
    genvar  i4;
    reg [63:0]  sum4 [1:0];
    generate
        for (i4 = 0;i4<=1 ;i4=i4+1 ) begin
            always @(posedge clk)begin
                if(rst)begin
                    sum4[i4]    <= 0;
                end
                else begin
                    sum4[i4]    <= sum3[2*i4] + sum3[2*i4+1];
                end
            end
        end       
    endgenerate
    reg [63:0]  sum5;
    always @(posedge clk)begin
        if(rst)begin
            sum5    <= 0;
        end
        else begin
            sum5    <= sum4[0] + sum4[1];
        end
    end
    assign P = sum5;
endmodule 

Add a new 评论

Some HTML is okay.