一买喧、半加器與全加器
半加器電路是指對(duì)兩個(gè)輸入數(shù)據(jù)位相加,輸出一個(gè)結(jié)果位和進(jìn)位憔杨,沒有進(jìn)位輸入的加法器電路鸟赫。
圖1.1 半加器真值表
半加器verilog代碼:
module half_adder(
input a,b,
output s,cout
);
assign {cout,s} = a + b;
endmodule
全加器電路與半加器電路相比,多了進(jìn)位輸入消别。
圖1.2 全加器真值表
全加器verilog代碼:
module full_adder(
input a,b,cin,
output s,cout
);
assign {cout,s} = a + b + cin;
endmodule
二抛蚤、多bit加法器的設(shè)計(jì)
有了上節(jié)全加器的設(shè)計(jì)基礎(chǔ),可以展開設(shè)計(jì)多bit加法器寻狂。Nbit加法器需要N個(gè)全加器岁经,低位全加器的進(jìn)位輸出作為高位全加器的進(jìn)位輸入,以此類推蛇券。最低位全加器的進(jìn)位輸入作為整個(gè)模塊進(jìn)位輸入蒿偎,最高位進(jìn)位輸出作為整個(gè)模塊的進(jìn)位輸出。這種設(shè)計(jì)方法叫作行波進(jìn)位法加法器(Ripple Carry Adder怀读,RCA)。
圖2.1 行波進(jìn)位法
行波進(jìn)位法加法器verilog代碼:
module rca #(width=4)(
input [width-1:0] a,b,
input cin,
output [width-1:0]s,
output cout
);
wire [width:0]cin_temp;
assign cin_temp[0]=cin;
assign cout=cin_temp[width];
genvar i;
generate
for(i=0;i<width;i++)begin
full_adder inst(
.a(a[i]),
.b(b[i]),
.cin(cin_temp[i]),
.s(s[i]),
.cout(cin_temp[i+1])
);
end
endgenerate
endmodule
行波進(jìn)位加法器具有布局簡單骑脱、設(shè)計(jì)方便等優(yōu)點(diǎn)菜枷,但高位的計(jì)算必須要等待低位運(yùn)算結(jié)束才可以得到自己的進(jìn)位輸入,開始運(yùn)算叁丧,當(dāng)運(yùn)算位數(shù)較大時(shí)會(huì)造成很大的運(yùn)算延遲啤誊,影響器件工作效率岳瞭。
圖2.2 全加器結(jié)構(gòu)
針對(duì)上述問題,超前進(jìn)位加法器(Carry-Lookahead Adder蚊锹,CLA)可以在低位運(yùn)算之前便可以得到各位的進(jìn)位輸入。如圖2.2所示,某一位的全加器進(jìn)位輸出可以用其輸入信號(hào)直接推算出來并作為下一位的進(jìn)位輸入掌挚,以此類推掂器,這一位的進(jìn)位輸入也可以由前一位全加器的輸入信號(hào)推算得到,直到最低位丢烘。
推算公式為:
所以柱宦!根據(jù)加法器模塊的當(dāng)前輸入信號(hào)便可以直接推算出每個(gè)全加器的進(jìn)位輸入!只需要先計(jì)算出各位的生成信號(hào)與傳播信號(hào)播瞳,再計(jì)算出每個(gè)全加器的進(jìn)位輸入掸刊,便可以直接進(jìn)行運(yùn)算,將N級(jí)延遲轉(zhuǎn)化為固定級(jí)數(shù)延遲赢乓。具體的分析參考資料1的博主分析的很好忧侧,強(qiáng)烈推薦。
超前進(jìn)位加法器verilog代碼:
module cla #(width=4)(
input [width-1:0]a,b,
input cin,
output [width-1:0]s,
output cout
);
wire [width:0]cin_temp;
wire [width-1:0]g,p;
assign cin_temp[0]=cin;
assign cout=cin_temp[width];
genvar i;
generate
for(i=0;i<width;i++)begin
g[i]=a[i]&b[i];
p[i]=a[i]|b[i];
cin_temp[i+1]=g[i]|(cin_temp[i]&p[i]);
full_adder inst(
.a(a[i]),
.b(b[i]),
.cin(cin_temp[i]),
.s(s[i]),
.cout()
);
end
endgenerate
endmodule
三牌芋、加減法器設(shè)計(jì)
已知蚓炬,減去一個(gè)數(shù)等于加上這個(gè)數(shù)的補(bǔ)碼,所以在加法器的基礎(chǔ)上姜贡,將輸入?yún)?shù)稍作修改试吁,便可以實(shí)現(xiàn)一個(gè)共用結(jié)構(gòu)的加減法模塊。
以行波進(jìn)位法為例楼咳,修改后的加減法器verilog代碼:
module aos #(width=4)(
input [width-1:0] a,b,
input cin,
input sub,//sub=1為減法熄捍,=0為加法
output [width-1:0]s,
output cout
);
wire [width:0]cin_temp,b_temp;
assign cin_temp[0]=cin^sub;//減法時(shí)看作被借位,sub_temp[0]作為補(bǔ)碼~b+1的+1母怜,當(dāng)被借位時(shí)cin=1余耽,cin_temp[0]=0,當(dāng)未被借位時(shí)cin=0,cin_temp[0]=1作為正常補(bǔ)碼苹熏。
assign cout=cin_temp[width]^sub;//減法時(shí)看作借位碟贾,運(yùn)算結(jié)果為向高位借位后的值,若有需要將cout看作符號(hào)位求補(bǔ)碼即為答案
assign b_temp={width{sub}}^b; //減法時(shí)進(jìn)行取反
genvar i;
generate
for(i=0;i<width;i++)begin
full_adder inst(
.a(a[i]),
.b(b_temp[i]),
.cin(cin_temp[i]),
.s(s[i]),
.cout(cin_temp[i+1])
);
end
endgenerate
endmodule