最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

2.1FPGA設(shè)計思想-明德?lián)P至簡設(shè)計法原理與應用

2022-12-23 07:34 作者:明德?lián)P易老師  | 我要投稿

1、本節(jié)是講解詳細講解了如何正確的看懂 信號波形

1.1?看波形圖的方法

本書的D觸發(fā)器一章、怎么看FPGA波形一節(jié)中,講述下如何看信號的波形,讀者只需要記住一個規(guī)則:時鐘上升沿看信號,看到的是信號變化前的值。有興趣的讀者,可以返回再細看那一章內(nèi)容。

圖?111

例如圖111,在第4個時鐘上升沿看信號a,則是看到a的值為1(變化前);看信號c,看到c的值為0(變化前);在第5個時鐘上升沿看信號b,看到b的值為1,看信號c,看到c的值為1。

圖?112

例如圖112,在第5個時鐘上升沿看信號dout,其值為1;看信號cnt,其值為1,而不是2。

以上就是看波形的方法,該方法的由來,可以參考本書的D觸發(fā)器一章、怎么看FPGA波形一節(jié)的內(nèi)容。當然,使用該方法是有前提的:所有信號都是同步信號;波形是理想的波形。


1.2?至簡設(shè)計法的四種設(shè)計類型

學習FPGA,最關(guān)鍵的是學什么?

筆者發(fā)現(xiàn),有部分讀者將學習的重點放在接口知識、算法原理等理論知識層面。例如,學習串口的時候,把學習重點放在:什么是串口、串口有什么優(yōu)勢、什么時候用到串口等理論。至于串口代碼,也是借鑒和模仿,原代碼是什么結(jié)構(gòu),自己設(shè)計的代碼也要有這種結(jié)構(gòu),原代碼有什么信號,自己也要有這些信號等。如果該串口功能稍加改動,則陷入完全無從下手的狀態(tài)。

每個工程師都有自己的代碼風格,甚至有些工程師今天的風格和昨天的風格都會不一樣。網(wǎng)絡上的代碼自然也是良莠不齊,一味靠模仿,能成長為高手,那就奇怪了。

明德?lián)P認為,學習FPGA應該是為了提高自己的設(shè)計開發(fā)能力。學習串口,不是為了懂得這個串口,而是通過這個串口例子,學習其設(shè)計思路和方法,以便應用到其他接口上。

明德?lián)P認為,設(shè)計思路和方法,不應過多過雜,而是形成自己的一套模式。今天學少林鐵頭功,明天學武當太極,后天學華山劍法,先不說精力問題,能達到精通狀態(tài)嗎?

明德?lián)P研發(fā)了一套通用的設(shè)計方法:至簡設(shè)計法。

至簡設(shè)計法從宏觀上,適應所有的功能設(shè)計需求。例如,無論是什么功能,我們都先將其轉(zhuǎn)化成需求波形。然后在此基礎(chǔ)上設(shè)計模塊架構(gòu);在模塊架構(gòu)基礎(chǔ)上設(shè)計信號。這步驟都是通用的、是固化的。

至簡設(shè)計法在微觀上,制定了實用的規(guī)范。詳細到什么時候添加信號;怎么添加信號;添加信號名字是什么等,我們都做了詳細的規(guī)定。

大部分的FPGA設(shè)計,明德?lián)P將其歸類下面講述的4種類型。無論多復雜的功能,都是這4種類型的變種。下面通過4個典型案例的設(shè)計,來講述至簡設(shè)計法。


1.2.1?至簡設(shè)計法設(shè)計類型1

案例1:當收到en=1后,dout產(chǎn)生一個寬度為10個時鐘周期的高電平脈沖。圖113是功能波形圖。

圖 113

根據(jù)看波形規(guī)則,在第3個時鐘上沿的時候,看到en==1,根據(jù)功能要求,上升沿之后dout就會變?yōu)?。10個時鐘周期后,即第13個時鐘上升沿時,dout將變?yōu)?。

推理1:從功能要求中,看到數(shù)字10,我們就知道要計數(shù),要使用計數(shù)器。

推理2:10個是指dout==1的次數(shù)為10個時鐘周期,所以該計數(shù)器數(shù)的是dout==1的次數(shù),因此看到dout==1時,計數(shù)器就會加1。

此外,明德?lián)P還制定了計數(shù)器要遵守的原則。

原則1:初值一定為0。復位后,計數(shù)器一定要為0。

原則2:數(shù)到最后一個時,要及時清0。

根據(jù)上面2個推理和原則,補充計數(shù)器信號cnt,更新后的波形如圖114。

圖?114

從功能要求和波形圖,我們確認,計數(shù)器cnt是對dout==1進行計數(shù),并且一共數(shù)10個。為此,在GVIM編輯器中輸 入“Jsq”并回車,將出現(xiàn)圖115的代碼。

圖?115

在第13行,輸入dout==1,在第14行代碼中,輸入10-1,這樣就完成了計數(shù)器設(shè)計,如圖?116。

圖?116

add_cnt表示:計數(shù)器cnt加1條件。

end_cnt表示:計數(shù)器數(shù)到最后一個,也稱之為結(jié)束條件。

圖116第1~第11代碼功能:時鐘上升沿時,如果計數(shù)器加1條件有效,并且是數(shù)到最后一個,則計數(shù)器清零;如果計數(shù)器加1條件有效,但不是最后一個,則計數(shù)器就加1;其他時候,計數(shù)器就保持不變。

那么加1條件,即add_cnt是什么呢?在第13行進行了定義。該行代碼表示,dout==1就是計數(shù)器的加1條件。

那么結(jié)束條件,即end_cnt是什么呢?在第14行進行了定義。該行代碼表示,數(shù)到10個就結(jié)束。其中我們關(guān)注的是那個數(shù)字10,而-1是固定的格式。

add_cnt && cnt==10-1,含義是表示“數(shù)到第10個的時候”,add_cnt && cnt==x-1表示“數(shù)到第?x個的時候”。記住這個規(guī)則。end_cnt==1也表示數(shù)完了。

設(shè)計好計數(shù)器cnt后,我們就可以設(shè)計輸出信號dout了。仔細分析dout,該信號有兩個變化點:變1和變0。我們分 析原因,dout變1是由于收到en==1;dout變0,則是數(shù)到了10個或者是數(shù)完了。所以綜上所述,dout的代碼是:


至此,我們完成了主體程序的設(shè)計,接下來補充module的其他部分。

將module的名稱定義為my_ex1。并且我們已經(jīng)知道該模塊有4個信號:clk、rst_n、en和dout。為此,代碼如下:


其中clk、rst_n和en是輸入信號,dout是輸出信號,并且4個信號都是1比特的,根據(jù)這些信息,我們補充輸入輸出端口定義。代碼如下:


接下來定義信號類型。

cnt是用always產(chǎn)生的信號,因此類型為reg。cnt計數(shù)的最大值為9,需要用4根線表示,即位寬是4位。add_cnt和end_cnt都是用assign方式設(shè)計的,因此類型為wire。并且其值是0或者1,1個線表示即可。因此代碼如下:


dout是用always方式設(shè)計的,因此類型為reg。并且其值是0或者1,1根線表示即可。因此代碼如下:


至此,整個代碼的設(shè)計工作已經(jīng)完成。整體代碼如下:

1.2.2?至簡設(shè)計法設(shè)計類型2

例2.?當收到en=1后,dout間隔3個時鐘后,產(chǎn)生寬度為2個時鐘周期的高電平脈沖。

圖?117

如上面波形圖所示,在第3個時鐘上升沿看到en==1,間隔?3個時鐘后,dout變1,再過2個時鐘后,dout變0。

根據(jù)案例1的經(jīng)驗,出現(xiàn)大于1的數(shù)字時,就需要計數(shù)。我們這里有數(shù)字2和3,建議的計數(shù)方式如下。

圖?118

當然,其他計數(shù)方式最終也能實現(xiàn)功能。但明德?lián)P的總結(jié)是上面方式最好,實現(xiàn)的代碼將是最簡的,其他方式則稍微復雜。

接下來判斷計數(shù)器的加1條件。與案例1不同的是,計數(shù)器加1區(qū)域如下圖陰影部分,但圖中沒有任何信號來指示此區(qū)域 。

圖?119

為此,添加一個名字為“flag_add”的信號,剛好覆蓋了陰影部分,如下圖。

圖?120

補充該信號后,計數(shù)器的加1條件就變?yōu)閒lag_add==1,并且是數(shù)5個。代碼如下:


flag_add有2個變化點,變1和變0。變1的條件是收到en==1,變0的條件是計數(shù)器數(shù)完了,因此代碼如下:


dout也有2個變化點:變1和變0。變1的條件是“3個間隔之后”,也就是“數(shù)到3個的時候”;變0的條件是數(shù)完了。代碼如下:


至此,我們完成了主體程序的設(shè)計,接下來是補充module的其他部分。

將module的名稱定義為my_ex2。并且我們已經(jīng)知道該模塊有4個信號:clk、rst_n、en和dout。為此,代碼如下:



其中clk、rst_n和en是輸入信號,dout是輸出信號,并且4個信號都是1比特的,根據(jù)這些信息,我們補充輸入輸出端口定義。代碼如下:


接下來定義信號類型。

cnt是用always產(chǎn)生的信號,因此類型為reg。cnt計數(shù)的最大值為4,需要用3根線表示,即位寬是3位。add_cnt和end_cnt都是用assign方式設(shè)計的,因此類型為wire。并且其值是0或者1,1個線表示即可。因此代碼如下:


dout是用always方式設(shè)計的,因此類型為reg。并且其值是0或者1,1根線表示即可。因此代碼如下:


flag_add是用always方式設(shè)計的,因此類型為reg。并且其值是0或者1,1根線表示即可。因此代碼如下:


至此,整個代碼的設(shè)計工作已經(jīng)完成。整體代碼如下:


經(jīng)過這個案例,我們做一下總結(jié):在設(shè)計計數(shù)器的時候,如果計數(shù)區(qū)域沒有信號來表示時,可補充一個信號flag_add。


1.2.3?至簡設(shè)計法設(shè)計類型3

案例3.?當收到en1=1時,dout產(chǎn)生3個時鐘周期的高電平脈沖;當收到en2==1時,dout產(chǎn)生2個周期的高電平脈沖 。下面波形圖描述了該功能。

圖?121

圖中,第3個時鐘上升沿收到en1==1,所以dout變1并且持續(xù)3個時鐘周期;在第9個時鐘上升沿看到en2==1,所以?dout變1并且持續(xù)2個時鐘周期。注意,en1==1和en2==1的出現(xiàn)是沒有順序的。

有讀者可能會問,如果en1==1和en2==1同時出現(xiàn),或者說在dout==1期間,出現(xiàn)了en1==1或者en2==1,該怎么辦?請不要考慮這種情況,本案例假設(shè)永遠不會出現(xiàn)該情況。明德?lián)P在模塊劃分規(guī)范時,會要求各個模塊之間配合清楚,這有助于簡化我們的設(shè)計,精簡系統(tǒng)。

看到大于1的數(shù)字,就知道要計數(shù)。推薦的計數(shù)方式如下:

圖?122

首先,不要用2個計數(shù)器分別計兩種情況。這是因為這2個計數(shù)器都是不同時計數(shù)的,是可以合并的。同時,我們可以知道,這兩種情況都是計算dout==1的次數(shù)。

在確認計數(shù)器數(shù)多少個時,我們遇到了問題。因為這個計數(shù)器有時候數(shù)到3個就清零(en1==1觸發(fā)的波形),有時候數(shù)到2個就清零(en2==1觸發(fā) 的波形)。此時,我們建議你用變量x代替,即數(shù)到x個。注意,verilog是沒有變量的概念的,這個變量,是明德?lián)P提出的一個設(shè)計概念,x本質(zhì)上還是一個信號。

引入變量有什么用呢?設(shè)計計數(shù)器時就方便了,該計數(shù)器加1條件是dout==1,數(shù)x個就結(jié)束,因此代碼如下:


甚至我們還可以寫出dout的代碼,dout變1的條件是:en1==1或者en2==1;變0的條件是:計數(shù)器數(shù)完了。所以代碼如下:


我們再設(shè)計一下變量x,我們知道計數(shù)器en1==1觸發(fā)的時候數(shù)3個就清零,en2==1觸發(fā)的時候數(shù)到2個就清零,為此增加一個信號flag_sel來區(qū)分這兩種情況,flag_sel==0表示是en1==1觸發(fā)的,flag_sel==1表示是en2==1觸發(fā)的,波形如下:

圖?123

flag_sel變0的條件是遇到en1==1,flag_sel變1的條件是遇到en2==1,為此flag_sel的代碼如下。


有了flag_sel,我們就好區(qū)分x的值了。?flag_sel為0時,x為3(數(shù)3個清零);flag_sel為1時,x為2(數(shù)2個清零),此時要用組合邏輯設(shè)計x,不然會出錯的。代碼如下:


至此,本工程的主體程序已經(jīng)設(shè)計完畢,本題,我們使用了變量x,這是明德?lián)P的至簡設(shè)計方法中的變量法。

主體程序完成后,我們補充模塊的其他部分。

將module的名稱定義為my_ex3。并且我們已經(jīng)知道該模塊有5個信號:clk、rst_n、en1、en2和dout。為此 ,代碼如下:



其中clk、rst_n、en1和en2是輸入信號,dout是輸出信號,并且5個信號都是1比特的,根據(jù)這些信息,我們補充輸入輸出端口定義。代碼如下:


接下來定義信號類型。

cnt是用always產(chǎn)生的信號,因此類型為reg。cnt計數(shù)的最大值為2,需要用2根線表示,即位寬是2位。add_cnt和end_cnt都是用assign方式設(shè)計的,因此類型為wire。并且其值是0或者1,1個線表示即可。因此代碼如下:


dout是用always方式設(shè)計的,因此類型為reg。并且其值是0或者1,1根線表示即可。因此代碼如下:


flag_sel是用always方式設(shè)計的,因此類型為reg。并且其值是0或者1,1根線表示即可。因此代碼如下:


x是用always方式設(shè)計的,因此類型為reg,并且其值最大為3,用2根線表示即可。因此代碼如下:


至此,整個代碼的設(shè)計工作已經(jīng)完成。整體代碼如下:


總結(jié):設(shè)計時,我們不要受具體數(shù)字的影響,而是仔細識別信號的一致性動作,然后利用變量法來設(shè)計。這樣就能設(shè)計出精妙的代碼。


1.2.4?至簡設(shè)計法設(shè)計類型4

案例4.?當收到en=1時,dout間隔1個時鐘后,產(chǎn)生2個時鐘周期的高電平脈沖,并且重復3次。

圖?124

上面波形圖顯示了描述的功能。第3個時鐘上升沿收到en==1,所以dout間隔1個時鐘后變1并且持續(xù)2個時鐘周期,這個動作重復3次,結(jié)束。

看到大于1的數(shù)字,就知道要計數(shù)。下面的計數(shù)方式非常普遍:

圖?125

即用一個計數(shù)器,從頭數(shù)到尾。這個計數(shù)器的設(shè)計很簡單,但產(chǎn)生dout信號就不容易了。

明德?lián)P推薦的計數(shù)方式如下:

圖?126

利用2個計數(shù)器。cnt0就如案例2一樣,數(shù)的是間隔和高電平時鐘;而計數(shù)器cnt1數(shù)的是重復次數(shù)。

如案例2相同,需要添加信號flag_add來指示cnt0的加1區(qū)域,波形如下圖。

圖?127

所以cnt0的加1條件是flag_add==1,計數(shù)3個就清零。

仔細觀察cnt1可以看到,每次cnt0數(shù)完后,cnt1就會加1。所以cnt1的加1條件是end_cnt0,計數(shù)3個就清零。從而我們可以設(shè)計出cnt0和cnt1的代碼,輸入Jsq2,即可調(diào)出模板。


flag_add有兩個變化點:變1和變0。變1是因為en==1,變0是因為重復次數(shù)都完了,也就是end_cnt1。所以flag_add代碼如下。


dout有兩個變化點:變1和變0。在cnt0數(shù)到1時(一個間隔)時變1,在cnt0數(shù)完時變0,所以dout的代碼如下。


至此,本工程的主體程序已經(jīng)設(shè)計完畢,之后需要讀者補充信號定義、輸入輸出定義了。

將module的名稱定義為my_ex3。并且我們已經(jīng)知道該模塊有5個信號:clk、rst_n、en和dout。為此,代碼如下:


其中clk、rst_n、en是輸入信號,dout是輸出信號,并且4個信號都是1比特的,根據(jù)這些信息,我們補充輸入輸出端口定義。代碼如下:



接下來定義信號類型。

cnt0是用always產(chǎn)生的信號,因此類型為reg。cnt0計數(shù)的最大值為2,需要用2根線表示,即位寬是?2位。add_cnt0和end_cnt0都是用assign方式設(shè)計的,因此類型為wire。并且其值是?0或者1,1個線表示即可。因此代碼如下:


cnt1是用always產(chǎn)生的信號,因此類型為reg。cnt1計數(shù)的 最大值為2,需要用2根線表示,即位寬是2位。?add_cnt1和end_cnt1都是用assign方式設(shè)計的,因此類型為wire。并且其值是0或者1,1個線表示即可。因此代碼如下:


dout是用always方式設(shè)計的,因此類型為reg。并且其值是0或者1,1根線表示即可。因此代碼如下:


flag_add是用always方式設(shè)計的,因此類型為reg。并且其值是0或者1,1根線表示即可。因此代碼如下:


至此,整個代碼的設(shè)計工作已經(jīng)完成。整體代碼如下:


本題中,我們設(shè)計了2個計數(shù)器 ,從而使得dout的設(shè)計非常簡單。計數(shù)器的組合使用,對設(shè)計的復雜度有非常大的影響。合理和正確使用,將能設(shè)計出賞心悅目的代碼。


1.3?至簡設(shè)計法高效設(shè)計

上一節(jié)我們描述了四種情況下的設(shè)計方法。在闡述案例過程中,我們畫出了大量的波形圖。有讀者可能會問,在工作中,我們是不是也需要先大量地畫波形圖,再來寫代碼呢?

不是的!工作中,我們要設(shè)計的系統(tǒng)更加的復雜,一個模塊的信號也非常地多,如果我們每個模塊都要畫波形圖,這不是明德?lián)P提倡的至簡設(shè)計。何況,功能一復雜,畫出來的波形信號也是相當?shù)囟?,也容易迷糊當中?/p>

在上一節(jié)中,我們畫波形圖的目的,是為了讓讀者更清晰地理解功能、計數(shù)器和信號的關(guān)系。如果我們牢記明德?lián)P的規(guī)則。或者熟練掌握后,波形存在心中即可。我們的設(shè)計將非常簡單。

FPGA其實不是波形設(shè)計,而是功能設(shè)計,講究的是邏輯,講究的是因果關(guān)系。功能設(shè)計就是根據(jù)功能需求,編寫我們的設(shè)計代碼。我們以上一節(jié)中的案例4為例,說明什么叫功能設(shè)計。

案例4的功能要求是:當收到en=1時,dout間隔1個時鐘后,產(chǎn)生2個時鐘周期的高電平脈沖,并且重復3次。

由題意可知,要對“間隔” 和“高電平”個數(shù)進行計數(shù),但沒有信號表示“高隔”,為此想出補充一個信號?flag_add,用來表示計數(shù)區(qū)域。間隔時間+高電平時間,得到計數(shù)器數(shù)3個。

圖?128

我們看到重復3次這一句話,這就說明還有一個計數(shù)器計數(shù)重復的次數(shù)。自然地想到,每完成一次就加1,一共加3次。得到代碼如下。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??129


在設(shè)計計數(shù)器0的時候,新增了信號flag_add。那進一步思考,什么時候要產(chǎn)生動作,那就讓flag_add為1。自然, 從題意可知,en==1是開始,重復次數(shù)完了,那就結(jié)束,不用再產(chǎn)生信號。所以flag_add代碼。


最后我們再來設(shè)計dout,由題意可知,每次均是間隔1個之后dout變1,2個時鐘之后變0。那用什么來數(shù)這個1和2呢?cnt0。綜合起來,就是說cnt0數(shù)到1個后,dout變1,數(shù)完后變0。


總結(jié):從功能的文字描述中出發(fā),根據(jù)功能要求來設(shè)計代碼。在設(shè)計時,一定要理解清楚信號的因果關(guān)系,例如為什么變0,為什么變1,從功能說明中找答案。經(jīng)常訓練這種思考和設(shè)計方式,幾分鐘就能設(shè)計出精妙的代碼,而且因果關(guān)系、邏輯關(guān)系清楚,幾乎不存在出錯的可能,從而寫出所想即所得的代碼。




2.1FPGA設(shè)計思想-明德?lián)P至簡設(shè)計法原理與應用的評論 (共 條)

分享到微博請遵守國家法律
江津市| 常州市| 深泽县| 太白县| 南丹县| 元江| 汤原县| 通化县| 正定县| 大石桥市| 涿州市| 黄石市| 那坡县| 驻马店市| 老河口市| 和田县| 改则县| 哈密市| 天祝| 达州市| 黄浦区| 泰州市| 子洲县| 泸定县| 泰宁县| 清苑县| 仁怀市| 阳西县| 水城县| 连平县| 巴楚县| 双流县| 元朗区| 常宁市| 长治县| 龙江县| 金昌市| 鸡西市| 伊宁市| 乌海市| 绥滨县|