從VHDL代碼到真實(shí)硬件:設計有限狀態(tài)機
學(xué)習如何通過(guò)創(chuàng )建一個(gè)4位二進(jìn)制計數器,在VHDL中實(shí)現有限狀態(tài)機。編譯后,它將在連接到帶有輸入開(kāi)關(guān)和LED顯示器的自定義PCB的Altera CPLD開(kāi)發(fā)板上運行。
本文引用地址:http://dyxdggzs.com/article/202409/462551.htm本項目是我“從VHDL代碼到真實(shí)硬件”系列的第二部分,在該系列中,我們使用基于硬件的方法和可編程邏輯IC設計簡(jiǎn)單的電子系統。這些系統為重要設計概念提供了極好的介紹,這些概念也可以應用于更復雜的項目。
有限狀態(tài)機項目概述
在這個(gè)項目中,我將介紹有限狀態(tài)機(FSM)的開(kāi)發(fā)。具體來(lái)說(shuō),我將構建一個(gè)4位二進(jìn)制計數器,帶有四個(gè)輸出LED和一個(gè)四位DIP開(kāi)關(guān)模式輸入
邏輯將使用VHDL(一種硬件描述編程語(yǔ)言)編寫(xiě),并上傳到復雜可編程邏輯(CPLD)芯片。CPLD是一種可重復編程的現成邏輯門(mén)IC,類(lèi)似于FPGA。
本項目將使用與我之前設計的8位算術(shù)邏輯單元(ALU)相同的硬件和軟件設置:
Altera Max II EPM240 CPLD開(kāi)發(fā)板,
英特爾的Quartus Prime Lite版IDE。
如果您想復習可編程邏輯集成電路和Quartus Prime套件的基礎知識,您需要查看之前的項目。
什么是有限狀態(tài)機?
在深入設計之前,我們先快速回顧一下有限狀態(tài)機。有限狀態(tài)機是順序邏輯電路的抽象數學(xué)模型,在任何給定時(shí)刻,它只能在有限數量的狀態(tài)中運行。
FSM可以在每個(gè)時(shí)鐘周期在其狀態(tài)之間轉換一次。下一個(gè)狀態(tài)基于外部輸入和當前狀態(tài)(這意味著(zhù)它使用了記憶邏輯)。
有限狀態(tài)機可用于檢測或生成序列,是電梯、交通燈、自動(dòng)售貨機和電子鎖等系統的基礎。
二進(jìn)制計數器
有限狀態(tài)機(FSM)的一種特殊實(shí)現是二進(jìn)制計數器。這些電路的設計目標是迭代并顯示所需的二進(jìn)制數序列,通常使用一系列相互連接的觸發(fā)器構建。二進(jìn)制計數器的每個(gè)新?tīng)顟B(tài)都必須由輸入脈沖觸發(fā),該脈沖可以來(lái)自外部源或電路自己的時(shí)鐘信號。
有了這些背景知識,讓我們深入了解一下4位二進(jìn)制計數器的代碼。
FSM二進(jìn)制計數器的VHDL代碼
我們將在VHDL文件的頂部聲明幾個(gè)庫,開(kāi)始為二進(jìn)制計數器編寫(xiě)代碼:
港口定義
接下來(lái),我們將為我們的電路創(chuàng )建一個(gè)名為fsm的實(shí)體,并定義其輸入和輸出端口:
在此代碼片段中,我們定義了:
流程和數據類(lèi)型定義
既然我們已經(jīng)定義了FSM實(shí)體,我們就可以為我們的電路創(chuàng )建一個(gè)架構。這個(gè)架構將有三個(gè)過(guò)程:
狀態(tài)記憶。
下一個(gè)狀態(tài)邏輯。
輸出邏輯。
在創(chuàng )建這些進(jìn)程之前,我們需要為我們的狀態(tài)定義一個(gè)新的數據類(lèi)型,并為該數據類(lèi)型定義兩個(gè)信號變量,用于記憶當前狀態(tài)和下一個(gè)狀態(tài)(將它們視為寄存器)。
狀態(tài)記憶過(guò)程
現在我們可以創(chuàng )建第一個(gè)名為STATE_MEMORY的進(jìn)程。使用IF語(yǔ)句,它會(huì )在CLK信號的每個(gè)上升沿將下一個(gè)狀態(tài)的值寫(xiě)入當前狀態(tài)變量。
下一個(gè)狀態(tài)邏輯過(guò)程
我們將使用SEL輸入端口和CURRENT_STATE信號創(chuàng )建一個(gè)名為NEXT_STATE_LOGIC的進(jìn)程。在這個(gè)進(jìn)程中,我們?yōu)楫斍盃顟B(tài)調用一個(gè)CASE-WHEN語(yǔ)句。我們在第一個(gè)CASE-WHEN語(yǔ)句的每個(gè)WHEN子句中嵌套其他CASE-WHEN語(yǔ)句以用于模式。
這樣,我們就有了一個(gè)架構,它首先檢查FSM的當前狀態(tài),然后從SEL端口讀取值。當這個(gè)過(guò)程完成時(shí),最后一個(gè)嵌套的WHEN子句將根據我們的代碼(對正在計數的序列)將正確的下一個(gè)狀態(tài)值寫(xiě)入NEXT_STATE信號
下面的代碼塊顯示了一個(gè)簡(jiǎn)單的向上計數器,當SEL端口值等于“0000”時(shí),該計數器處于活動(dòng)狀態(tài)。為了簡(jiǎn)潔起見(jiàn),這里只顯示了一些重復的case語(yǔ)句,但完整的代碼將在下面提供。
跳過(guò)案例,C3到C13是相似的,我們到達NEXT_STATE_LOGIC過(guò)程的末尾,我們有:
輸出邏輯流程
最后,為了在4位LED顯示屏上輸出當前狀態(tài),我們需要編寫(xiě)另一個(gè)名為OUTPUT_LOGIC的進(jìn)程。它枚舉了我們之前定義的每種狀態(tài)類(lèi)型,并配以相應的4位二進(jìn)制數。
這同樣是通過(guò)使用CURRENT_STATE信號并調用另一個(gè)CASE-WHEN語(yǔ)句來(lái)完成的。CNT輸出表示當前狀態(tài)作為其4位二進(jìn)制對應物:
編譯代碼
編寫(xiě)代碼后,我們首先需要編譯它。然后,我們必須使用Quartus的Pin Planner工具,將我們在程序中定義的端口分配到Altera CPLD的物理引腳上,使用表1中顯示的映射。
表1. 端口到引腳映射
上傳到開(kāi)發(fā)板
接下來(lái),我們需要再次編譯代碼,然后才能最終將其上傳到開(kāi)發(fā)板上。此過(guò)程是使用通過(guò)JTAG連接到Altera MAX II的USB Blaster進(jìn)行的,如圖1所示。
Altera板和USB Blaster連接
圖1. Altera板和USB Blaster連接。圖片由Kristijan Nelkovski提供
添加外部觸發(fā)器
將代碼上傳到Altera板后,我們需要添加一個(gè)時(shí)鐘信號——某種類(lèi)型的外部觸發(fā)器,使我們的計數器能夠遍歷其狀態(tài)。在這里,我要稍微作弊一下,使用運行默認Arduino Blink草圖的Raspberry Pi Pico,它充當我們電路的粗糙時(shí)鐘源。
您可以使用任何其他MCU開(kāi)發(fā)板來(lái)實(shí)現此功能;只需確保向Altera MAX II發(fā)送3.3 V邏輯電平信號即可。Raspberry Pi Pico本身輸出3.3 V邏輯信號。
在我們的電路中,Blink草圖將提供0.5 Hz的時(shí)鐘信號(您可以在A(yíng)rduino代碼的延遲部分更改頻率)。它不會(huì )讓LED閃爍一秒鐘,然后再熄滅一秒鐘,而是告訴我們的同步電路何時(shí)切換到其下一個(gè)狀態(tài),如我們的VHDL代碼中所定義。
PCB電路圖
圖2中的示意圖顯示了項目的完整電路圖。在這里,每個(gè)LED都通過(guò)限流電阻連接到輸出引腳,連接到輸入引腳的DIP開(kāi)關(guān)的每個(gè)觸點(diǎn)都通過(guò)電阻網(wǎng)絡(luò )下拉到地。然后,時(shí)鐘引腳連接到運行Blink的微控制器板上的假定LED引腳。
4位二進(jìn)制計數器項目的電路原理圖
圖2:4位二進(jìn)制計數器項目的電路示意圖。圖片由Kristijan Nelkovski提供
在將所有東西連接起來(lái)并為電路提供足夠的電源后,我們的FSM計數器應根據通過(guò)DIP開(kāi)關(guān)選擇的計數模式,開(kāi)始在其四個(gè)LED上迭代不同的二進(jìn)制序列。
設計其他計數序列
對于SEL輸入的其他值,您可以創(chuàng )建任意4位數字序列。在本文末尾的完整代碼下載中,我包含了16種計數模式,可以使用表2中描述的4位SEL輸入進(jìn)行選擇。
表2. 計數模式的SEL控制
注意:從技術(shù)上講,斐波那契數列應該重復出現1,但在這個(gè)簡(jiǎn)單的項目中,這些序列中只有一個(gè)1。
物料清單
表3包含項目物料清單(BOM)。
表3. 4位計數器物料清單。
輪到你了!
在這個(gè)項目中,我們使用VHDL硬件描述語(yǔ)言創(chuàng )建了一個(gè)有限狀態(tài)機電路,并在CPLD開(kāi)發(fā)板上運行。本系列文章的目標是介紹可編程邏輯,并使用真實(shí)硬件而不是電路圖和計算機模擬來(lái)深入了解FPGA組件的實(shí)際使用。
如果你復制這個(gè)項目,你可以隨時(shí)修改代碼,切換計數模式,或者根據需要添加和刪除不同的序列。在下面的評論中分享你的想法和修改!
評論