(原創(chuàng)聲明:該文是作者的原創(chuàng),面向?qū)ο笫?/em>FPGA入門者,后續(xù)會(huì)有進(jìn)階的高級(jí)教程。宗旨是讓每個(gè)想做FPGA的人輕松入門,作者不光讓大家知其然,還要讓大家知其所以然!每個(gè)工程作者都搭建了全自動(dòng)化的仿真環(huán)境,只需要雙擊top_tb.bat文件就可以完成整個(gè)的仿真(前提是安裝了modelsim),降低了初學(xué)者的門檻。如需整個(gè)工程請(qǐng)留言(微信Blue23Light),不收任何費(fèi)用,但是僅供參考,不建議大家獲得資料后從事一些商業(yè)活動(dòng)!)
前面幾課的時(shí)間都是在講計(jì)數(shù)器模塊,相信大家掌握的都差不多了,那這節(jié)課我們開啟一個(gè)新的模塊——狀態(tài)機(jī)。為什么要用狀態(tài)機(jī)呢?這要從硬件設(shè)計(jì)的并行思維講起,F(xiàn)PGA芯片只要一上電,內(nèi)部的所有always模塊開始開始并行執(zhí)行。但是對(duì)于實(shí)際的工程應(yīng)用中,往往需要設(shè)計(jì)硬件來實(shí)現(xiàn)一些具有順序的工作,必須一些算法的實(shí)現(xiàn),在比如一些寄存器的配置,就需要用到狀態(tài)機(jī)的思想。
狀態(tài)機(jī)是一種用于處理具有前后順序的事件的計(jì)算機(jī)模型,包含現(xiàn)態(tài)、條件、動(dòng)作和次態(tài)四個(gè)要素,它可以將一個(gè)復(fù)雜的控制流程分解成多個(gè)互相獨(dú)立的狀態(tài),從而簡(jiǎn)化設(shè)計(jì)過程并提高了系統(tǒng)的可靠性和性能。
現(xiàn)態(tài):系統(tǒng)當(dāng)前所處的狀態(tài)。比如早晨起來你還在家里,這就是你當(dāng)前的狀態(tài);
輸入:一般指外部事件,當(dāng)一個(gè)外部事件發(fā)生后,狀態(tài)機(jī)便會(huì)根據(jù)狀態(tài)轉(zhuǎn)移函數(shù)發(fā)生響應(yīng)。 比如早晨7點(diǎn)30分是每天出門上班的時(shí)間。輸入條件滿足,狀態(tài)就要開始轉(zhuǎn)變。
次態(tài):根據(jù)現(xiàn)態(tài)、輸入、狀態(tài)轉(zhuǎn)移條件所得到的狀態(tài)機(jī)將要跳轉(zhuǎn)至的新狀態(tài)。其中,“次態(tài)”是相對(duì)于“現(xiàn)態(tài)”而言的,一旦被跳轉(zhuǎn)后,“次態(tài)”就轉(zhuǎn)變成新的“現(xiàn)態(tài)”了。比如早晨7點(diǎn)30分去上班,去上班就是次態(tài)。但是7點(diǎn)30分后,你在上班的路上,此時(shí)去上班就變成了現(xiàn)態(tài)。
輸出:由現(xiàn)態(tài)或現(xiàn)態(tài)和輸入共同決定的,但是有時(shí)某一狀態(tài)或者某一輸入改變,輸出并不一定會(huì)發(fā)生變化,帶來的僅僅是狀態(tài)遷移而已。比如輸出是在公司工作,狀態(tài)從家里變成去上班的路上,都沒有達(dá)到輸出的結(jié)果,此時(shí)輸入不變。等到了公司開始工作,那輸出就有變化了。
狀態(tài)機(jī)有兩種類型,一種是摩爾(Moore)型狀態(tài)機(jī):下一狀態(tài)只由當(dāng)前狀態(tài)決定 ;另一種是米勒(Mealy) 型狀態(tài)機(jī):下一狀態(tài)不但與當(dāng)前狀態(tài)有關(guān),還與當(dāng)前輸入值有關(guān) 。
如下所示Moore型狀態(tài)機(jī), 最左側(cè)是次態(tài)組合邏輯電路,通過將狀態(tài)輸出反饋到次態(tài)組合邏輯電路,在和輸入信號(hào)決定,下一狀態(tài)是什么狀態(tài)。中間部分是時(shí)序電路,就是一個(gè)觸發(fā)器,將下一狀態(tài)的值給到現(xiàn)在的狀態(tài)。最右側(cè)是組合輸出邏輯,通過判斷當(dāng)前的狀態(tài),得到輸出。
如下所示Mealy型狀態(tài)機(jī),結(jié)構(gòu)和Moore型狀態(tài)機(jī)類似,只是最右側(cè)的輸出邏輯不僅與當(dāng)前的狀態(tài)有關(guān),還有輸入有關(guān)。
在實(shí)際的應(yīng)用中,Mealy型狀態(tài)機(jī)的輸出與輸入有關(guān),輸出信號(hào)很容易出現(xiàn)毛刺,所以工程設(shè)計(jì)一般采用Moore型狀態(tài)機(jī)。但是Moore型狀態(tài)機(jī)最終的輸出是組合邏輯,還是有產(chǎn)生毛刺的風(fēng)險(xiǎn),目前輸出邏輯大多采用時(shí)序邏輯進(jìn)行實(shí)現(xiàn)。
一般來說,在FPGA中狀態(tài)機(jī)有多種寫法,常見的有一段式、兩段式和三段式狀態(tài)機(jī)。
一段式狀態(tài)機(jī):所有的狀態(tài)變化以及輸出變化都寫在一個(gè)always塊中,在該always塊中既描述狀態(tài)的同步轉(zhuǎn)移,又描述狀態(tài)的輸入條件和輸出。采用一段式狀態(tài)機(jī)會(huì)讓結(jié)構(gòu)和邏輯看起來比較混亂,不推薦使用。
兩段式狀態(tài)機(jī):用兩個(gè)always塊來描述狀態(tài)機(jī)。其中一個(gè)模塊采用同步時(shí)序邏輯描述狀態(tài)轉(zhuǎn)移,另一個(gè)模塊采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件。它需要兩個(gè)狀態(tài)——現(xiàn)態(tài)和次態(tài),然后通過現(xiàn)態(tài)和次態(tài)的轉(zhuǎn)換來實(shí)現(xiàn)時(shí)序邏輯。輸出采用組合邏輯。也不太推薦使用。
三段式狀態(tài)機(jī):用三個(gè)always塊來描述狀態(tài)機(jī)。其中一個(gè)模塊采用同步時(shí)序邏輯描述狀態(tài)轉(zhuǎn)移,另一個(gè)模塊采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件(注意和兩段式的區(qū)別)。第三個(gè)模塊描述狀態(tài)的輸出(既可以用組合邏輯也可以用時(shí)序邏輯,建議使用時(shí)序邏輯)。
所以對(duì)于比較復(fù)雜的狀態(tài)機(jī)建議采用三段式狀態(tài)機(jī)的設(shè)計(jì),比較簡(jiǎn)單的狀態(tài)機(jī)采用改進(jìn)的一段式狀態(tài)機(jī),即用一個(gè)always塊描述狀態(tài)的同步轉(zhuǎn)移,但是用一個(gè)模塊單獨(dú)描述狀態(tài)的輸出(建議使用時(shí)序邏輯)。
下面通過一個(gè)簡(jiǎn)單的工程讓大家在直觀上理解一下狀態(tài)機(jī)的運(yùn)行。工程要求:系統(tǒng)時(shí)鐘是100MHz,低電平復(fù)位,一根輸入線上的電平會(huì)隨機(jī)跳動(dòng),請(qǐng)檢測(cè)出數(shù)字序列1011001。需求很明確,就是把線上特定的序列檢測(cè)出來,線上的狀態(tài)是串行變化的,所以用狀態(tài)機(jī)實(shí)現(xiàn)是比較合適的。
那怎么定義狀態(tài)呢?一般都會(huì)有一個(gè)IDLE狀態(tài),就是系統(tǒng)的初始狀態(tài),還有就是S1,S10,S101,S1011,S10110,S101100,S101101這幾個(gè)狀態(tài),根據(jù)輸入信號(hào)進(jìn)行切換。比如開始檢測(cè)上線的信號(hào)是1,那狀態(tài)就由IDLE轉(zhuǎn)變成S1,如果下一個(gè)時(shí)刻檢測(cè)到的線上的信號(hào)是0,那狀態(tài)就有S1轉(zhuǎn)變成S10,如果這個(gè)時(shí)刻檢測(cè)到的線上的信號(hào)是1,那狀態(tài)就有S1轉(zhuǎn)變成IDEL,以此類推。一般用狀態(tài)轉(zhuǎn)移圖來表示,很直觀明了。如下所示,pi輸入,po是輸出,根據(jù)輸入確定狀態(tài)機(jī)的跳轉(zhuǎn),并標(biāo)明輸出的值。
有了狀態(tài)轉(zhuǎn)移圖,那FPGA代碼的設(shè)計(jì)就很簡(jiǎn)單了,由于本狀態(tài)機(jī)很簡(jiǎn)單,我們采用改進(jìn)的一段狀態(tài)機(jī)進(jìn)行設(shè)計(jì),下面講解一下。pi是輸入的隨機(jī)電平信號(hào),po是檢測(cè)到數(shù)字序列1011001后的輸出信號(hào),po拉高表明檢測(cè)到了期望的序列。定義了7bit的狀態(tài)寄存器state,用來進(jìn)行7個(gè)狀態(tài)的切換,狀態(tài)參數(shù)用的獨(dú)熱碼進(jìn)行定義,獨(dú)熱碼的好處就是任意狀態(tài)的切換指揮有一位變化,降低了數(shù)據(jù)變化出錯(cuò)的機(jī)率。
然后根據(jù)狀態(tài)圖,通過輸入pi的變化設(shè)計(jì)狀態(tài)機(jī)的跳轉(zhuǎn)即可,這兒需要注意一點(diǎn),用了case語(yǔ)句一定要有default,就是一個(gè)默認(rèn)的狀態(tài)。目前的狀態(tài)機(jī)簡(jiǎn)單,可以窮盡所有的狀態(tài),如果對(duì)于復(fù)雜的狀態(tài)機(jī),如果某些狀態(tài)跳轉(zhuǎn)沒有描述,沒有default語(yǔ)句,狀態(tài)機(jī)可能就會(huì)卡死;而有了default語(yǔ)句,遇到未知的跳轉(zhuǎn)條件就會(huì)跳轉(zhuǎn)到這個(gè)默認(rèn)的狀態(tài)。
最后用時(shí)序邏輯設(shè)計(jì)了輸出po,po拉高,就說明檢測(cè)到了期望的序列。
最后看一下仿真結(jié)果,如下所示:下圖是檢測(cè)到期望的1011001序列的一段仿真圖,設(shè)計(jì)的功能是正確的。
文章來源:http://www.zghlxwxcb.cn/news/detail-812658.html
今天又熟悉了一個(gè)新的模塊——狀態(tài)機(jī)。如果能把狀態(tài)機(jī)和計(jì)數(shù)器合理的組合,那就能設(shè)計(jì)出來更多的功能。前期的uart模塊只能發(fā)送和接收單byte的數(shù)據(jù),那如果發(fā)送和接收多byte的數(shù)據(jù)呢?那就要用上狀態(tài)機(jī)了,我們下節(jié)課好好講解。文章來源地址http://www.zghlxwxcb.cn/news/detail-812658.html
到了這里,關(guān)于孩子都能學(xué)會(huì)的FPGA:第八課——狀態(tài)機(jī)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!