无符号整数的乘法
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、利用特殊资源实现整数乘法