博主最近在學習加法器乘法等等相關知識,在學習乘法器booth編碼加Wallace樹壓縮時,發現在壓縮部分積的時候用到了進位保留加法器(Carry Save Adder),博主對這種加法器不是很理解,而且拖了好久,我一直認為進位保留加法器就是一般的串行加法器,今天終於有所理解,在這里給大家分享一下。
首先,我們舉個例子,對於四位無符號數1011與1110相乘,我們可以得到如下式子:
1 0 1 1 x 1 1 1 0 ------------------------------ 0 0 0 0 PP1 1 0 1 1 PP2 1 0 1 1 PP3 1 0 1 1 PP4 ------------------------------
乘積項中間結果有4個:PP1、PP2、PP3、PP4。由於進位保存加法器只能進行三個數的相加,因而可采用兩個進位保存加法器實現。第一個進位保存加法器實現PP1、PP2、PP3的加法,第二個進位保存加法器將PP3和上一級的S和C相加。最終通過一個並行加法器輸出積。計算過程如下:
第一個進位保存加法器 PP1: 0 0 0 0 PP2: 1 0 1 1 0 PP3: 1 0 1 1 0 0 --------------------------------------- sum1 1 1 1 0 1 0 c1 0 0 0 1 0 0 第二個進位保存加法器 carry_in: 1 0 1 1 0 0 0 sum1 0 1 1 1 0 1 0 c1 0 0 0 1 0 0 0 --------------------------------------- sum2: 1 1 0 1 0 1 0 c2: 0 0 1 1 0 0 0 並行加法器: sum2: 1 1 0 1 0 1 0 c2: 0 1 1 0 0 0 0 --------------------------------------- result 1 0 0 1 1 0 1 0
我們注意到,在參與下一級運算的過程中,由於進位要用於高位的求和,故c1,c2均應左移一位求。算出來的結果為:10011010(154)。
所謂“進位保留”,便是進位不進上去,只在本位之間計算。
基於Wallace樹的4位乘法器實現Verilog代碼如下所示:
module wallace_multiplier(
input [3:0] a,
input [3:0] b,
output [7:0] result
);
wire [7:0] pp1;
wire [7:0] pp2;
wire [7:0] pp3;
wire [7:0] pp4;
wire [7:0] sum1;
wire [7:0] carry1;
wire [7:0] sum2;
wire [7:0] carry2;
assign pp1 = b[0] ? a : 'd0;
assign pp2 = b[1] ? a : 'd0;
assign pp3 = b[2] ? a : 'd0;
assign pp4 = b[3] ? a : 'd0;
assign result = sum2 + (carry2 << 1);
carry_save_adder u1_carry_save_adder(
pp1 ,
pp2 << 1'b1,
pp3 << 2'd2,
sum1 ,
carry1
);
carry_save_adder u2_carry_save_adder(
pp4 << 2'd3 ,
sum1 ,
carry1 << 1'b1,
sum2 ,
carry2
);
endmodule
module carry_save_adder
#(
parameter DATA_WIDTH = 7
)
(
input [DATA_WIDTH:0] a,
input [DATA_WIDTH:0] b,
input [DATA_WIDTH:0] cin,
output [DATA_WIDTH:0] sum,
output [DATA_WIDTH:0] cout
);
assign sum = a ^ b ^ cin;
assign cout = a & b | (a | b) & cin;
endmodule
testbench:
`timescale 1ns / 1ns
module wallace_multiplier_tb();
reg [3:0] a;
reg [3:0] b;
wire[7:0] result;
wallace_multiplier u_wallace_multiplier(
.a (a ),
.b (b ),
.result (result )
);
initial begin
a = 4'b0010;
b = 4'b0110;
#10;
a = 4'b0001;
b = 4'b1000;
#10;
a = 4'b1010;
b = 4'b0111;
#10;
a = 4'b1110;
b = 4'b0010;
#10;
a = 4'b1111;
b = 4'b1111;
#10;
a = 4'b0110;
b = 4'b1001;
end
endmodule
仿真結果如下圖:
以上就是Wallace樹型4位乘法器的實現了,我認為關鍵在於進位保留加法器(Carry Save Adder)的理解,希望能給大家帶來幫助。