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

numText 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 
发表评论

您必须 [ 登录 ] 才能发表留言!

相关文章