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,将其转化为流水线加法
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