第四章、VerilogHDL設(shè)計技巧._第1頁
第四章、VerilogHDL設(shè)計技巧._第2頁
第四章、VerilogHDL設(shè)計技巧._第3頁
已閱讀5頁,還剩50頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、第四章、 Verilog HDL設(shè)計技巧本章通過一些簡單的實例演示一下如何在verilog hdl中實現(xiàn)看似不可能實現(xiàn)的技巧,主要包括1雙向端口的使用2.PWM波形的產(chǎn)生3常見幾種分頻器的設(shè)計4巧用存儲器定義語句實現(xiàn)存儲器設(shè)計5基于存儲器的DDS設(shè)計6有限狀態(tài)機(jī)本章講述一些常用的 verilog設(shè)計方法和技巧,可以加速實際的工程應(yīng)用,提高效率。雙向端口雙向端口在應(yīng)用過程中常常用到,如在進(jìn)行和存儲器的接口設(shè)計時。由于存儲器的數(shù)據(jù)線是雙向信號,故FPGA的端口也必須用雙向端口才能夠連接。Verilog HDL中的雙向端口關(guān)鍵字為 in out,女口 in out dat,則表示dat為一個雙向(既

2、可以輸 入也可以輸出)的端口。在硬件中為了更好的處理端口,大多數(shù)情況下都是使用單向端口,即in put或者output。這樣更容易對電路的邏輯進(jìn)行描述。雙向端口也往往轉(zhuǎn)換成兩個單向的端口進(jìn)行操作。仔細(xì)分析一下,當(dāng)一個端口作為雙向端口時,實際上是分時的輸入和輸出,也就是說,當(dāng)內(nèi)部邏輯 需要雙向端口作為輸入時,這時候是用雙向的輸入功能,反之,用輸出功能。假設(shè)”內(nèi)部需要”為一個變量,暫且命名為 dir,則,雙向端口轉(zhuǎn)化為兩個單向端口的電路就可以如下圖所 示。圖中,實線框是整個的邏輯設(shè)計電路模塊,io為此模塊的雙向端口。 虛線框為將雙向端口轉(zhuǎn)化為兩個單向端口的子模塊,兩個三角形的電路為三態(tài)門,上面的三

3、態(tài)門低電平使能,下面的三態(tài)門高電平使能。當(dāng)需要將io端作為輸入時候,即 dir為高(假設(shè)為高電平時使用io端的輸入功能),上面的三態(tài)門被關(guān)閉,下面的三態(tài)門打開,于是信號的流向從io 口經(jīng)過下面的三態(tài)門由a端輸出,那么這個時候其他邏輯部分就可以使用a端的信號進(jìn)行運算處理;反之,當(dāng)內(nèi)部的其他邏輯需要輸出信號至io雙向端口時,可以置dir為低電平,上面的三態(tài)門被打開,下面的三態(tài)門被關(guān)閉,這樣b端口的信號經(jīng)由上面的三態(tài)門輸出至io端。這樣,虛線框中的子模塊就完成了雙向端口轉(zhuǎn)化為兩個獨立的單向端口(a和b)的功能。代碼如下:代碼注釋:聲明io端口為雙向端口,一般情況下雙向端口的類型聲明為wire型,這里

4、省略,默認(rèn)為wire 型。(2)當(dāng)dir為高電平時,io端口賦值給a端口,否則,a端為高阻態(tài),也可以寫成assign a =(dir)?io:1 bz;。當(dāng)dir為低電平時,b端口賦值給io端口,否則,io端賦值成高阻態(tài),也可以寫成assignio =(!dir) ? b:1 z;。上面電路中用到了三態(tài)門,通常來說,三態(tài)門在fpga和cpld內(nèi)部不推薦使用,而且一般僅限于fpga或者是cpld的引腳端才有,內(nèi)部沒有三態(tài)門。如果在設(shè)計過程中大量采用三態(tài)門 的話,會使芯片的功耗大幅增加,資源浪費嚴(yán)重。仔細(xì)研究發(fā)現(xiàn),可以在這里省略一個三態(tài)門。新電路如下:因為io的雙向特性是分時使用的,所以在內(nèi)部其他

5、邏輯使用a端和b端的時候也是分時使用的,換句話說,當(dāng)內(nèi)其他邏輯部向b寫的時候,無論a端是什么值對內(nèi)部的其他電路時沒 有影響的,因為這個時候內(nèi)部其他的邏輯不讀取a端口;反過來,當(dāng)內(nèi)部需要讀取a端的值的時候,a端的值必須來自于io端的值,故必須把 b端和io端斷開,即三態(tài)門呈現(xiàn) 3態(tài)即 可。新的代碼如下:module bidir2(io, a, b );in out io;output a;in put b;assig n a = io;/assign io = ( dir = 0 ) ? b:1 bz;en dmodule代碼注釋:(1)直接賦值即可。PWM波形的產(chǎn)生脈沖寬度調(diào)制(PWM),是英

6、文“ Pulse Width Modulation的縮寫,簡稱脈寬調(diào)制,是利用 微處理器的數(shù)字輸出來對模擬電路進(jìn)行控制的一種非常有效的技術(shù),廣泛應(yīng)用在從測量、信到功率控制與變換的許多領(lǐng)域中。PWM波形本質(zhì)上是寬度可以變化的脈沖。見下圖圖中,從A到C為一個脈沖的周期,AB之間電平為高電平,稱作這個脈沖周期的寬度, PWM是指AB之間的高電平寬度可以調(diào)節(jié)。若想用數(shù)字電路來實現(xiàn) pwm,不妨借鑒一下模擬電路中的pwm是如和生成的。9先產(chǎn)生鋸齒波,然后利用鋸齒波的電壓和另一個門限電壓做比較,當(dāng)門限電壓變化的時候, 比較器輸出的脈沖寬度就變化了。示意圖如下:ab由上圖比較得知,當(dāng)門限電平電壓升高時, 比

7、較器的輸出的占空比寬度在減少, 即達(dá)到了脈 沖寬度調(diào)制的目的。那么,在數(shù)字領(lǐng)域里,門限電平可以由一個任意的常量或者用端口輸入來實現(xiàn), 怎么樣去實 現(xiàn)鋸齒波呢?仔細(xì)研究鋸齒波,電壓隨著時間按照一定的比例上升(也就是增加) ,有點類 似計數(shù)器的味道。而實際上,如果將計數(shù)器的輸出的數(shù)字量進(jìn)行 DA轉(zhuǎn)換的話,看到的輸出就是鋸齒波。這里以8位的計數(shù)器和門限寬度為例,設(shè)計一個寬度可調(diào)的脈沖輸出。module pwm(thres, elk, pwm );in put elk;output pwm;in put 7:0 thres;reg 7:0 cntr; /(1)always(posedge elk) /

8、(2)cntr = thres)?1:0; /(3)en dmodule代碼注釋:(1) 設(shè)置計數(shù)用的變量,位寬為8位。和門限寬度一樣。(2) 計數(shù)器計數(shù),相當(dāng)于模擬波形中的鋸齒波(3) 比較器電路,當(dāng)鋸齒波值大于或等于門限時,pwm輸出高電平,否則,輸出低電平??上耄?dāng)門限輸入的值發(fā)生變化時,pwm輸出的脈沖寬度一定隨著變化。使用Quartus II仿真如下圖:thres為240時候,pwm的輸出脈沖寬度很窄。實現(xiàn)了pwm輸出脈沖寬度受thres門限值的調(diào)制。PWM在很多場合有重要的應(yīng)用,例如,直流電機(jī)驅(qū)動,步進(jìn)電機(jī)驅(qū)動、呼吸燈等。分頻器計數(shù)器和分頻器是 Verilog HDL設(shè)計中最基礎(chǔ)的

9、時序電路的組成部分。分頻器指的是一個系統(tǒng)能夠?qū)⑤斎氲南到y(tǒng)時鐘信號轉(zhuǎn)變成較低頻率信號的輸出。例如:4分頻電路就是指輸出的時鐘頻率是輸入時鐘頻率的四分之一。那么,如何實現(xiàn)呢?仔細(xì)分析輸出和輸入的關(guān)系就可以得到答案。先看下圖:輸入波形輸出波形f;!a?F*012$3孑0:1;23;10 i 1 !H_hLKK_rLrLHK_hu1I1I+fT_bdt911:t3丨 11111-1a194I-4I:!:!:i-aIa;I:E:tiF-$這里有2個方波,上面的波形每個周期被虛豎線隔開,可以看出下面波形的周期為上面的 波形的4倍。如果說上面的波形為輸入的時鐘信號,下面的波形為分頻器輸出的信號,那 么說這個

10、輸出就是輸入的 4分頻。仔細(xì)研究上圖,可以看出,如果要輸出4分頻信號的話,可以對輸入的信號進(jìn)行模4計數(shù)(即03),當(dāng)計數(shù)值為0和1時,將輸出信號的電平置為低電平;當(dāng)計數(shù)值為2和3的時候?qū)⑤敵鲂盘柕碾娖街脼楦唠娖健S捎谟嫈?shù)是模4的,所以計數(shù)值就會在 03之間不停的計數(shù),而輸出信號也會不停的輸出低電平、高電平、低電平,這樣4分頻的輸出信號就實現(xiàn)了!module freqdiv4(clki,clko); in put clki;output clko;reg1:0 cntr; always(posedge clki) if(cntr = 3)cntr = 0;elsecntr =c ntr + 1b

11、1;assig n clko=(c ntr=1)?0:1;en dmodule為了能更加清楚地了解Verilog語言的特點,請把上面代碼作如下修改,然后體會一下assign和always的區(qū)別。module freqdiv4(clki,clko);in put clki;output reg clko; /將輸出設(shè)計成 reg 型reg1:0 cntr;always(posedge clki)beginif(c ntr = 3) cntr = 0;elsecntr =c ntr + 1b1;if (cntr=1) 在這個always中直接判斷計數(shù)值,然后給出clko的電平值clko = 0;e

12、lseclko = 1;enden dmodule在剛才的4分頻中,輸出信號時方波,如果說輸出信號不是方波的話,但只要頻率是輸入的1/4,就稱之為4分頻。如下圖,波形 2和波形3都是輸入信號的4分頻。module freqdiv4(clki,clko);in put clki;output clko;reg1:0 cntr;always(posedge clki) if(cntr = 3)cntr = 0;elsecntr =c ntr + 1b1;assig n clko=(c ntr=O)?O:1;只需要修改這里en dmodule同理也可以完成占空比為 25%的4分頻輸出,代碼請讀者自己

13、完成。2分頻2分頻和4分頻一樣,首先要構(gòu)建一個模 2計數(shù)器,當(dāng)計數(shù)器值為 0時,輸出低電平;當(dāng)計 數(shù)器值為1時,輸出高電平。這樣計數(shù)器每計2個數(shù)就可以得到一個周期的輸出,故是2分頻。2分頻的另外一種思想:如果說輸入信號每個信號上升沿到來的時候,都將輸出端進(jìn)行電平翻轉(zhuǎn)一下(原來是低電平,現(xiàn)在變高電平;原來是高電平,現(xiàn)在變成低電平。)這樣,輸出端若要得到一個周期就需要翻轉(zhuǎn) 2次,也就是2個輸入時鐘的上升沿, 也就是輸入2個周期 得到一個周期,也即:2分頻。代碼如下:module freqdiv2(clki,clko);in put clki;output reg clko;always(posed

14、ge clki)clko = !clko;en dmodule通過波形仿真可以驗證2分頻的正確性。這種二分頻的方式用的比較頻繁,也推薦大家在以后的應(yīng)用中使用。 接下來進(jìn)行三分頻的學(xué)習(xí)。根據(jù)前面的學(xué)習(xí),可以得出,三分頻可能有2中波形輸出,見下圖:波形1波形2在上面的波形中,2中輸出的占空比分別是 33%和67%,沒有50%的占空比輸出波形了。如波形3為50%的方波,看圖中虛線處,方波輸出在輸入時鐘的下降沿和上升沿均有變化。所以,這里要想到,如果使用下降沿做分頻,效果如何呢?為了便于比較,下圖以33%占空比為例,分別用下降沿和上升沿進(jìn)行分頻。圖中,點虛線為一個周期,這個周期輸出下降沿的分頻信號,線

15、虛線為上升沿分頻的一個周期。大家會發(fā)現(xiàn),兩個輸出“錯位” 了半個輸入時鐘周期,按照50%的計算,輸出脈沖寬度為1.5個輸入時鐘周期,如果說將兩個33%的分頻輸出信號相“或”的話,輸出不就是50%占空比了嘛!3分頻50%輸出占空比的代碼如下:module freqdiv3(i nput clki,output clko);reg 1:0 cn t1;/(1)always(posedge clki)beginif(cn t1 = 2) cnt1 = 0;elsecn t1=c nt1+1;endreg o1/*sy nthesis keep */; /(2)always(*)/(3)if(cnt1

16、=0) o1 = 1;else o1 = 0;reg 1:0 cn t2;/(4)always (n egedge clki)beginif(c nt2 = 2) cnt2 =0;elsecn t2 = cn t2 + 1;endreg o2/*s yn thesis keep */;always(*)if(cnt2=0) o2 = 1;/(5)else o2 0) o1 = O;else o1 = 1;或者 always(*) if(cnt1=1)|(cnt1=2) o1 = 0; else o1 = 1;從邏輯角度上講,只要有 1個時鐘周期的高電平輸出即可。(4) cnt2為下降沿分頻用的

17、計數(shù)器值。不同的計數(shù)器要用不同的變量計數(shù),因為在硬件描述語言中,變量對應(yīng)著硬件,一個硬件只能有一個固定功能(邏輯上分時處理的除外)。(5) 同(3),可以有多種寫法,讀者可以進(jìn)行嘗試驗證。剛才使用了 33%的占空比輸出信號相或得到了50%的占空比輸出,同理,使用67%的上升沿分頻和下降沿分頻也可以得到50%的輸出,原理見下圖:下降沿分頻 上升沿分頻使用兩個輸出信號的相“與”操作,可以得到50%的占空比輸出。代碼請讀者自行完成。以上使用的是 3分頻輸出50%的占空比輸出,其實,同樣的原理適用于所有的奇數(shù)分頻。因為奇數(shù)分頻若想得到 50%的占空比輸出,則必然有半個周期的寬度脈沖出現(xiàn)(例如,5分頻,

18、50%占空比,則脈沖寬度為2.5個時鐘周期),而上升沿和下降沿恰好就是半個周期的差別,因此,無論任何奇數(shù),只要用此方法均可得到50%分頻輸出。只是要注意,上升沿計數(shù)和下降沿計數(shù)要同一個時鐘周期開始,這可以通過設(shè)計一個異步的復(fù)位端來實現(xiàn),讀 者需細(xì)心揣摩。半整數(shù)分頻所謂半整數(shù)分頻指的是 N.5分頻,N為整數(shù)。比如2.5分頻。如果輸入頻率為 50Hz,則 輸出為20Hz。在前面的整數(shù)分頻中, 都是以上升(或下降)沿作為計數(shù)的,所以每計數(shù)一個則為一個周期, 不會出現(xiàn).5的效果。這里采用反推導(dǎo)方式來進(jìn)行。假設(shè)已經(jīng)得到了分頻后的結(jié)果。2.5分頻的輸出分頻后的周期根據(jù)剛才的推導(dǎo),直接使用輸入時鐘去計數(shù)不可

19、能得到半整數(shù)的分頻效果。所以必須使用另外的時鐘來計數(shù)。圖中,由于沒有明確指出分頻后的占空比,圖中僅給出半個周期的脈沖寬度,不過周期是固定的,就是2.5個輸入時鐘。為了明確分頻后的周期,圖中以分頻后輸出信號的2分頻給出波形的。這里大膽進(jìn)行一下嘗試,如果說,用輸出信號的2分頻和輸入時鐘做“異或”操作,然后再用異或后的時鐘作為分頻時鐘參與動作,會是什么樣的結(jié)果呢?先給出“異或”后的波形。2.5分頻的輸出分頻后的周期2個周期連接處發(fā)生了最后面一行是異或后的時鐘信號??梢钥闯鰰r鐘的周期在分頻后的 變化。這里用它,代替原輸入時鐘進(jìn)行計數(shù)和分頻嘗試。module freqdiv2dot5(i nput cl

20、ki,output reg clko);reg clkodiv2;always(posedge clko)clkodiv2=!clkodiv2;wire n ewclk;assig n n ewclk= clkiAclkodiv2;reg 1:0 cn tr;always(posedge n ewclk) /(1)beginif(cntr = 2) cntr = 0; /(2)elsecn tr=c ntr+1;endalways(*)if(cntr=0) clko = 1;/(3)else clko = 0;en dmodule代碼說明:(1) 這兒使用新的時鐘信號作為計數(shù)時鐘。(2) 因v

21、erilog不支持小數(shù)2.5,采用整數(shù)3作為計數(shù)的模,經(jīng)驗證可以發(fā)現(xiàn),如果寫成整數(shù)2,則進(jìn)行的是1.5分頻。這里可以修改 2.5 分頻輸出脈沖的寬度,如果改為if(cntr=1),貝U輸出占空比為1.5/2.5??梢酝ㄟ^實踐驗證。仿真波形如下:通過查看計數(shù)器的技術(shù)過程,可以看出,在計數(shù)器的值由2變到0的時候,實際的newclk是沒有脈沖上升沿的。因為這里采用了一個相互關(guān)聯(lián)的連帶性輸出導(dǎo)致了該結(jié)果,可以看出,newclk 間接地產(chǎn)生了 clko ,而clko 又間接地影響了 newclk 的生成。此處無法直接推 導(dǎo)出。有的文獻(xiàn)上把這種方式稱作脈沖扣除電路,它有一套成型的公式,根據(jù)這個公式,任何半

22、整數(shù)分頻都可以很容易設(shè)計出來。N.5分頻電路構(gòu)成。另一種形式的半整數(shù)分頻思想:如果說能夠在一個時鐘周期內(nèi)計數(shù)2個的話,半整數(shù)分頻就可以轉(zhuǎn)化成整數(shù)分頻了。例如2.5分頻,在2.5個周期內(nèi)能計5個數(shù),則,可以在計數(shù)1個的時候輸出高電平,其余值時輸出低電平。那么,怎么樣才能在1個周期內(nèi)計2個數(shù)呢?有的人立刻想至打always ( posedge elk, negedge elk) cntr=cntr + 1;這種方式,這是錯誤的。因為硬件描述語言是對硬件的描述,硬件上不存在的邏輯(即現(xiàn)實的觸發(fā)器都只有1個輸入時鐘),即使語句語法沒有錯誤,也是不能生成硬件的。這里給出 Quartus II對這種方式提

23、出的錯誤報告,供大家參考。Error (10239):VerilogHDL Always Co nstructerror atfreqdiv2dot5.v(23): event con trol cannot test for both positive and n egative edges of variable clk。那么怎樣才能實現(xiàn)上升下降沿同時計數(shù)呢?試著想一下,當(dāng)上升沿計數(shù)后,緊接著下降沿到來,那么下降沿計數(shù)必須是在上升沿計數(shù)值的基礎(chǔ)上進(jìn)行加1操作,同理,再出現(xiàn)上升沿又必須在之前的下降沿計數(shù)基礎(chǔ)上進(jìn)行+1 ;或者換種說法,不管哪個沿計數(shù),都必須在最終計數(shù)器的值上進(jìn)行加1計數(shù)。于是

24、,這里需要設(shè)計多個計數(shù)器,上升沿計數(shù)器posecntr ,下降沿計數(shù)器negcntr,和最終的計數(shù)器的值cntr。以模5計數(shù)為例,這三者之間的關(guān)系是這樣的,cntr 在正常計數(shù)過程中應(yīng)該是posecntr和negcntr中的最大值(誰大取誰);當(dāng)計數(shù)值到達(dá)模值時候,再計數(shù)(無論是上升沿還是下降沿)應(yīng)為0 (假設(shè)做的是加計數(shù),減計數(shù)另論),而不是誰大就取誰了。然后在 0的基礎(chǔ)上繼續(xù)計數(shù)。雙沿計數(shù)器的代碼如下:module dot5_2(clki,cntr);in put clki;reg 2:0 posc ntr;reg 2:0 n egc ntr;always(posedge clki)if(

25、cn tr=4)begi n posc ntr = 0;e ndelsebegi n posc ntr = cntr + 1;e ndalways (n egedge clki)if(cn tr=4)begi n n egc ntr = 0;e ndelsebegi n n egc ntr = n egc ntr)?posc ntr: n egc ntr;en dmodule仿真波形如下:JclkiA ihlhl L_rL_rT_rT_rT_r尋1+j cntrU I可以看出,每個時鐘的上升沿或者是下降沿cntr都進(jìn)行了加1動作,是真正的雙邊沿計數(shù)器。在上面代碼上稍加修改,就得到了半整數(shù)分頻的

26、實現(xiàn)了。module dot5_2(clki,clko);/(1)in put clki;output reg clko;wire 2:0 cntr /*syn thesis keep*/; /(2)/always*/(4)if(cntr = 0)&(cntr =1) clko = 1;else clko 0dkLJl iTTTT.-LT-LT-LT-LT-L-L_T-L_r-L_T-L_TTEJ cntrV iidkcX_r_r l _r l _r l _r l田 negcntrU ii10F*1 pQ5CIltr可以看出輸出信號clko的周期為2.5個輸入時鐘周期。小數(shù)分頻:所謂小數(shù)分頻,

27、就是輸出頻率和輸入頻率的比是小數(shù),由于Verilog HDL的特點,這種情況下輸出肯定不是均勻的,只是從統(tǒng)計學(xué)角度上平均是小數(shù)。例如:3.1分頻,也就是說,假設(shè)輸入了 3.1個脈沖個數(shù),得到一個輸出時鐘周期。很顯然,這種方法是不可能均 勻的,因為Verilog中所有的分頻動作都是在上升沿或者是下降沿的時候進(jìn)行的。只能從統(tǒng)計學(xué)角度考慮,則輸入了31個脈沖的話,輸出端得到10個脈沖,也就是,先做 2個10分頻,再做一個11分頻就可以了。這里可以套用這個公式,假設(shè)要做M.N小數(shù)分頻,可以做M分頻和M+1分頻的組合。假設(shè)需要做 m個M分頻,n個M+1分頻,則:m +n = 10;m*(M) + n*(

28、M +1)=M *10 + N;以3.1分頻為例:m +n = 10;m* (3) + 門氣4) = 3*10+1;得出m=9, n=1 ,也就是做9次3分頻,1次4分頻。需要說明的是,這9次3分頻和1次4分頻是分時工作的, 也就是所,在進(jìn)行3分頻期間, 4分頻模塊不要工作,反之亦然。對于這類問題,最好的辦法就是在一個always 中進(jìn)行,因為多個 always 之間是并行執(zhí)行的,相互控制必然帶來不必要的硬件動作和資源浪費。由于是3分頻和4分頻是分時工作,可以采用一個計數(shù)器,另外,一共需要做10次分頻,這個次數(shù)也需要存下來,這就是第二個計數(shù)器。分別命名為cnt4和cnt10 吧。詳細(xì)內(nèi)容見代碼

29、:代碼說明:(1)前面9次的3分頻時間內(nèi)做三分頻,控制3分頻的個數(shù)為9個(08)(2) 每個分頻模塊中都要分頻輸出,三分頻最后輸出高電平,也可以計數(shù)值為0時刻輸出高電平,其余時刻輸出低電平,這個地方和以前分頻方式相同。(3) 每次分頻之后要對分頻的總個數(shù)進(jìn)行加1,否則會一直停留在三分頻里,4分頻模塊就不會工作了。 當(dāng)三分頻結(jié)束時,進(jìn)入4分頻模塊。如果需要做多次的4分頻,也要寫成 cnt=?&cnt=?的形式。這里只需要做一次,故可以省略寫。(5) 和三分頻一樣,公用cnt4,因為是分時工作。(6) 這里寫成了通用形式,和 (4)原理一樣??梢灾苯訉懗蒫nt10 =0;因為就做一次 4分頻。仿真

30、波形如下:從波形的輸出上看, 在cnt10 計數(shù)值9之前都是3分頻,輸出較密一些。當(dāng)cnt10變?yōu)? 時候就是一個4分頻的輸出,稍稀疏些。在這種方式的分頻, 可以推廣到所有的有理小數(shù)方法,最好是化簡成最簡分?jǐn)?shù)形式,節(jié)約硬件寄存器資源。如果是無理小數(shù)呢?比如 10/3,這個結(jié)果是 3.3333,無理小數(shù)是沒有 辦法套用之前的公式的。不過,只要能表示成分?jǐn)?shù)形式的分頻都可以采用下面這種方式。小數(shù)分頻的另一種形式在之前的分頻中,我門采用的計數(shù)器都是進(jìn)行加1操作的,如果不是加 1呢,比如說加3會是什么效果呢?以下以模16的計數(shù)器演示一下module freqdivfloat_2(i nput clki,

31、output reg 3:0 cntr); always(posedge clki)cntr = cntr + 3;F面是仿真圖en dmodule 1SS.76 di*315.36 “rLrLrLnArLrLrLrLrLrLrLrLrLrLrLrLrLrLrLArLrLrLrLrLJi i這里有兩個光標(biāo),在光標(biāo)中間的數(shù)據(jù)為一個大周期,之后便不停得循環(huán)。 且兩個光標(biāo)之間的數(shù)值由小到大的變化了 3次,也就是說如果做成分頻的話,會輸出 3個脈沖,而輸入時鐘 的個數(shù)為16個,也就是說,如果做分頻的話,分頻的頻率應(yīng)為16/3分頻。也可以這樣理解,當(dāng)cntr計數(shù)器進(jìn)行加1計數(shù)的時候,每計完一個周期輸出一

32、個脈沖的話就是16分頻,那么每次加3,就是16/3分頻。那么,如何確定分頻的輸出呢?在之前的分頻中都是靠計數(shù)值來決定輸出信號電平的高低,而在這種每次加3的計數(shù)過程中,每次計數(shù)的值都是不同的,如何確定呢?第一種方式,從上面的仿真圖上可以看出,當(dāng)進(jìn)入第二周的時候,開始的計數(shù)值一定比第一周值得最后的計數(shù)值小(如:圖中的2比15小),可以在這個時候輸出一個脈沖。實現(xiàn)代碼如下:module freqdiv16_3(i nput clki, output clko);reg 3:0 cntr, cn tr_dly; /(1)always(posedge clki)cntr = cntr + 3;alway

33、s(posedge clki) /(2)cn tr_dly = cntr;assign clko=(cntr12)?1:0;(3)仿真波形如下:TLnnnnrnr.nnnr.nnnnnnnnnnn.n可以看出,輸出的波形沒變,只是提前了一個時鐘周期,因為這里沒有比較,不需要將之前的計數(shù)值暫存。cntr3,這個值可以理解第三種方式,也是最簡單的方式,直接取計數(shù)器的最高位,即 成模16的中間值,且這種方式得到的輸出近似的為方波。 代碼如下:assign clko=cntr3;仿真波形如下:8 X11X1C I4 XT YiaX13Y0 Y3 Y8 Y9 Y12Y15Y2 Y5 Y8雖然波形的脈寬發(fā)

34、生了變化,但個數(shù)沒變。因此,這個結(jié)果也是正確的。分頻系數(shù)大于1小于1.5的另一種分頻方法例如,4/3分頻。這種分頻結(jié)果只能是在多個脈沖之間任意消除一個,像4/3分頻,每4個脈沖中小曲一個脈沖。當(dāng)然,也可以采用前面的計數(shù)方式來實現(xiàn),可以計4個數(shù),前三個計數(shù)中,直接輸出輸入的時鐘,最后計數(shù)的一個周期內(nèi)不輸出。這樣就可以實現(xiàn)4個脈沖輸出3個了,即4/3分頻。下面是另一種方式的實現(xiàn)。先看代碼:代碼說明:(1) 和之前一樣,設(shè)計一個暫存計數(shù)器最高位的變量(2) 將計數(shù)器的最高位延時一個時鐘周期(3) 這個表達(dá)式的結(jié)果需要仔細(xì)分析cntr2的波形,請讀者參照下面仿真圖自行分析。下圖為4/3分頻仿真結(jié)果:從

35、上圖上看,clko_n_n_nLrLTLTLTLnLTLn_rmLrnrLJirLnrLnj-LnLTL_n_rLTLn_rLTrnrLj每4個輸入clki輸出3個周期脈沖,達(dá)到了 4/3分頻的效果。存儲器的設(shè)計與使用寄存器與存儲器的定義在Verilog HDL中,通常使用reg m-1:0 r來定義寄存器r。這個寄存器r的位寬為m位.可以用下圖來說明。1丨丨 1 它占有m個位空間。Reg類型通常用來定義寄存器,但也有例外的情況,例如前面講過的 與門電路可以使用reg定義輸出端:module an dgate2(i nput a, in put b, output reg c);/(1)alw

36、ays(*)c= a & b;en dmodule這里將c定義成reg型,而實際上生成與門電路的時候并沒有寄存器的存在。它只是從語 法角度上滿足 always塊的賦值特點而設(shè)計的,所以,寄存器類型的變量不一定生成寄存器。于是在新的語法標(biāo)準(zhǔn)中,將reg類型重新命名為 variable 類型,并且同時將 wire等連線型命名為net型。同為variable 類型的還有integer型,在32位的操作系統(tǒng)當(dāng)中,它的作用相當(dāng)于reg31:0 ,即32位的寄存器類型變量。例如:integer i;相當(dāng)于reg31:0 i ;。對于多位的寄存器或者是連線型變量的定義,通常也稱作向量的定義,它有高地位順序的

37、。這里用msb_constant_expression:lsb_constant_expression表示向量的通用形式,msb_co nsta nt_expression為最高位常量表達(dá)式,代表范圍的左側(cè)值,lsb_co nsta nt_expression為最低位常量表達(dá)式,代表范圍的右側(cè)值。右側(cè)表達(dá)式的值可以大于、等于、小于左側(cè)表達(dá)式的值。在前面的學(xué)習(xí)之中,大家知道,可以將向量中的部分位取出進(jìn)行單獨操作。 例如:wire 3:0 bus;wire b;assig n b=bus1;這種操作稱為位操作,如果取出多個位,稱作域操作。例如:wire 3:0 bus;wire 1:0 b;ass

38、ign b=bus1:0; /取 bus 的低兩位域。如果說,不允許在向量中進(jìn)行位選擇和域選擇的話,可以使用scalared關(guān)鍵字來定義向量。例如:wire vectored 7:0 bus;那么,這個時候 bus就不可以進(jìn)行位操作和域操作了。vectored 關(guān)鍵字為標(biāo)量類矢量。例如上例bus就是標(biāo)量類矢量。默認(rèn)情況下 wire7:0 bus這個bus向量為矢量類 矢量,它相當(dāng)于 wire scalared 7:0 bus; ,scalared 為矢量類矢量的關(guān)鍵字。在沒有位寬的定義中,都稱為標(biāo)量。如reg a; ,a就是一位標(biāo)量??傊?,標(biāo)量類矢量與矢量類標(biāo)量按位或部分位(域)賦值的矢量稱為

39、標(biāo)量類矢量,這相當(dāng)于多個一位標(biāo)量的集合,標(biāo)量類矢量進(jìn)行類型說明時,需要關(guān)鍵字scalared 。不能按位或域賦值的矢量稱為矢量類矢量,在進(jìn)行類型說明時,需要關(guān)鍵字vectored 。標(biāo)量類矢量的說明可以缺省,就是說沒有關(guān)鍵字 scalared 或vectored的矢量均將被解釋成標(biāo)量類矢量,這是使用最多的一類矢量。由若干個位寬相同向量組合在一起,就可以構(gòu)成存儲器空間。例如:reg 7:0 mymem63:0;這里定義了一個存儲器空間,能存儲數(shù)據(jù)位寬為8位,由64個單元組成??臻g表示如下圖:位寬8位在對存儲器空間進(jìn)行操作的時候,只能對存儲器空間單個單元進(jìn)行操作。 如:mymen1=8 h80;表

40、示將第1個空間存入值 80 (十六進(jìn)制)位寬8位對存儲器空間賦值的方法是分別對存儲器中的每個字賦值。例如:mymem1 = 8hAA; mymem2 = 8h88;mymem3 = 8hFF; mymem4 = 8h22;這樣就可以實現(xiàn)對存儲器中的任意單元進(jìn)行賦值。完整的示例代碼如下。module memory1(addr,data);in put 3:0 addr;output reg 7:0 data;reg7:0 mymem15:0;in teger i;in itial/(1)for(i=0;i16;i=i+1)/(2)mymemi = i;always(*) data1 1 1 1

41、1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 1IIIIIIIIIIIII為存儲器賦值的另一種方法是使用系統(tǒng)任務(wù),所謂系統(tǒng)任務(wù)就是指Verilog 內(nèi)置的一些函數(shù),均已$開頭,如$monitor,他們不能夠生成硬件電路,通常用于仿真。但在存儲器賦值中,可以使用。分別是:1) $readmemb(加載二進(jìn)制值)2) $readmemh(加載十六進(jìn)制值)這些系統(tǒng)任務(wù)從指定的文本文件中讀取數(shù)據(jù)并加載到存儲器。文本文件必須包含相應(yīng)的二進(jìn)制或者十六進(jìn)制數(shù)。例如:$readmemb (ram.patt, mymem);mymem是存儲器空間。文件“ ram.pa

42、tt ”必須包含二進(jìn)制值。 文件也可以包含空白空間和注釋。下面是文件中可能內(nèi)容的實例。11011101111011011000011101111000000001111001001100110011系統(tǒng)任務(wù)$readmemb促使從索引63即mymem最左邊的字索引,開始讀取值。完整代碼及仿真圖如下,為了更能清楚的看到現(xiàn)象,示例中將mymem存儲空間定義成了 16 個:memory.vmodule memory(addr,data);in put 3:0 addr;output reg 7:0 data;reg7:0 mymem15:0;in itial$readmemb(ram.patt, m

43、ymem); /(1)always(*) dataNew,在彈出的窗口中選擇 Memory In itializatio n File,如下圖,然后選擇ok,在彈出的窗口中設(shè)定寬度為8,深度為16,然后點擊 0K。Number of words:Word size:|eCancelOK JNumber of Words & Word Size這時候會彈出界面,在界面中寫入相應(yīng)的內(nèi)容即可。這里隨機(jī)的寫入一些值,如下圖: 巒 Mifl.mifAddr+3+4+6I+7000000000000000010000001Q0000001100000100OOQOOIOt00001111000101118

44、10101010100011101111001110101010010111101100001110111101 10011111將文件保存為Mif1.mif 。如果在存儲器定義的時候使用syn thesis ramn it_file=”Mif1.mif”屬性的話,則在編譯時候就可以按照mif文件中定義的值給存儲器賦初值了。例如:reg7:0 mymem15:0/*syn thesis ramn it_file=”Mif1.mif”*/;使用該屬性時候,需要將mif文件盒verilog文件放在同一個文件夾卜面,否則的話,需要指明mif文件的相對路徑或者絕對路徑。并且注意,這個屬性也是以注釋的形式出現(xiàn) 的,它必須介于存儲器定義語句和分號之間。也可以用下面的形

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論