HDLBits:在線學習Verilog(六 · Problem 25-29)
本系列文章將和讀者一起巡禮數字邏輯在線學習網站 HDLBits 的教程與習題,並附上解答和一些作者個人的理解,相信無論是想 7 分鐘精通 Verilog,還是對 Verilog 和數電知識查漏補缺的同學,都能從中有所收穫。
附上傳送門:Module fadd - HDLBits
Problem 25: Adder 2(Module fadd)
牛刀小試
在本題中,您將描述一個具有兩級層次結構的電路。在top_module中,實例化兩個add16模塊(已為您提供),每個add16中實例化16個add1實例(此模塊需要您編寫)。所以,您需要描述兩個模塊:top_module和add1。
與Problem 24: Adder 1(Module add)一樣,提供給您一個執行16bit的加法的模塊。您需要實例化兩個16bit加法模塊來實現32bit加法器。一個add16計算加法結果的低16位,另一個計算結果的高16位。您的32位加法器同樣不需要處理進位輸入(假設為0)和進位輸出(無需進位)信號。
如下圖所示,將add16模塊連接在一起,給出的add16模塊如下:
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
在每個add16中,實例化了16個全加器(add1,未給出,需要您自己寫出)去執行加法操作。您必須編寫具有以下聲明的完整全加器(add1):
module add1 ( input a, input b, input cin, output sum, output cout );
回憶一下,全加器計算a+b+cin(三個信號均為1bit)的結果(sum)和進位(carry-out)。
總之,本題中一共有三個模塊:
1、top_module:包含兩個16位加法器的頂級模塊;
2、add16(已給出):一個16bit的加法器,由16個全加器構成;
3、add(未給出):1bit全加器
注意:在您提交的代碼中如果缺少add1,您將收到一條如下的錯誤提示:
Error (12006): Node instance "user_fadd[0].a1" instantiates undefined entity "add1".
小提示:全加器的邏輯表達式
解答與分析
module top_module (
input [31:0] a,
input [31:0] b,
output [31:0] sum
);//
wire carry;
add16 a1(a[15:0],b[15:0],1b0,sum[15:0],carry);
add16 a2(a[31:16],b[31:16],carry,sum[31:16],);
endmodule
module add1 ( input a, input b, input cin, output sum, output cout );
assign sum = a ^ b ^ cin;
assign cout = a&b | a&cin | b&cin;
endmodule
本體與上一題實現的功能是一樣的,就是要多實現一個1bit全加器,如果不小心把16bit的全加器實現的話會提示模塊聲明多次的錯誤:
Error (10228): Verilog HDL error at tb_modules.sv(1): module "add16" cannot be declared more than once File:
Problem 26: Carry-select adder (Module cseladd)
上一個練習中(Problem 25: Adder 2(Module fadd))實現的加法器應該叫做行波進位加法器(RCA: Ripple-Carry Adder)。這種加法器的缺點是計算進位輸出的延遲是相當慢的(最壞的情況下,來自於進位輸入)。並且如果前一級加法器計算完成之前,後一級加法器不能開始計算。這又使得加法器的計算延遲變大。
牛刀小試
這次來實現一個改進型的加法器,如下圖所示。第一級加法器保持不變,第二級加法器實現兩個,一個假設進位為0,另一個假設進位為1。然後使用第一級結果和2選一選擇器來選擇哪一個結果是正確的。
在本題中,您將獲得與上一練習相同的模塊add16,它將兩個16bit數和進位輸入相加,併產生16bit的結果和進位輸出。您必須實例化其中的三add16來構建進位選擇加法器,同時實現16bit的2選1選擇器來選擇結果。
將模塊如下圖所示連在一起。提供的模塊add16如下:
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
解答與分析
module top_module(
input [31:0] a,
input [31:0] b,
output [31:0] sum
);
wire carry;
wire [31:16] sum0;
wire [31:16] sum1;
add16 al(a[15:0],b[15:0],1b0,sum[15:0],carry);
add16 ah0(a[31:16],b[31:16],1b0,sum0[31:16],);
add16 ah1(a[31:16],b[31:16],1b1,sum1[31:16],);
assign sum[31:16] = carry?sum1:sum0;
endmodule
如果學過數字集成電路的進位鏈的話應該知道這是選擇進位加法器(CSA: Carry-Select Adder),相對於上一題的行波進位(也叫逐級進位,逐位進位)加法器延遲小一半左右,但是比增多了50%的邏輯資源。
Problem 27: Adder–subtractor (Module addsub)
加減法器可以由加法器來構建,可以對其中一個數取相反數(對輸入數據取反,然後加1)。最終結果是一個可以執行以下兩個操作的電路: 和 。如果您想要更詳細地了解該電路的工作原理,請參閱維基百科。
牛刀小試
如下圖所示構建加減法器,您需要實例化兩次下面給出的16bit加法器模塊:
module add16 ( input[15:0] a, input[15:0] b, input cin, output[15:0] sum, output cout );
當sub為1時,使用32位的異或門對B進行取反。(這也可以被視為b[31:0]與sub複製32次相異或,請參閱複製運算符Problem 17: Replication operator(Vector4))。同時sub信號連接到加法器的進位。