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
endmodule
1、积的宽度讨论
2、基于无符号乘法器的原码乘法器
3、基于无符号乘法器的补码乘法器
4、补码乘法之 “ 正被乘数 ” 乘以 “ 正乘数 ”
5、补码乘法之 “ 负被乘数 ” 乘以 “ 正乘数 ”
6、补码乘法之 “ 正被乘数 ” 乘以 “ 负乘数 ”
7、补码乘法之 “ 负被乘数 ” 乘以 “ 负乘数 ”
8、补码乘法之加性分解乘法器
9、补码乘法之BOOTH乘法器
10、利用特殊资源实现整数乘法