4位加法器的设计代码verilog_HDLBits:在线学习Verilog(六 · Problem 25-29)
本系列文章將和讀者一起巡禮數(shù)字邏輯在線學習網(wǎng)站 HDLBits 的教程與習題,并附上解答和一些作者個人的理解,相信無論是想 7 分鐘精通 Verilog,還是對 Verilog 和數(shù)電知識查漏補缺的同學,都能從中有所收獲。
附上傳送門:Module fadd - HDLBits
Problem 25: Adder 2(Module fadd)
牛刀小試
在本題中,您將描述一個具有兩級層次結構的電路。在top_module中,實例化兩個add16模塊(已為您提供),每個add16中實例化16個add1實例(此模塊需要您編寫)。所以,您需要描述兩個模塊:top_module和add1。
與Problem 24: Adder 1(Module add)一樣,提供給您一個執(zhí)行16bit的加法的模塊。您需要實例化兩個16bit加法模塊來實現(xiàn)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,未給出,需要您自己寫出)去執(zhí)行加法操作。您必須編寫具有以下聲明的完整全加器(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],1'b0,sum[15:0],carry);add16 a2(a[31:16],b[31:16],carry,sum[31:16],);endmodulemodule 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本體與上一題實現(xiàn)的功能是一樣的,就是要多實現(xiàn)一個1bit全加器,如果不小心把16bit的全加器實現(xiàn)的話會提示模塊聲明多次的錯誤:
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))實現(xiàn)的加法器應該叫做行波進位加法器(RCA: Ripple-Carry Adder)。這種加法器的缺點是計算進位輸出的延遲是相當慢的(最壞的情況下,來自于進位輸入)。并且如果前一級加法器計算完成之前,后一級加法器不能開始計算。這又使得加法器的計算延遲變大。
牛刀小試
這次來實現(xiàn)一個改進型的加法器,如下圖所示。第一級加法器保持不變,第二級加法器實現(xiàn)兩個,一個假設進位為0,另一個假設進位為1。然后使用第一級結果和2選一選擇器來選擇哪一個結果是正確的。
在本題中,您將獲得與上一練習相同的模塊add16,它將兩個16bit數(shù)和進位輸入相加,并產(chǎn)生16bit的結果和進位輸出。您必須實例化其中的三add16來構建進位選擇加法器,同時實現(xiàn)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],1'b0,sum[15:0],carry);add16 ah0(a[31:16],b[31:16],1'b0,sum0[31:16],);add16 ah1(a[31:16],b[31:16],1'b1,sum1[31:16],);assign sum[31:16] = carry?sum1:sum0;endmodule如果學過數(shù)字集成電路的進位鏈的話應該知道這是選擇進位加法器(CSA: Carry-Select Adder),相對于上一題的行波進位(也叫逐級進位,逐位進位)加法器延遲小一半左右,但是比增多了50%的邏輯資源。
Problem 27: Adder–subtractor (Module addsub)
加減法器可以由加法器來構建,可以對其中一個數(shù)取相反數(shù)(對輸入數(shù)據(jù)取反,然后加1)。最終結果是一個可以執(zhí)行以下兩個操作的電路:
和 。如果您想要更詳細地了解該電路的工作原理,請參閱維基百科。牛刀小試
如下圖所示構建加減法器,您需要實例化兩次下面給出的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信號連接到加法器的進位。
小提示:異或門也可以看作是可編程的非門,其中一個輸入控制是否應該反轉另一個。 以下兩個電路都是異或門:
解答與分析
module top_module(input [31:0] a,input [31:0] b,input sub,output [31:0] result );wire [31:0] b_n;wire carry;assign b_n = b^{32{sub}};add16 a0(a[15:0],b_n[15:0],sub,result[15:0],carry);add16 a1(a[31:16],b_n[31:16],carry,result[31:16],);endmodule學過數(shù)字邏輯電路的應該知道的小常識,減去一個數(shù)等于加上這個數(shù)的補碼(就是題中的按位取反再加1)。
到這里關于模塊層次的學習就結束了,下一題開始,我們進位過程塊的學習。
Problem 28: Always blocks(combinational) (Alwaysblock1)
我們知道數(shù)字電路是由導線連接的邏輯門組成,因此任何電路都可以表示為module和assign語句的某種組合。但是,有時候這不是描述電路最簡便的方法。過程塊(比如always塊)提供了一種用于替代assign語句描述電路的方法。
有兩種always塊是可以綜合出電路硬件的:
綜合邏輯:always @(*) 時序邏輯:always @(posedge clk)組合always塊相當于assign語句,因此組合電路存在兩種表達方法。具體使用哪個主要取決于使用哪個更方便。過程塊內(nèi)的代碼與外部的assign代碼不同。過程塊中可以使用更豐富的語句(比如if-then,case),但不能包含連續(xù)賦值*。但也引入了一些非直觀的錯誤。(*過程連續(xù)賦值確實可以存在,但與連續(xù)賦值有些不同,并且不可綜合)
例如,assign和組合always塊描述相同的電路。兩者均創(chuàng)造出了相同的組合邏輯電路。只要任何輸入(右側)改變值,兩者都將重新計算輸出。
assign out1 = a & b | c ^ d; always @(*) out2 = a & b | c ^ d;對于組合always塊,敏感變量列表總是使用(*)。如果把所有的輸入都列出來也是可以的,但容易出錯的(可能少列出了一個),并且在硬件綜合時會忽略您少列了一個,仍按原電路綜合。 但仿真器將會按少列一個來仿真,這導致了仿真與硬件不匹配。(在SystemVerilog中,使用always_comb)
牛刀小試
使用assign語句和組合always塊來構建與門。(因為賦值語句和組合always相同,仿真器檢測不出來你使用了那種方法,所以沒有辦法強制你使用這兩種方法,但是你會這里練習的,對吧?......)(譯者注:作者還是很調(diào)皮的)
解答與分析
// synthesis verilog_input_version verilog_2001 module top_module(input a, input b,output wire out_assign,output reg out_alwaysblock );assign out_assign = a & b;always@(*)out_alwaysblock = a & b;endmodule好像沒什么分析的,照著上面的講解抄就行。
Problem 29: Always blocks(clocked) (Alwaysblock2)
對于硬件綜合來說,存在兩種always塊:
組合邏輯:always @(*) 時序邏輯:always @(posedge clk)時序always塊也會像組合always塊一樣生成一系列的組合電路,但同時在組合邏輯的輸出生成了一組觸發(fā)器(或寄存器)。該輸出在下一個時鐘上升沿(posedge clk)后可見,而不是之前的立即可見。
阻塞性賦值和非阻塞性賦值
在Verilog中有以下三種賦值方法:
連續(xù)賦值(assign x=y;):不能在過程塊內(nèi)使用; 過程阻塞性賦值(x=y;):只能在過程塊中使用; 過程費阻塞性復制(x<=y):只能在過程塊內(nèi)使用。在組合always塊中,使用阻塞性賦值。在時序always塊中,使用非阻塞性賦值。具體為什么對設計硬件用處不大,還需要理解Verilog模擬器如何跟蹤事件(譯者注:的確是這樣,記住組合用阻塞性,時序用非阻塞性就可以了)。不遵循此規(guī)則會導致極難發(fā)現(xiàn)非確定性錯誤,并且在仿真和綜合出來的硬件之間存在差異。
牛刀小試
使用assign語句,組合always塊和時序always塊這三種方式來構建異或門。 請注意,時鐘always塊生成了與另外兩個不同的電路,多了一個觸發(fā)器,因此輸出會有一定的延遲。
解答與分析
module top_module(input clk,input a,input b,output wire out_assign,output reg out_always_comb,output reg out_always_ff );assign out_assign = a ^ b;always@(*) out_always_comb = a ^ b;always@(posedge clk) out_always_ff <= a ^ b;endmodule從仿真的波形圖可以看出,out_always_ff比其他兩個輸出延遲了一個時鐘周期,這就是非阻塞性賦值帶來的。
PS:本系列課程的題號是從0開始的,與網(wǎng)站1不符,望周知。
總結
以上是生活随笔為你收集整理的4位加法器的设计代码verilog_HDLBits:在线学习Verilog(六 · Problem 25-29)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何选择精品文献如何挑选精品电脑
- 下一篇: 通讯故障_掌握PLC必备知识,人机界面和