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