版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第七章數(shù)字電路設(shè)計(jì)原則與 VerilogHDL難點(diǎn)解析7.1時(shí)序電路基礎(chǔ)7.2異步電路中的同步處理方法7.3阻塞賦值與非阻塞賦值7.4優(yōu)秀HDL代碼風(fēng)格7.5TestBench編寫(xiě)本章小結(jié) 7.1時(shí)序電路基礎(chǔ)
如今在FPGA上實(shí)現(xiàn)大規(guī)模的邏輯電路工作頻率越來(lái)越高。為了保證設(shè)計(jì)的穩(wěn)定可靠性,必須要理解影響數(shù)字電路運(yùn)行頻率以及可靠性的因素。只有理解了這些因素的存在原因,才有辦法提高代碼設(shè)計(jì)的質(zhì)量,以達(dá)到提高邏輯電路運(yùn)行頻率的目的。下面通過(guò)簡(jiǎn)單的數(shù)字電路時(shí)序模型來(lái)分析影響數(shù)字電路的基本參數(shù)。首先對(duì)于純組合邏輯電路來(lái)說(shuō),其邏輯功能塊的輸出僅僅與當(dāng)前的輸入值有關(guān)系。其電路延時(shí)分析也非常簡(jiǎn)單,只考慮輸入到輸出的信號(hào)延時(shí)Tdelay。但是影響Tdelay時(shí)間的因素比較多,比如,不同的器件輸入到輸出的延時(shí)時(shí)間不同,不同的工藝條件以及在不同的環(huán)境下,Tdelay的時(shí)間也不同。所以組合邏輯電路的延時(shí)參數(shù)是不固定的,研究組合邏輯電路的延時(shí)沒(méi)有實(shí)際意義。對(duì)于絕大部分的電路來(lái)說(shuō),輸出不僅取決于當(dāng)前的輸入值,也取決于原先的輸入值。也就是說(shuō),電路具有記憶功能。這屬于同步時(shí)序電路,其基本時(shí)序模型如圖7-1所示。tCLK是時(shí)鐘的最小周期,tCQ是寄存器固有的時(shí)鐘輸出延時(shí),tLOGIC是同步元件之間的組合邏輯延遲,tNET是網(wǎng)線(xiàn)的延遲,tSU是寄存器固有的時(shí)鐘建立時(shí)間,tCLK_SKEW是兩個(gè)DFF之間的時(shí)鐘扭曲,同步時(shí)序電路由寄存器和組合邏輯組成,系統(tǒng)中所有的寄存器均在一個(gè)全局時(shí)鐘的控制下工作。以下三個(gè)重要的時(shí)序參數(shù)與寄存器有關(guān)。圖7-1基本同步時(shí)序電路模型
1.建立時(shí)間tSU
建立時(shí)間tSU是在時(shí)鐘翻轉(zhuǎn)(對(duì)于正沿觸發(fā)寄存器為0→1的翻轉(zhuǎn))之前數(shù)據(jù)輸入(D)必須有效的時(shí)間。
2.保持時(shí)間tHOLD
保持時(shí)間tHOLD是在時(shí)鐘邊沿之后數(shù)據(jù)輸入必須仍然有效的時(shí)間。
假設(shè)建立和保持時(shí)間都滿(mǎn)足,那么輸入端D處的數(shù)據(jù)則在最壞情況下的傳播延時(shí)(tNET)之后被賦值到了輸出端q,如圖7-2所示。圖7-2同步寄存器的建立時(shí)間、保持時(shí)間以及傳播延遲的定義
3.最高時(shí)鐘頻率fMAX
在熟悉了建立時(shí)間、保持時(shí)間以及傳播延遲的基本概念之后,下面通過(guò)這三個(gè)基本參數(shù)來(lái)推導(dǎo)時(shí)鐘的最高頻率fMAX。對(duì)于同步時(shí)序邏輯電路,對(duì)時(shí)鐘激勵(lì)做出響應(yīng)的開(kāi)關(guān)事件是同時(shí)發(fā)生的,但是運(yùn)行結(jié)果必須等到下一個(gè)時(shí)鐘翻轉(zhuǎn)時(shí)才能進(jìn)入到下一級(jí)。也就是說(shuō),只有在當(dāng)前所有的計(jì)算都已經(jīng)完成并且系統(tǒng)開(kāi)始閑置時(shí)下一輪的操作才能開(kāi)始,因此,為了保證時(shí)序電路數(shù)據(jù)采集和處理的正確性,時(shí)鐘周期tCLK必須能容納電路中任何一級(jí)的最長(zhǎng)延時(shí)。假設(shè)該組合邏輯的最長(zhǎng)延時(shí)等于tLOGIC,那么時(shí)序電路正確工作要求的最小時(shí)鐘為(7-1)其中tNET為傳輸延遲,tCQ是寄存器固有的時(shí)鐘輸出延時(shí),那么通過(guò)公式(7-1)很容易得到系統(tǒng)的最高頻率,常用fMAX表示:(7-2)我們假設(shè)寄存器的固有最小延時(shí)時(shí)間為tCQregister,那么為了保證時(shí)序電路正常工作,還需要如下的約束:≥tHOLD
(7-3)7.1.1同步電路的時(shí)序分析
1.時(shí)鐘扭曲(ClockSkew)
時(shí)鐘扭曲指同源時(shí)鐘到達(dá)兩個(gè)不同寄存器時(shí)鐘端的時(shí)間差別。時(shí)鐘扭曲主要是由時(shí)鐘路徑的靜態(tài)不匹配以及時(shí)鐘在負(fù)載上的差異造成的。時(shí)鐘扭曲造成的是時(shí)鐘相位的偏移,并不會(huì)造成時(shí)鐘周期的變化。時(shí)鐘扭曲包括正扭曲和負(fù)扭曲,如圖7-3所示為時(shí)鐘的正扭曲。圖7-3時(shí)鐘正扭曲下面依然以圖7-1所示的時(shí)序模型來(lái)分析。假如考慮兩個(gè)時(shí)鐘之間的扭曲(Skew),那么電路的時(shí)鐘周期的公式就變成了下式:(7-4)令并且令條件1:如果,則。這說(shuō)明信號(hào)相對(duì)時(shí)鐘有效沿到達(dá)觸發(fā)器的D端的時(shí)間超過(guò)了tSU,滿(mǎn)足建立時(shí)間要求;反之,則不滿(mǎn)足。
條件2:如果,則。這說(shuō)明在時(shí)鐘有效沿到達(dá)之后,信號(hào)能維持足夠長(zhǎng)的時(shí)間,滿(mǎn)足保持時(shí)間要求;反之,則不滿(mǎn)足。
由條件1和條件2得出,當(dāng)時(shí),tHOLD受影響;當(dāng)時(shí),tSU受影響;最好的辦法就是讓幾乎為0。所以在FPGA中設(shè)計(jì)同步電路,必須要保證時(shí)鐘的扭曲非常小,所有的時(shí)鐘都要來(lái)自全局時(shí)鐘驅(qū)動(dòng)。因?yàn)槿謺r(shí)鐘信號(hào)在FPGA內(nèi)部作有特殊處理,能夠保證時(shí)鐘信號(hào)的良好特性。圖7-4異步電路時(shí)序模型
2.時(shí)鐘抖動(dòng)(ClockJitter)
時(shí)鐘抖動(dòng)是指在芯片的某一個(gè)給定點(diǎn)上時(shí)鐘周期發(fā)生暫時(shí)的變化。即時(shí)鐘周期在每個(gè)不同的周期上可以縮短或者加長(zhǎng)。最常用的抖動(dòng)參數(shù)稱(chēng)為周期抖動(dòng)和周期間抖動(dòng)。周期抖動(dòng)一般比較大,也比較確定,常由于第三方原因造成,如干擾、電源、噪聲等;周期間抖動(dòng)由環(huán)境因素造成,滿(mǎn)足高斯分布,一般難以跟蹤。常用避免時(shí)鐘抖動(dòng)的方法有:
(1)采用全局時(shí)鐘資源,增強(qiáng)時(shí)鐘的抗干擾能力,從而改善時(shí)鐘抖動(dòng);
(2)在FPGA系統(tǒng)硬件設(shè)計(jì)時(shí)考慮時(shí)鐘的抗干擾布局布線(xiàn)。7.1.2異步電路和同步電路的區(qū)別
異步電路和同步電路的主要區(qū)別在于時(shí)鐘。下面對(duì)異步電路和同步電路各自的特點(diǎn)進(jìn)行比較。
1.異步電路
(1)電路的核心邏輯是組合電路,比如異步的FIFO/RAM讀寫(xiě)信號(hào)、地址譯碼信號(hào)等
電路。
(2)電路的輸出不依賴(lài)于某一個(gè)時(shí)鐘,也就是說(shuō),不是由時(shí)鐘信號(hào)驅(qū)動(dòng)觸發(fā)器產(chǎn)生的。
(3)異步電路非常容易產(chǎn)生毛刺,且易受環(huán)境的影響,不利于器件的移植。
2.同步電路
(1)電路的核心邏輯是由各種各樣的觸發(fā)器實(shí)現(xiàn)的,所以比較容易使用寄存器的異步復(fù)位/置位端,以使整個(gè)電路有一個(gè)確定的初始狀態(tài)。
(2)整個(gè)電路是由時(shí)鐘沿驅(qū)動(dòng)的。
(3)以觸發(fā)器為主體的同步時(shí)序電路可以很好地避免毛刺的影響,使設(shè)計(jì)更可靠。
(4)同步時(shí)序電路利于器件移植,因?yàn)榄h(huán)境以及器件工藝對(duì)同步電路的影響幾乎可以不考慮。
(5)同步電路可以容易地組織流水線(xiàn),提高芯片的運(yùn)行速率。
(6)同步電路可以很好地利用先進(jìn)的設(shè)計(jì)工具,如靜態(tài)時(shí)序分析工具等,為設(shè)計(jì)者提供最大便利條件,便于對(duì)電路錯(cuò)誤進(jìn)行分析,加快設(shè)計(jì)進(jìn)度。 綜上所述,同步時(shí)序電路更適合現(xiàn)代FPGA設(shè)計(jì)。隨著FPGA/CPLD的規(guī)模越來(lái)越大,設(shè)計(jì)者無(wú)需像以前一樣經(jīng)常使用行波計(jì)數(shù)器或者異步脈沖生成器等典型的異步邏輯設(shè)計(jì)方式,以節(jié)約設(shè)計(jì)所消耗的面積資源,而新型FPGA豐富的邏輯資源、強(qiáng)大的EDA綜合實(shí)現(xiàn)工具為時(shí)序驅(qū)動(dòng)優(yōu)化提供了良好的條件?,F(xiàn)代FPGA推薦使用同步時(shí)序邏輯設(shè)計(jì)。7.1.3同步時(shí)序設(shè)計(jì)規(guī)則
進(jìn)行同步時(shí)序設(shè)計(jì)時(shí)應(yīng)該遵循以下幾個(gè)規(guī)則:
(1)盡可能在整個(gè)設(shè)計(jì)中只使用一個(gè)主時(shí)鐘,同時(shí)只使用同一個(gè)時(shí)鐘沿;主時(shí)鐘走FPGA全局網(wǎng)絡(luò),因?yàn)镕PGA器件中的全局時(shí)鐘資源是專(zhuān)門(mén)為降低時(shí)鐘的抖動(dòng)和扭曲而設(shè)計(jì)的。在XilinxFPGA中,采用專(zhuān)門(mén)的時(shí)鐘管理模塊(CMT)來(lái)管理全局時(shí)鐘資源,有效地提高了時(shí)鐘的質(zhì)量。
(2)在FPGA設(shè)計(jì)中,所有輸入、輸出信號(hào)均應(yīng)通過(guò)寄存器寄存;寄存器接口當(dāng)作異步接口考慮。
(3)當(dāng)全部電路不能用同步電路設(shè)計(jì)時(shí),也就是說(shuō)需要多個(gè)時(shí)鐘來(lái)實(shí)現(xiàn)時(shí),原則上將電路分成多個(gè)局部同步電路來(lái)設(shè)計(jì),各局部電路接口之間采用異步電路來(lái)考慮。
(4)電路設(shè)計(jì)中需要考慮時(shí)序余量,當(dāng)設(shè)計(jì)無(wú)法滿(mǎn)足理論最高頻率時(shí),芯片就會(huì)無(wú)法可靠工作。
(5)電路中所有寄存器、狀態(tài)機(jī)在單板上電復(fù)位時(shí),應(yīng)處于一個(gè)已知的狀態(tài)。 7.2異步電路中的同步處理方法
7.2.1時(shí)鐘的同步處理
時(shí)鐘是數(shù)字電路中所有信號(hào)的參考。沒(méi)有時(shí)鐘或者時(shí)鐘信號(hào)處理不得當(dāng),都會(huì)影響系統(tǒng)的性能甚至功能。所以在一般情況下,我們?cè)谕粋€(gè)設(shè)計(jì)中使用同一個(gè)時(shí)鐘源,當(dāng)系統(tǒng)中有多個(gè)時(shí)鐘時(shí),需要根據(jù)不同情況選擇不同的處理方法。
(1)當(dāng)有多個(gè)時(shí)鐘在同一個(gè)數(shù)字電路中,且有一個(gè)時(shí)鐘(假設(shè)為SysClk)的頻率大于其它時(shí)鐘頻率的兩倍以上時(shí),在接口部分就必須要對(duì)其他時(shí)鐘進(jìn)行同步化處理,將其處理為與SynClk同步的時(shí)鐘信號(hào)。這樣處理的好處是:①便于處理電路內(nèi)部時(shí)序;②時(shí)鐘間邊界條件只在接口部分電路進(jìn)行處理。
一般的時(shí)鐘同步電路如圖7-5所示。
圖7-5時(shí)鐘同步電路實(shí)質(zhì)上,時(shí)鐘采樣的同步處理方法就是上升沿提取電路。上升沿提取的輸出信息中帶有系統(tǒng)時(shí)鐘的信息,有利于保障電路的可靠性和可移植性。
(2)當(dāng)系統(tǒng)中所有時(shí)鐘沒(méi)有一個(gè)時(shí)鐘頻率達(dá)到其他時(shí)鐘頻率的兩倍時(shí),無(wú)法滿(mǎn)足采樣定理,在接口部分就必須對(duì)其他時(shí)鐘和數(shù)據(jù)通過(guò)FIFO進(jìn)行隔離,并將其他時(shí)鐘信息轉(zhuǎn)換為和系統(tǒng)時(shí)鐘同步的允許信號(hào)。比如,在高速的數(shù)據(jù)采集系統(tǒng)中,AD的采集時(shí)鐘頻率往往比較高,大于系統(tǒng)時(shí)鐘頻率的一半以上,這時(shí)采用同步化處理無(wú)法滿(mǎn)足時(shí)序設(shè)計(jì)。
(3)系統(tǒng)中多個(gè)時(shí)鐘之間存在數(shù)據(jù)互相采樣,如圖7-6所示的情況。clk1和clk2來(lái)自不同的時(shí)鐘源,該電路既可能出現(xiàn)在同一芯片里,也可能出現(xiàn)在不同的芯片里,但是都存在同樣的危險(xiǎn)性。由于時(shí)鐘源不同,對(duì)于寄存器reg2和reg3來(lái)說(shuō),在同一時(shí)刻,極有可能一個(gè)認(rèn)為reg1輸出為“1”,另一個(gè)認(rèn)為是“0”,必然導(dǎo)致電路結(jié)果的錯(cuò)誤。對(duì)于這種電路,必須先在reg1之后添加一個(gè)觸發(fā)器,用clk2的時(shí)鐘沿進(jìn)行采樣,然后用該觸發(fā)器的輸出經(jīng)過(guò)組合邏輯輸出到reg2和reg3中,如圖7-7所示。圖7-6多時(shí)鐘同步模型圖7-7多時(shí)鐘同步處理改進(jìn)后的模型
(4)由于時(shí)鐘建立—?保持時(shí)間的限制,F(xiàn)PGA設(shè)計(jì)中應(yīng)盡量避免采用多時(shí)鐘網(wǎng)絡(luò),或者盡量減少時(shí)鐘的個(gè)數(shù)。在FPGA對(duì)ASIC芯片進(jìn)行驗(yàn)證時(shí),必須要將時(shí)鐘網(wǎng)絡(luò)進(jìn)行簡(jiǎn)化,因?yàn)镕PGA內(nèi)部時(shí)鐘資源不像ASIC一樣具有很強(qiáng)的穿透性和靈活性。圖7-8為一個(gè)含有危險(xiǎn)的多級(jí)時(shí)鐘的例子,多路選擇器的輸入是clk和clk的2分頻,時(shí)鐘由SEL引腳控制的多路選擇器輸出,在這兩個(gè)時(shí)鐘均為邏輯“1”且SEL的狀態(tài)改變時(shí),存在靜態(tài)冒險(xiǎn)競(jìng)爭(zhēng)現(xiàn)象。所以為了確保電路的正常工作,需要進(jìn)行修改。修改之后的電路如圖7-9所示。圖7-8多級(jí)時(shí)鐘處理存在競(jìng)爭(zhēng)冒險(xiǎn)模塊圖7-9修改之后的多級(jí)時(shí)鐘處理模塊7.2.2接口電路處理
FPGA經(jīng)常作為粘合邏輯,與別的芯片之間進(jìn)行數(shù)據(jù)交換。為了保證電路的數(shù)據(jù)接口能夠穩(wěn)定地傳輸數(shù)據(jù),需要專(zhuān)用的接口電路來(lái)處理外部芯片和FPGA之間良好的接口時(shí)序,如圖7-10所示。圖7-10接口電路功能示意圖接口電路為FPGA和外部芯片之間架起了一座橋梁。其功能主要體現(xiàn)在如下幾個(gè)方面:
(1)接口電路隔離了外圍電路和內(nèi)部電路,它并不改變外圍電路的時(shí)序和相位要求,而是要力求保證內(nèi)部電路的處理更加理想化和理論化。
(2)接口電路使得內(nèi)部電路有統(tǒng)一的系統(tǒng)時(shí)鐘,如果外部處理器接口有非系統(tǒng)時(shí)鐘,則需要進(jìn)行處理。
(3)為了使內(nèi)部電路接收的信號(hào)更穩(wěn)定,需要對(duì)有可能的干擾進(jìn)行濾波。
(4)如果雙向數(shù)據(jù)傳輸,則需要提供三態(tài)控
1.三態(tài)門(mén)電路
三態(tài)門(mén)電路指邏輯門(mén)的輸出除了高、低之外還有第三種狀態(tài)—高阻狀態(tài)。高阻態(tài)相當(dāng)于隔斷狀態(tài),它對(duì)于下一級(jí)輸出電路沒(méi)有任何影響,正因?yàn)槿绱?,三態(tài)門(mén)在擴(kuò)展邏輯接口功能時(shí)非常有用。在總線(xiàn)數(shù)據(jù)傳輸上,三態(tài)門(mén)可以有效控制同時(shí)只有一個(gè)從設(shè)備占有總線(xiàn),每個(gè)從設(shè)備通過(guò)oe使能選通;如果沒(méi)有選通,就處于高阻態(tài),相當(dāng)于沒(méi)有接在總線(xiàn)上,不會(huì)產(chǎn)生任何影響。三態(tài)門(mén)的邏輯符號(hào)和真值表如圖4-1所示。
在接口電路中,使用三態(tài)門(mén)可以很輕松地將外圍的雙向電路引入內(nèi)部電路,使內(nèi)部電路中沒(méi)有三態(tài)電路。另外,三態(tài)輸出在一般情況下輸出高阻,只有必須輸出時(shí)才輸出數(shù)據(jù),避免與外圍電路發(fā)生沖突。使用VerilogHDL描述雙向數(shù)據(jù)傳輸?shù)谋硎救缦拢?/p>
inputdatain,clk,ena;
inoutdata,
//使用三態(tài)門(mén)處理數(shù)據(jù)輸出
always@(posedgeclk,ena)
if(ena)
data<=datain;
else
data<=‘Z’;
//對(duì)于數(shù)據(jù)輸入,直接賦值就可以
assigndata=data_in;
2.透明鎖存器(Latch)
鎖存器是非常危險(xiǎn)的電路,因?yàn)樗鼪](méi)有確定的初始狀態(tài),而且輸出隨著輸入變化,這就意味著毛刺可以通過(guò)鎖存器。若該電路與其他D觸發(fā)器電路相連,則會(huì)影響這些觸發(fā)器的建立、保持時(shí)間。所以除非在特殊情況下,否則我們不會(huì)使用鎖存器來(lái)鎖存。在同步數(shù)字電路中,應(yīng)力求避免不小心產(chǎn)生鎖存器,如在4.3節(jié)中講述的if-else語(yǔ)句以及case語(yǔ)句使用中避免鎖存器的描述。但是,鎖存器在以下條件同時(shí)滿(mǎn)足的情況下可以使用:
(1)要鎖存的數(shù)據(jù)在數(shù)據(jù)標(biāo)志(如讀信號(hào))的上升沿和下降沿之間可能變化;
(2)內(nèi)部電路在數(shù)據(jù)標(biāo)志的上升沿或下降沿之間需要使用要鎖存的數(shù)據(jù);
(3)內(nèi)部電路在數(shù)據(jù)標(biāo)志結(jié)束后可能還需要使用要鎖存的數(shù)據(jù)。
在51單片機(jī)與FPGA/CPLD接口電路中,對(duì)于單片機(jī)數(shù)據(jù)接口讀時(shí)序和寫(xiě)時(shí)序電路分別如圖7-11和7-12所示。為了正確接收數(shù)據(jù),在FPGA/CPLD方需要采用鎖存器在A(yíng)LE信號(hào)下降沿將地址鎖存,然后當(dāng)WR讀信號(hào)為低的情況下,從數(shù)據(jù)端口接收數(shù)據(jù),同時(shí)在RD信號(hào)為高的情況下,將數(shù)據(jù)寫(xiě)到51單片機(jī)數(shù)據(jù)總線(xiàn)上。圖7-1151單片機(jī)讀數(shù)據(jù)時(shí)序電路圖7-1251單片機(jī)寫(xiě)數(shù)據(jù)時(shí)序電路
【程序7-1】透明鎖存器實(shí)例。
modulemcu_interface(
input
wireclk,
input
wirereset,
input
wirewr_n,rd_n,ale,
input
wire[7:0]datai_in,
inout
wire[7:0]data,
output
wire[7:0]data_out1,
output
wire[7:0]data_out2);
reg[7:0]addr;
//通過(guò)鎖存器鎖存地址
always@(negedgeale,negedgereset)
if(!reset)
addr<=8‘h0;
else
addr<=data;
//根據(jù)地址讀數(shù)據(jù)
always@(posedgeclk,negedgerst)
if(!rst)
begin
dataout1<=8'h0;
dataout2<=8'h0;
end
else
if(!wr)
case(address)
begin
8'b00000000:data_out1<=data;
8'b00000001:data_ou2<=data;
end
endcase
//根據(jù)地址向單片機(jī)寫(xiě)數(shù)據(jù)
always@(posedgeclk)
if(!rd)
if(address)
8'b00000010:data<=data_in;
else
data<=8'hZ;
endmodule
3.移位寄存器
FPGA的最大優(yōu)勢(shì)在于并行處理,所以串并轉(zhuǎn)換和并串轉(zhuǎn)換在FPGA設(shè)計(jì)中應(yīng)用非常廣泛。在普通的設(shè)計(jì)中,采用移位寄存器構(gòu)成的串—并/并—串轉(zhuǎn)換接口電路來(lái)處理FPGA的并行處理速度問(wèn)題。一般情況下,內(nèi)部電路的處理速度較慢,通常使用移位寄存器進(jìn)行速率變換。移位寄存器非常簡(jiǎn)單,在此不作冗述。
4.濾波電路
當(dāng)輸入信號(hào)不穩(wěn)定或有干擾的情況下,可以使用濾波器過(guò)濾不需要的信號(hào)。一般情況下根據(jù)采集時(shí)鐘和過(guò)濾對(duì)象的速率倍數(shù)選擇不同的濾波器形式。下面提供兩種常用的濾波器電路形式,如圖7-13和7-14所示,第一種濾波電路適合1位的信號(hào)濾波,而且濾波采樣的次數(shù)并不多的情況下使用,其RTL源碼如程序7-2所示。可以根據(jù)輸入信號(hào)的特點(diǎn),對(duì)濾波器進(jìn)行不同的修改和調(diào)整。圖7-13濾波電路(一)
【程序7-2】濾波電路。
modulefilter(
inputwireclk,
inputwired,
outputregq);
regd_temp1,d_temp2,d_temp3;
wired_or,d_and;
always@(posedgeclk)
begin
d_temp1<=d;
d_temp2<=d_temp1;
d_temp3<=d_temp2;
if(q)
q<=d_or;
else
q<=d_and;
end
assignd_or=d|d_temp1|d_temp2|d_temp3;
assignd_and=d&d_temp1&d_temp2&d_temp3;
endmodule
圖7-14濾波電路(二)
5.異步FIFO模塊
異步FIFO模塊在接口電路中應(yīng)用非常廣泛。使用它是跨時(shí)鐘域傳輸數(shù)據(jù)的良好解決方法。異步FIFO模塊的結(jié)構(gòu)如圖7-15所示,數(shù)據(jù)輸入輸出分別在輸入時(shí)鐘和輸出時(shí)鐘的驅(qū)動(dòng)下進(jìn)行操作,所以異步FIFO緩存結(jié)構(gòu)為跨時(shí)鐘域傳輸提供了很好的隔離作用,只要FIFO緩存空間大小設(shè)置合理,就能良好地控制兩個(gè)時(shí)鐘域之間數(shù)據(jù)的正確傳輸。圖7-15異步FIFO模塊的結(jié)構(gòu)示意圖7.2.3全局信號(hào)處理
1.時(shí)鐘信號(hào)、異步清零、置位信號(hào)為組合邏輯輸出
組合電路最大的缺點(diǎn)就是對(duì)電平敏感,因此非常容易產(chǎn)生毛刺。而組合邏輯的微小毛刺如果放置在異步全局信號(hào)或者時(shí)鐘信號(hào)上,極易造成時(shí)序電路發(fā)生錯(cuò)誤。所以針對(duì)這些非常重要的信號(hào),應(yīng)盡量采用同步電路。如果一定要采用組合邏輯,就必須用卡諾圖嚴(yán)格地分析時(shí)序電路,確定徹底消除競(jìng)爭(zhēng)與冒險(xiǎn)后,方可引入到時(shí)序電路中使用。針對(duì)下面兩種情況分別說(shuō)明如何避免組合邏輯對(duì)時(shí)序電路的影響。
1)時(shí)鐘信號(hào)、異步清零、置位信號(hào)來(lái)源于多個(gè)信號(hào)中的一個(gè)
如圖7-16所示電路,同一個(gè)時(shí)鐘源,必須要通過(guò)組合邏輯控制其通斷,觸發(fā)器的時(shí)鐘由clk和sel信號(hào)相與之后產(chǎn)生,目的是通過(guò)控制觸發(fā)器的時(shí)鐘的通斷來(lái)控制觸發(fā)器的輸出。這時(shí)clock和sel不是嚴(yán)格同步的,則有可能在觸發(fā)器的時(shí)鐘管腳產(chǎn)生毛刺。而在FPGA中,觸發(fā)器對(duì)毛刺是非常敏感的,很有可能導(dǎo)致觸發(fā)器的誤操作。為了達(dá)到相同的目的,可以將選擇信號(hào)sel與觸發(fā)器的使能端連接,以避免觸發(fā)器的時(shí)鐘端引入毛刺,同時(shí)又能夠達(dá)到所需要的功能。改善之后的電路如圖7-17所示。圖7-16原時(shí)鐘選擇控制電路圖7-17改善之后的時(shí)鐘選擇控制電路
2)通過(guò)組合邏輯對(duì)觸發(fā)器的時(shí)鐘在多個(gè)時(shí)鐘中選擇一個(gè)
在通信系統(tǒng)中,往往為了保證單板的可靠工作,會(huì)作備份電路;需要備份時(shí)鐘、復(fù)位、置位等信號(hào),通過(guò)控制信號(hào)對(duì)主電路信號(hào)和備份電路信號(hào)進(jìn)行切換,如圖7-18所示電路。為了在clka和clkb兩個(gè)時(shí)鐘中二選一,采用了直接組合邏輯實(shí)現(xiàn)。然而,組合電路由于不同的路徑而延遲不同,所以在電路的時(shí)鐘輸出很容易產(chǎn)生毛刺。顯然此法不妥。為了避免毛刺,正確的方法是對(duì)控制切換的sel信號(hào)分別用兩個(gè)觸發(fā)器進(jìn)行同步化,這樣在輸出時(shí)鐘時(shí)就不會(huì)再出現(xiàn)毛刺。如圖7-19所示為改善之后的時(shí)鐘切換電路。圖7-18原時(shí)鐘切換電路圖7-19改善之后的時(shí)鐘切換電路對(duì)于改善之后的時(shí)鐘切換電路,其時(shí)序圖如圖7-20所示。其中,regA代表接clka的觸發(fā)器,其對(duì)應(yīng)的與門(mén)輸出為regA_clk;同樣定義regB和regB_clk。顯然,當(dāng)regA和regB前后“偏移”在一定的范圍之內(nèi)時(shí),outclk不會(huì)出現(xiàn)毛刺。圖7-20改善之后的時(shí)鐘切換電路的時(shí)序圖
2.使用自我清除、自我置位和自我鐘控的寄存器
對(duì)于自我清除、自我置位,最好通過(guò)組合邏輯將其轉(zhuǎn)變成對(duì)輸入端數(shù)據(jù)的置位與清除,從而提高電路的可靠性;對(duì)于自我鐘控電路,盡量使用觸發(fā)器的使能端達(dá)到鐘控的目的。
下面舉例介紹自我清除和自我置位電路。如圖7-21所示為自我清除電路圖,當(dāng)輸出端均為“1”時(shí),電路復(fù)位,雖然使能端復(fù)位延遲了一個(gè)時(shí)鐘周期,但是消除了產(chǎn)生毛刺的隱患。如圖7-22所示為自我置位電路圖,當(dāng)輸出端均為“0”時(shí),電路置位,這樣輸出端置位延遲了一個(gè)時(shí)鐘周期,但是消除了毛刺。圖7-21自我清除電路圖圖7-22自我置位電路圖
3.時(shí)鐘信號(hào)、異步清零信號(hào)、置位信號(hào)有外部輸入,本身輸入信號(hào)有毛刺
對(duì)于此種情況,采取的辦法就是對(duì)有毛刺的時(shí)鐘、置位、清零信號(hào)使用內(nèi)部觸發(fā)器進(jìn)行鎖存,使其同步化。 7.3阻塞賦值與非阻塞賦值
VerilogHDL語(yǔ)言中,對(duì)于always模塊,有兩種賦值方式:阻塞賦值和非阻塞賦值。對(duì)于初學(xué)者,往往迷惑這兩種賦值方式的用法,在第四、五章中,總結(jié)過(guò)以下三條簡(jiǎn)單的
原則:
(1)將電路中的組合邏輯和寄存器進(jìn)行分離;
(2)為寄存器選擇合適的中間變量,在always語(yǔ)句內(nèi)部用非阻塞賦值;
(3)在描述組合邏輯的always模塊中用阻塞賦值。
7.3.1節(jié)舉例分析了兩種賦值語(yǔ)句的用法。7.3.1概述
1.阻塞賦值(BlockingAssignment)
阻塞賦值的基本描述格式為
[變量]=[邏輯表達(dá)式];
阻塞賦值在執(zhí)行時(shí),右端表達(dá)式執(zhí)行并賦值到左邊變量,不會(huì)受任何情況打斷。所以在本次賦值結(jié)束之前它“阻塞”了當(dāng)前其他的賦值任務(wù)。阻塞賦值的操作和C語(yǔ)言中的變量賦值非常相似。
2.非阻塞賦值(NonblockingAssignment)
非阻塞賦值的基本描述格式為
[變量]<=[邏輯表達(dá)式];
非阻塞賦值行為有些細(xì)微之處比較難以理解。最好從硬件角度來(lái)理解,always模塊可以被認(rèn)為是純硬件模塊,當(dāng)always模塊被激活時(shí),非阻塞賦值的右側(cè)表達(dá)式就開(kāi)始執(zhí)行;當(dāng)always模塊所有表達(dá)式執(zhí)行結(jié)束之后,所有執(zhí)行結(jié)果才賦值到左側(cè)變量中。之所以稱(chēng)為“非阻塞”,就是在本條賦值語(yǔ)句執(zhí)行的過(guò)程中,其他賦值語(yǔ)句也可以執(zhí)行。
3.舉例
為了更形象地理解阻塞與非阻塞賦值,以三輸入與門(mén)電路來(lái)介紹這兩種賦值方法得到的結(jié)果的差異。程序7-3采用阻塞賦值,程序7-4采用非阻塞賦值描述。
【程序7-3】阻塞賦值舉例。
moduleblock_example
(
input
wirea,b,c,
output
regy
);
always@*
begin
y=a;
y=y&b;
y=y&c;
end
endmodule
【程序7-4】非阻塞賦值舉例。
moduleand_nonblock
(
inputwirea,b,c,
outputregy
);
always@*
begin
y<=a;
y<=y&b;
y<=y&c;
end
endmodule
分析:根據(jù)非阻塞賦值的原則,賦值語(yǔ)句前兩條就沒(méi)有起作用,實(shí)際上程序7-4相當(dāng)于:
always@*
y<=y&c;
顯然,如果我們是想描述y賦值為a、b和c相與的值,則該描述不符合要求。7.3.2組合邏輯電路中的賦值描述
前面舉例屬于極端情況。除了默認(rèn)值外,大部分組合電路都會(huì)多次賦值同一變量。阻塞賦值和非阻塞賦值雖然都可以用來(lái)描述同一電路,但是有微弱的差別。下面以1位比較器舉例來(lái)解釋這種差別。程序7-5采用阻塞賦值。
【程序7-5】阻塞賦值實(shí)現(xiàn)1位比較器。
moduleeq1_block
(
input
wirei0,i1,
output
regeq
);
regp0,p1;
always@(i0,i1) //i0和i1在敏感量列表當(dāng)中
//語(yǔ)句描述的順序非常關(guān)鍵
begin
p0=~i0&~i1;
p1=i0&i1;
eq=p0|p1;
end
endmodule
分析:程序7-5中,敏感量列表中包含i0和i1,只要這兩個(gè)變量有一個(gè)發(fā)生改變,都會(huì)激活always語(yǔ)句,那么p0、p1和eq就會(huì)順序賦值,最終eq賦值就會(huì)被更新。但是這三條語(yǔ)句的描述順序非常關(guān)鍵。假如將最后一條語(yǔ)句提前,則程序如下:
always@(i0,i1)
begin
eq=p0|p1;
p0=~i0&~i1;
p1=i0&i1;
end
【程序7-6】非阻塞賦值實(shí)現(xiàn)1位比較器。
moduleeq1_non_block
(
input
wirei0,i1,
output
regeq
);
regp0,p1;
always@(i0,i1,p0,p1) //p0,p1依然在敏感量列表中
//描述順序無(wú)關(guān)緊要
begin
p0<=~i0&~i1;
p1<=i0&i1;
eq<=p0|p1;
end
endmodule
分析:p0和p1包含在敏感量列表中。當(dāng)i0或者i1有所變化時(shí),always模塊被激活;p0和p1在第一個(gè)時(shí)鐘節(jié)拍結(jié)束時(shí)賦值。由于eq值為基于p0和p1原來(lái)保持值的賦值,所以eq不變。當(dāng)前賦值結(jié)束時(shí),always模塊重新被激活。由于p0和p1被改變(這就是p0和p1放在敏感量列表中的原因),因而eq變量在第二個(gè)時(shí)鐘節(jié)拍被賦予了新值。從以上分析可知,即使將以上語(yǔ)句的順序發(fā)生改變,也不會(huì)影響最終結(jié)果,因?yàn)閑q的賦值以及always模塊的激活與這些語(yǔ)句的順序并沒(méi)關(guān)系。
總結(jié):雖然兩種描述方法都可以描述同一電路,但是兩個(gè)電路的結(jié)果是有區(qū)別的,采用非阻塞賦值法描述仿真所花費(fèi)的時(shí)間更長(zhǎng)一些,電路輸出結(jié)果在時(shí)序上也有微弱差別。鑒于此,我們有這么一條原則:“在組合邏輯電路描述中采用阻塞賦值”。7.3.3時(shí)序電路賦值描述
就單獨(dú)一個(gè)寄存器來(lái)說(shuō),阻塞賦值和非阻塞賦值都可以描述存儲(chǔ)單元,如DFF可以描述為
always@(posedgeclk)
q<=d;
也可以描述為
always@(posedgeclk)
q=d;但是當(dāng)設(shè)計(jì)中存在多個(gè)寄存器描述單元時(shí),就會(huì)有細(xì)微的差別。假設(shè)有兩個(gè)寄存器在每個(gè)時(shí)鐘的上升沿進(jìn)行數(shù)據(jù)交換,則采用阻塞賦值描述如下:
always@(posedgeclk)
a=b;
always@(posedgeclk)
b=a;在時(shí)鐘的上升沿,兩個(gè)always語(yǔ)句同時(shí)被激活并且并行執(zhí)行。一個(gè)時(shí)鐘節(jié)拍后兩條語(yǔ)句執(zhí)行結(jié)束。按照verilog語(yǔ)法標(biāo)準(zhǔn),兩個(gè)always語(yǔ)句執(zhí)行結(jié)果時(shí)間順序上誰(shuí)都有可能在前面。這樣一來(lái),如果第一個(gè)always語(yǔ)句執(zhí)行在前面,由于阻塞賦值,所以變量a立即得到b的賦值,那么當(dāng)?shù)诙€(gè)always塊執(zhí)行之后,變量b得到a的賦值;由于剛才第一個(gè)always執(zhí)行時(shí)b值賦予了a,所以現(xiàn)在b的值會(huì)維持不變,還是原來(lái)的值。同樣的道理,如果第二個(gè)always模塊先執(zhí)行了,那么a就會(huì)保持自身值不變,從Verilog語(yǔ)法角度來(lái)看,兩種結(jié)果都是有效的。但是從數(shù)字電路的角度來(lái)說(shuō),明顯引起了競(jìng)爭(zhēng)。下面將阻塞賦值修改為非阻塞賦值,以上代碼修改為
always@(posedgeclk)
a<=b;
always@(posedgeclk)
b<=a;
采用非阻塞賦值,由于原始信號(hào)在賦值語(yǔ)句中使用,所以a和b都會(huì)得到正確的值,而與順序沒(méi)有關(guān)系。因此在時(shí)序邏輯描述中,阻塞賦值往往會(huì)引起條件競(jìng)爭(zhēng),應(yīng)采用非阻塞賦值方式賦值。7.3.4時(shí)序電路中的混合賦值
DFF是最簡(jiǎn)單的時(shí)序電路,很有可能在同一always模塊中既包含阻塞賦值,又包含非阻塞賦值??梢酝ㄟ^(guò)一個(gè)簡(jiǎn)例來(lái)解釋各種混合描述的變量行為,從而更好地理解兩種賦值的區(qū)別。
下面舉例描述a與b的與操作,并將結(jié)果在時(shí)鐘的上升沿存儲(chǔ)到存儲(chǔ)器中?;谇懊娴拿枋龇椒?,可以將寄存器和組合邏輯分開(kāi)兩段描述,如程序7-7所示。
【程序7-7】寄存器和組合邏輯分為兩段描述。
moduleab_and
(
input
wireclk,
input
wirea,b,
output
regq
);
regq_next;
//DFF
always@(posedgeclk)
q<=q_next;
//組合邏輯電路
always@*
q_next=a&b;
endmodule
【程序7-8】
六種組合產(chǎn)生六種結(jié)果。
moduleab_ff_all
(
inputwireclk,
inputwirea,b,
outputregq0,q1,q2,q3,q4,q5
);
regab0,ab1,ab2,ab3,ab4,ab5;
//第一種情況
always@(posedgeclk)
begin
ab0=a&b;
q0<=ab0;
end
//第二種情況
always@(posedgeclk)
begin
ab1<=a&b;
q1<=ab1;
end
//第三種情況
always@(posedgeclk)
begin
ab2=a&b;
q2=ab2;
end
//第四種情況
always@(posedgeclk)
begin
q3<=ab3;
ab3=a&b;
end
//第五種情況
always@(posedgeclk)
begin
q4<=ab4;
ab4<=a&b;
end
//第六種情況
always@(posedgeclk)
begin
q5=ab5;
ab5=a&b;
end
endmodule
在第一種情況下,由于第一條語(yǔ)句為阻塞賦值,所以ab0值立即得到更新,q0得到a&b的值,其數(shù)據(jù)執(zhí)行原理圖如圖7-23(a)所示。由于ab0在always模塊中沒(méi)有輸出,因而ab0輸出寄存器可以省略掉,結(jié)果如圖7-23(b)所示。所以第一種情況滿(mǎn)足設(shè)計(jì)需求。圖7-23混合賦值電路原理圖在第二種情況下,ab1采用非阻塞賦值,在時(shí)鐘第一個(gè)節(jié)拍,q1賦值為ab1原來(lái)保持的值,而ab1得到賦值a&b;時(shí)鐘第二個(gè)節(jié)拍時(shí),q1才得到ab1的新的賦值,所以中間會(huì)產(chǎn)生一個(gè)意外的緩沖器,a&b值輸出到q1上時(shí)延遲了一個(gè)時(shí)鐘節(jié)拍。
在第三種情況下,ab2和q2都用阻塞賦值,根據(jù)7.3.3節(jié)描述,很容易產(chǎn)生條件競(jìng)爭(zhēng),所以此種情況不可以選用。用同樣的方法分析后面三種情況,會(huì)發(fā)現(xiàn)第四種情況是在第一種情況下將兩條賦值語(yǔ)句的順序?qū)φ{(diào),如此一來(lái),ab3在新值賦值之前就賦值給了q3,所以q3得到的是ab3鎖存的值,其實(shí)現(xiàn)的電路如圖7-23(a)所示。在第五種情況下,賦值語(yǔ)句對(duì)調(diào)依然會(huì)造成競(jìng)爭(zhēng)。在第六種情況下,ab5先是在賦值之前就被使用,然后q5才得到a&b的值,所代表的電路和第三種情況是一樣的。
綜上所述,只有第一種情況所描述的電路是正確而穩(wěn)定的。 7.4優(yōu)秀HDL代碼風(fēng)格
7.4.1代碼風(fēng)格的含義
代碼風(fēng)格有兩層含義,其一是代碼的書(shū)寫(xiě)習(xí)慣,這一點(diǎn)也是大家對(duì)代碼風(fēng)格的最原始的理解,那就是如何書(shū)寫(xiě)代碼,達(dá)到易于理解、易于調(diào)試以及易于移植的效果。而代碼風(fēng)格還有一層更為深刻的含義,就是指對(duì)特定電路采用特定的描述習(xí)慣和描述方法,使得電路實(shí)現(xiàn)起來(lái)更加可靠。
在FPGA設(shè)計(jì)中,代碼風(fēng)格分為通用風(fēng)格和專(zhuān)用風(fēng)格兩類(lèi)。前者不依賴(lài)于FPGA開(kāi)發(fā)的EDA工具和FPGA芯片類(lèi)型,為數(shù)字電路設(shè)計(jì)通用代碼風(fēng)格,適合于A(yíng)SIC設(shè)計(jì);后者指與開(kāi)發(fā)軟件和芯片類(lèi)型都有很大關(guān)系。作為FPGA設(shè)計(jì),應(yīng)該在堅(jiān)持通用風(fēng)格的基礎(chǔ)上,熟悉專(zhuān)用風(fēng)格,以更有利于設(shè)計(jì)出高可靠性的產(chǎn)品。
7.4.2通用代碼風(fēng)格
1.邏輯復(fù)用和邏輯復(fù)制
1)邏輯復(fù)用
邏輯復(fù)用是通過(guò)提高工作頻率來(lái)節(jié)省面積的一種優(yōu)化設(shè)計(jì)方法。在代碼復(fù)用上下工夫,比工具優(yōu)化要強(qiáng)的多,也是FPGA設(shè)計(jì)的核心思想。舉個(gè)補(bǔ)碼平方器的例子,系統(tǒng)輸入8bit補(bǔ)碼,求其平方和,由于輸入的是補(bǔ)碼,所以當(dāng)最高位是1時(shí),表示原值是負(fù)數(shù),需要按位取反,加1之后再求平方;當(dāng)最高位是0時(shí),表示原值是正數(shù),直接求平方。下面舉例采用普通處理方式和邏輯復(fù)用兩種方式來(lái)描述。普通處理方法實(shí)現(xiàn)方式為
modulesquare_genral_way
(
input
wire[7:0]data_in,
output
wire[15:0]square
)
wire[7:0]data_bar;
assigndata_bar=~data_in+1;
assignsquare=(data_in[7])?(data_bar*data_bar):(data_in*data_in);
endmodule
邏輯復(fù)用方式為
modulesquare_resource_share
(
input
wire[7:0]data_in,
output
wire[15:0]square
)
wire[7:0]data_tmp;
assigndata_tmp=(data_in[7])?(~data_in+1):datai_in;
assignsquare=data_tmp*data_tmp;
endmodule
經(jīng)過(guò)比較,第一種實(shí)現(xiàn)方式需要兩個(gè)16位乘法器,同時(shí)平方,然后根據(jù)輸入補(bǔ)碼符號(hào)選擇輸出結(jié)果,其關(guān)鍵在于使用了兩個(gè)乘法器,選擇器在乘法器之后;第二種實(shí)現(xiàn)方式首先根據(jù)輸入補(bǔ)碼的符號(hào)將補(bǔ)碼換算為正數(shù),然后做平方,僅需要1個(gè)16位乘法器,乘法器資源減少一半。雖然很多EDA工具支持邏輯復(fù)用綜合功能,但是很多情況下不能智能發(fā)現(xiàn)可以復(fù)用的邏輯,所以最好在代碼上體現(xiàn)。
2)邏輯復(fù)制
邏輯復(fù)制是通過(guò)增加面積而改善設(shè)計(jì)時(shí)序的優(yōu)化方法,經(jīng)常用于調(diào)整信號(hào)扇出。如果信號(hào)具有很高的扇出,即要驅(qū)動(dòng)很多后續(xù)電路,則要添加緩存器來(lái)增強(qiáng)驅(qū)動(dòng)能力。但是這樣會(huì)增大信號(hào)的延時(shí)。通過(guò)邏輯復(fù)制,使用多個(gè)相同信號(hào)來(lái)分擔(dān)驅(qū)動(dòng)任務(wù),有利于降低每路信號(hào)的扇出,便不需要額外的緩沖器來(lái)增強(qiáng)驅(qū)動(dòng),可減少信號(hào)的路徑延遲。例如,用于產(chǎn)生控制信號(hào)的模塊一般都有高的扇出,這時(shí)就要考慮邏輯復(fù)制。如圖7-24(a)所示為未使用邏輯復(fù)制的設(shè)計(jì)模式,占用資源較少,但是延遲大,容易出錯(cuò),而采用邏輯復(fù)制設(shè)計(jì),如圖7-24(b)所示,延遲小,占用資源多。圖7-24邏輯復(fù)制舉例邏輯復(fù)用和邏輯復(fù)制是矛盾統(tǒng)一體,一個(gè)是通過(guò)提高速度換取面積,另一個(gè)是通過(guò)面積增加換取速度提高,兩者之間存在平衡。在XST中用戶(hù)可以設(shè)定最大扇出數(shù),當(dāng)某信號(hào)的扇出超過(guò)最大扇出值時(shí),該信號(hào)會(huì)自動(dòng)被綜合工具復(fù)制,以降低扇出。
2.if和case語(yǔ)句的使用區(qū)別
if語(yǔ)句執(zhí)行具有優(yōu)先級(jí),而case語(yǔ)句執(zhí)行是并行的,不具有優(yōu)先級(jí),所以if-else結(jié)構(gòu)執(zhí)行速度較慢,但是占用面積小。如果對(duì)速度沒(méi)有什么要求而對(duì)面積要求很高,則可用if-else語(yǔ)句完成編解碼。case語(yǔ)句執(zhí)行較快,但是占用面積大,因而case語(yǔ)句實(shí)現(xiàn)對(duì)速度要求較高的編解碼電路;if-else語(yǔ)句嵌套太長(zhǎng)會(huì)導(dǎo)致延時(shí),所以應(yīng)根據(jù)實(shí)際情況合理地使用if和case語(yǔ)句。
3.關(guān)鍵路徑信號(hào)處理原則
在系統(tǒng)中經(jīng)常有一些信號(hào)路徑過(guò)長(zhǎng),從而造成建立時(shí)間不夠,這種信號(hào)路徑稱(chēng)為關(guān)鍵路徑。在復(fù)雜電路設(shè)計(jì)中必須有效地處理關(guān)鍵信號(hào),盡量減少其延時(shí),提高電路工作頻率。
1)簡(jiǎn)單組合電路關(guān)鍵路徑提取
簡(jiǎn)單組合電路關(guān)鍵路徑提取方法就是拆分邏輯,將復(fù)雜邏輯變成多個(gè)簡(jiǎn)單組合電路的進(jìn)一步組合,縮短關(guān)鍵信號(hào)的邏輯路徑。如對(duì)于語(yǔ)句
assigny=a&b&c|d&e&b;
信號(hào)b為關(guān)鍵信號(hào),先計(jì)算其簡(jiǎn)單路徑,再經(jīng)過(guò)關(guān)鍵路徑邏輯,即
assigntemp=a&b&c|d&e;
assigny=temp&b;
2)復(fù)雜時(shí)序電路關(guān)鍵路徑提取
對(duì)于always模塊中時(shí)間要求非常緊的信號(hào),需要通過(guò)分步提取方法,讓關(guān)鍵路徑先行,保證修改后的描述與原always塊邏輯等效。程序7-9給出了提取并改善always模塊中關(guān)鍵信號(hào)的實(shí)例。
【程序7-9】always塊中關(guān)鍵路徑的提取和優(yōu)化實(shí)例。
always@(w,x,y,z,in1,in2)begin
if(!w)begin
if(x&&(!(y&&z)))
out=in1;
else
out=in2;
else
if(y&&z)
out=in1;
end
else
begin
out=out;
end
end
若z=0,則原代碼等效于
if(!w)out=in1;
elseout=out;若z=1,則代碼等效于
if(!w&&x&&!y)out=in1;
else
if(!w&&x&&y)out=in2;
elseout=out;對(duì)于信號(hào)y也有類(lèi)似的分析結(jié)果。所以y和z都是關(guān)鍵信號(hào),可通過(guò)首先計(jì)算關(guān)鍵路徑進(jìn)行優(yōu)化。代碼優(yōu)化為
always@(w,x,y,z,in1,in2)begin
temp=y&&z;
if(!temp)begin
if(x&&!w)
out=in1;
else
out=in2;
else
if(temp)
out=in1;
end
else
out=out;
end
4.避免出現(xiàn)意外鎖存器
鎖存器是電平觸發(fā)的存儲(chǔ)器。觸發(fā)器是邊沿觸發(fā)的存儲(chǔ)器。在同步設(shè)計(jì)中要盡量減少鎖存器的使用。因?yàn)殒i存器對(duì)毛刺非常敏感,不能異步復(fù)位,在上電之后處于不確定狀態(tài)。此外,鎖存器還會(huì)使靜態(tài)時(shí)序分析變得非常復(fù)雜,不具備可重用性;在FPGA芯片中,基本單元是由查找表和觸發(fā)器組成的,若生成鎖存器,反而需要更多的資源。因此,在設(shè)計(jì)中需要避免鎖存器的產(chǎn)生。詳細(xì)內(nèi)容可參考4.5節(jié)關(guān)于always語(yǔ)句的用法所強(qiáng)調(diào)的三點(diǎn)。
5.流水線(xiàn)技術(shù)的使用
流水線(xiàn)處理基本思想是經(jīng)過(guò)多級(jí)邏輯的長(zhǎng)數(shù)據(jù)通路進(jìn)行重新構(gòu)造,通過(guò)將流水線(xiàn)型寄存器插入到組合邏輯的關(guān)鍵位置上,把原來(lái)必須在一個(gè)時(shí)鐘周期內(nèi)完成的操作分成在多個(gè)時(shí)鐘周期內(nèi)完成。這種方法減少了組合邏輯塊中的級(jí)數(shù),縮短了存儲(chǔ)元件間的數(shù)據(jù)通道,并且允許更高的工作頻率,從而提高了數(shù)據(jù)吞吐量。在FPGA器件中,擁有大量的寄存器資源,采用流水線(xiàn)設(shè)計(jì)可以動(dòng)態(tài)地提升器件性能。
流水線(xiàn)在高速、寬字?jǐn)?shù)據(jù)流傳輸和處理中變的非常重要。如圖7-25所示的組合邏輯塊由流水線(xiàn)寄存器分割成兩個(gè)子快,得到另一種可選的電路。如果原多級(jí)組合邏輯電路最長(zhǎng)路徑時(shí)間為T(mén)max,那么新電路的最長(zhǎng)路徑時(shí)間將縮短為原來(lái)的一半,也就是運(yùn)行速率提高1倍。圖7-25流水線(xiàn)插入實(shí)現(xiàn)過(guò)程流水線(xiàn)可以提高電路的工作頻率,但是卻產(chǎn)生了輸入輸出的延遲。流水線(xiàn)的每一級(jí)在得到電路第一個(gè)輸出之前,都要加上一個(gè)周期的延時(shí)。每增加一級(jí)流水線(xiàn),時(shí)間延遲就增加1拍。所以需要先將電路合理地劃分為N個(gè)步驟,分成不同的階段,然后通過(guò)合理的安排時(shí)序前后級(jí)接口間數(shù)據(jù)的匹配,擴(kuò)大數(shù)據(jù)吞吐量,完成并行運(yùn)算。如果前級(jí)操作的時(shí)間等于后級(jí)操作時(shí)間,則直接輸入即可;如果前級(jí)操作時(shí)間小于后級(jí)操作時(shí)間,則需要對(duì)前級(jí)數(shù)據(jù)進(jìn)行緩存,然后才能輸入到后級(jí);如果前級(jí)操作時(shí)間大于后級(jí)操作時(shí)間,則需要用串/并轉(zhuǎn)換方式進(jìn)行數(shù)據(jù)分流,然后輸入到后級(jí)。7.4.3Xilinx芯片專(zhuān)用代碼風(fēng)格
1.時(shí)鐘信號(hào)的分配策略
在FPGA中,擁有專(zhuān)門(mén)的時(shí)鐘管理資源和時(shí)鐘輸入管腳。所以針對(duì)時(shí)鐘的使用,需要參考如下準(zhǔn)則:
(1)使用全局時(shí)鐘,可以為信號(hào)提供最短的延時(shí)和可以忽略的扭曲。全局網(wǎng)線(xiàn)由全局緩沖器BUFG來(lái)驅(qū)動(dòng)。使用BUFG時(shí),時(shí)鐘信號(hào)經(jīng)過(guò)BUFG驅(qū)動(dòng)后,通過(guò)長(zhǎng)線(xiàn)同時(shí)接到每個(gè)觸發(fā)器的時(shí)鐘端,減少傳輸延遲。
(2)?FPGA適合同步電路設(shè)計(jì),盡可能減少使用時(shí)鐘信號(hào)的種類(lèi),避免由組合邏輯生成多個(gè)時(shí)鐘來(lái)分別驅(qū)動(dòng)多個(gè)觸發(fā)器的設(shè)計(jì)方法。因?yàn)樵贔PGA內(nèi)部專(zhuān)用時(shí)鐘資源是有限的,如果不使用專(zhuān)用時(shí)鐘資源,則各個(gè)負(fù)載點(diǎn)上的時(shí)鐘延遲偏差很大,會(huì)引起數(shù)據(jù)保持時(shí)間問(wèn)題,降低工作速度。
(3)減小時(shí)鐘扭曲的有效方法是,使用一個(gè)時(shí)鐘信號(hào),生成多個(gè)時(shí)鐘使能信號(hào),分別驅(qū)動(dòng)觸發(fā)器的時(shí)鐘使能端,所有觸發(fā)器的數(shù)據(jù)裝入都由同一個(gè)時(shí)鐘控制。但是只有時(shí)鐘使能信號(hào)有效的觸發(fā)器才會(huì)裝入數(shù)據(jù),時(shí)鐘使能信號(hào)無(wú)效的觸發(fā)器則僅保持?jǐn)?shù)據(jù)。
2.觸發(fā)器資源的分配技術(shù)
(1)盡量使用庫(kù)中的觸發(fā)器資源。FPGA觸發(fā)器資源豐富,而且開(kāi)發(fā)系統(tǒng)在劃分邏輯塊時(shí),對(duì)D觸發(fā)器等元件直接利用CLB中的觸發(fā)器,而對(duì)自建觸發(fā)器認(rèn)為是組合電路,需要使用CLB中的組合邏輯資源實(shí)現(xiàn)。這樣一來(lái),占據(jù)了更多的CLB資源。
(2)設(shè)計(jì)狀態(tài)機(jī)盡量使用ONE-HOT狀態(tài)機(jī)編碼方案,因?yàn)槠涿總€(gè)狀態(tài)由1位觸發(fā)器來(lái)表示,相對(duì)二進(jìn)制狀態(tài)編碼穩(wěn)定性要好的多,非常適合用于觸發(fā)器資源豐富的FPGA器件。7.4.4推薦時(shí)序電路描述代碼風(fēng)格
在以往的描述中,經(jīng)常將時(shí)序描述單獨(dú)在一個(gè)always中描述。現(xiàn)在理解了阻塞和非阻塞的賦值區(qū)別之后,可以將時(shí)序電路中寄存器描述與下一狀態(tài)邏輯描述放在同一個(gè)always模塊中。如此一來(lái),顯得代碼描述非常緊湊,如程序7-8的第一種情況一樣:
(1)采用阻塞賦值獲取下一狀態(tài)邏輯的立即結(jié)果,不過(guò)應(yīng)注意賦值語(yǔ)句的順序;
(2)使用非阻塞賦值語(yǔ)句賦值寄存器的立即結(jié)果。
下面舉例來(lái)介紹此種代碼風(fēng)格。
1.二進(jìn)制計(jì)數(shù)器
【程序7-10】
二進(jìn)制計(jì)數(shù)器。
modulebin_counter
#(parameterN=8)
(
input
wireclk,reset,
output
wiremax_tick,
output
wire[N-1:0]q
);
//信號(hào)聲明
reg[N-1:0]r_next,r_reg;
//寄存器以及下一狀態(tài)邏輯
always@(posedgeclk,posedgereset)
if(reset)
r_reg<=0;//{N{1b'0}}
else
begin
//下一狀態(tài)邏輯
r_next=r_reg+1;
//寄存器描述
r_reg<=r_next;
end
//輸出邏輯
assignq=r_reg;
assignmax_tick=(r_reg==2**N-1)?1'b1:1'b0;
endmodule
需要注意的是,輸出邏輯:
assignmax_tick=(r_reg==2**N-1)?1'b1:1'b0;
必須放在always模塊的外面,如果放在always模塊里面,max_tick輸出就會(huì)產(chǎn)生一個(gè)多余的時(shí)鐘延遲。
由于r_next信號(hào)沒(méi)有在別的地方用到,可以將以下兩條語(yǔ)句:
r_next=r_reg+1;
r_reg<=r_next;
合并為
r_reg<=r_reg+1;
如此一來(lái),自由計(jì)數(shù)器可以描述為更為精簡(jiǎn)的形式,如程序7-11所示。
【程序7-11】
自由計(jì)數(shù)器描述的精簡(jiǎn)形式。
modulebin_counter_terse
#(parameterN=8)
(
input
wireclk,reset,
output
wiremax_tick,
output
reg[N-1:0]q
);
always@(posedgeclk,posedgereset)
if(reset)
q<=0;
else
q<=q+1;
//輸出邏輯
assignmax_tick=(q==2**N-1)?1'b1:1'b0;
endmodule
2.狀態(tài)機(jī)電路描述
在狀態(tài)機(jī)描述中,下一狀態(tài)邏輯可以被合并到寄存器控制模塊中,如前面講述的程序6-1,可以被重新寫(xiě)成如程序7-12所示。
【程序7-12】合并下一狀態(tài)邏輯到寄存器控制模塊。
modulefsm_merged
(
input
wireclk,reset,
input
wirea,b,
output
wirey0,y1
);
//狀態(tài)信號(hào)聲明
parameter[1:0]s0=2'b00,
s1=2'b01,
s2=2'b10;
//信號(hào)聲明
reg[1:0]state_reg;
//狀態(tài)跳轉(zhuǎn)以及下一狀態(tài)邏輯產(chǎn)生
always@(posedgeclk,posedgereset)
if(reset)
state_reg<=s0;
else
case(state_reg)
s0:if(a)
if(b)
state_reg<=s2;
else
state_reg<=s1;
else
state_reg<=s0;
s1:if(a)
state_reg<=s0;
else
state_reg<=s1;
s2:state_reg<=s0;
defaultstate_reg<=s0;
endcase
//Moore輸出邏輯
assigny1=(state_reg==s0)||(state_reg==s1);
//Mealy輸出邏輯
assigny0=(state_reg==s0)&a&b;
endmodule 7.5TestBench編寫(xiě)
TestBench就是測(cè)試平臺(tái)的意思。軟件設(shè)計(jì)講究仿真驗(yàn)證,硬件設(shè)計(jì)同樣注重對(duì)設(shè)計(jì)的仿真以及驗(yàn)證。仿真驗(yàn)證在數(shù)字設(shè)計(jì)中屬于非常復(fù)雜的一部分,本節(jié)僅僅精簡(jiǎn)地介紹常用的TestBench的編寫(xiě),使得讀者能夠?qū)Υ蟛糠殖S玫脑O(shè)計(jì)有能力編寫(xiě)TestBench。若要繼續(xù)深入學(xué)習(xí),則請(qǐng)參考別的更為專(zhuān)業(yè)的介紹TestBench的書(shū)。
TestBench的功能就是先產(chǎn)生激勵(lì)輸入到待測(cè)設(shè)計(jì)(DUT)中,然后檢查DUT的輸出是否與預(yù)期的一致,達(dá)到驗(yàn)證設(shè)計(jì)功能的目的,如圖7-26所示。圖7-26TestBench的概念7.5.1基于HDL的TestBench編寫(xiě)
很多仿真工具都支持基于HDL的TestBench,比如ModelSim、ISE12.1中自帶的ISim、NC_Verilog等等。采用HDL編寫(xiě)TestBench,對(duì)設(shè)計(jì)添加激勵(lì),通過(guò)波形或者自動(dòng)比較工具或者輸出文件等分析設(shè)計(jì)的正確性,并分析TestBench自身的覆蓋率和正確性?;贖DL的TestBench仿真步驟如下:
(1)為待測(cè)試設(shè)計(jì)(DesignUnderTest,DUT)提供激勵(lì)信號(hào);
(2)正確例化DUT;
(3)將仿真數(shù)據(jù)顯示在終端或者存為文件,也可以顯示在波形窗口中以供分析檢查;
(4)對(duì)于復(fù)雜的設(shè)計(jì),可根據(jù)設(shè)計(jì)需要使用EDA工具,通過(guò)用戶(hù)接口自動(dòng)化比較仿真結(jié)果與理想值,實(shí)現(xiàn)結(jié)果的自動(dòng)檢查。7.5.2always和initial模塊
Verilog語(yǔ)句中包含兩種基本的過(guò)程結(jié)構(gòu)語(yǔ)句:always和initail語(yǔ)句。always模塊中包含順序執(zhí)行語(yǔ)句,其模塊的激活與執(zhí)行都是由敏感量列表中的變量觸發(fā)的。always模塊可以包含時(shí)序控制來(lái)產(chǎn)生相關(guān)如延時(shí)或者等待,敏感量列表有時(shí)可以省略,比如可以采用always語(yǔ)句產(chǎn)生時(shí)鐘信號(hào):
always
beign
clk=1'b1;
#20;
clk=1'b0;
#20
end
initial語(yǔ)句同樣可以包含順序執(zhí)行語(yǔ)句,然而,它只執(zhí)行一次,其語(yǔ)法結(jié)構(gòu)為
initial
begin
[過(guò)程語(yǔ)句]
end7.5.3順序執(zhí)行語(yǔ)句
順序執(zhí)行語(yǔ)句通常包含在initial模塊、always模塊、函數(shù)(functions)模塊以及任務(wù)(tasks)模塊中,常用的過(guò)程語(yǔ)句包括:①阻塞賦值語(yǔ)句;②非阻塞賦值語(yǔ)句;③?if判斷語(yǔ)句;④?case選擇語(yǔ)句;⑤循環(huán)語(yǔ)句。
if語(yǔ)句、case語(yǔ)句在前面的章節(jié)中都有介紹,這里重點(diǎn)介紹循環(huán)語(yǔ)句。Verilog支持的循環(huán)語(yǔ)句包括for、while、repeat以及forever語(yǔ)句。
for語(yǔ)句的語(yǔ)法結(jié)構(gòu)為
for([初始化];[結(jié)束條件];[步進(jìn)])
begin
[過(guò)程語(yǔ)句]
end
比如給16字的寄存器文件清零:
integeri;
for(i=0;i<16;i=i+1)
reg_file[i]=0;循環(huán)體的語(yǔ)句一直重復(fù)執(zhí)行,直到結(jié)束條件滿(mǎn)足。比如,前面寄存器文件清零語(yǔ)句同樣可以采用while語(yǔ)句和repeat語(yǔ)句完成,分別如下:
integeri;
i=0;
while(i<16)
begin
reg_file[i]=0;
i=i+1;
end
采用repeat語(yǔ)句可以表示為
integeri;
i=0;
repeat(16)
begin
reg_file[i]=0;
i=i+1;
end
7.5.4時(shí)序控制語(yǔ)句
在TestBench中,有三種精確控制時(shí)序的結(jié)構(gòu):
(1)延時(shí)控制:#[delaytime];
(2)事件控制:@[event,event,…]
(3)等待語(yǔ)句:wait[布爾表達(dá)式]
除此之外,時(shí)序定義語(yǔ)句'timescale也與時(shí)序有關(guān)。'timescale定義時(shí)序單位以及時(shí)序單位的精度,如'timescale1ns/1ps,代表在當(dāng)前文件中的時(shí)間單位是1ns,時(shí)間可以精確到1ps。下面舉例介紹時(shí)序控制語(yǔ)句的使用。
1.普通時(shí)鐘信號(hào)
(1)采用initial語(yǔ)句產(chǎn)生時(shí)鐘的方法如下:
parameterPERIOD=10;
regclk;
initial
begin
clk=0;
forever
#(PERIOD/2)clk=~clk;
end
(2)采用always語(yǔ)句產(chǎn)生時(shí)鐘的方法如下:
parameterPERIOD=10;
regclk;
initial
clk=0;//將clk初始化為0
always
#(PERIOD/2)clk=~clk;
2.占空比不是50%的時(shí)鐘信號(hào)
有時(shí)在設(shè)計(jì)中用到的時(shí)鐘占空比不是50%。比如用always語(yǔ)句實(shí)現(xiàn)占空比為40%的時(shí)鐘,其代碼如下:
parameterHI_TIME=4;
LO_TIME=6;
regclk;
always
begin
#HI_TIMEclk=0;
#LO_TIMEclk=1;
end
3.固定數(shù)目時(shí)鐘信號(hào)
如果需要產(chǎn)生固定數(shù)目的時(shí)鐘脈沖,則可以在initail語(yǔ)句中使用repeat語(yǔ)句來(lái)實(shí)現(xiàn),其代碼如下:
//兩個(gè)高脈沖的時(shí)鐘
parameterPULSE_COUNT=4,FAST_PERIOD=10;
regclk;
initial
begin
clk=0;
repeat(PULSE_COUNT)
#(FAST_PERIOD/2)clk=~clk;
end
4.相移時(shí)鐘信號(hào)
系統(tǒng)中往往有好幾個(gè)時(shí)鐘,并且時(shí)鐘之間有相位差別,下面舉例描述相移時(shí)鐘信號(hào):
parameterHI_TIME=5,LO_TIME=10,PHASE_SHIFT=2;
regabsolute_clk;
wirederived_clk;
always
beign
#HI_TIMEabsolute_clk=0;
#LO_TIMEabsolute_clk=1;
end
assign#PHASE_SHIFTderived_clk=absolute_clk;
5.異步復(fù)位信號(hào)
復(fù)位信號(hào)不是周期信號(hào),而是在系統(tǒng)開(kāi)始時(shí)復(fù)位有效,所以采用initial語(yǔ)句賦值產(chǎn)生:
parameterPERIOD=10;
regreset_N;
initial
begin
reset_N=1;
#PERIODreset_N=0;
#(5*PERIOD)reset_N=1;
end
復(fù)位信號(hào)低有效,復(fù)位在10ns時(shí)開(kāi)始,持續(xù)50ns。
6.同步復(fù)位信號(hào)
同步復(fù)位信號(hào)的實(shí)現(xiàn)如下:
initial
begin
reset_N=1;
@(negedgeclk);
reset_N=0;
#30
@(negedgeclk);
reset_N=1;
end
該代碼首先將reset_N初始化為1,然后在第一個(gè)clk的下降沿處開(kāi)始復(fù)位,再延時(shí)30ns,最后在下一個(gè)時(shí)鐘沿處撤銷(xiāo)復(fù)位。如此一來(lái),復(fù)位的產(chǎn)生和撤銷(xiāo)都避開(kāi)了時(shí)鐘的有效上升沿,因此這種復(fù)位屬于同步復(fù)位。 另外一種同步復(fù)位信號(hào)的實(shí)現(xiàn)方法如下:
initial
begin
reset_N=1;
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 城市地鐵隧道注漿加固施工方案
- 鍋爐吊裝方案
- 2026廣西貴港市港南區(qū)自然資源局招聘編外聘用人員5人考試備考題庫(kù)及答案解析
- 2026河北衡水鐵路電氣化學(xué)校高校應(yīng)屆畢業(yè)生引進(jìn)考試備考試題及答案解析
- 2026年鄭州市法律援助基金會(huì)招聘工作人員考試備考試題及答案解析
- 2026西北工業(yè)大學(xué)動(dòng)力與能源學(xué)院葉輪機(jī)氣熱彈研究所招聘1人(陜西)考試備考題庫(kù)及答案解析
- 2026重慶醫(yī)科大學(xué)附屬康復(fù)醫(yī)院公共衛(wèi)生科人員招聘1人考試參考題庫(kù)及答案解析
- 2026年1月重慶市萬(wàn)州區(qū)雙河口街道辦事處公益性崗位招聘1人考試參考題庫(kù)及答案解析
- 2026年陜西戶(hù)縣海絲村鎮(zhèn)銀行高校見(jiàn)習(xí)生招聘考試備考試題及答案解析
- 2026四川德陽(yáng)市羅江區(qū)就業(yè)創(chuàng)業(yè)促進(jìn)中心城鎮(zhèn)公益性崗位招聘1人(區(qū)博物館)考試參考題庫(kù)及答案解析
- 2026年內(nèi)蒙古化工職業(yè)學(xué)院高職單招職業(yè)適應(yīng)性考試參考題庫(kù)及答案詳解
- 中國(guó)肺血栓栓塞癥診治、預(yù)防和管理指南(2025版)
- 義務(wù)消防員培訓(xùn)課件
- 2025中北京鐵路局集團(tuán)招聘934人(本科及以上)筆試參考題庫(kù)附帶答案詳解(3卷合一)
- 倉(cāng)儲(chǔ)管理人員考核細(xì)則及績(jī)效標(biāo)準(zhǔn)
- 牛黃對(duì)肝功能影響研究-洞察及研究
- 泰康培訓(xùn)課件
- 電子簽名系統(tǒng)安全預(yù)案
- (零模)2026屆廣州市高三年級(jí)調(diào)研測(cè)試物理試卷(含答案)
- 消化內(nèi)鏡虛擬仿真訓(xùn)練系統(tǒng)的技術(shù)參數(shù)優(yōu)化
- 車(chē)輛保養(yǎng)套餐服務(wù)協(xié)議
評(píng)論
0/150
提交評(píng)論