1 項目背景 技術(shù)交流群 :544453837 在使用教學(xué)板的串口前,需要安裝CH340的驅動(dòng)程序。下載后直接解壓安裝就可以了。 當用USB線(xiàn)接上電腦和教學(xué)板,并且教學(xué)板上電后,打開(kāi)電腦的“設備管理器”,將會(huì )看到如下顯示。當出現該顯示時(shí),表示驅程安裝成功并且已經(jīng)被電腦正確地識別。 我們可以從“設備管理器”中查看串口號,如下圖所示。圖中表示該串口號為XX。我們可以修改串口號,方法是:XXXXXX。 串口:可以選擇串口號,支持串口號1~4。如果連接的串口號不在此范圍,則需要從設備管理器中修改串口號,詳細見(jiàn)本章前面的描述。 波特率:選擇串口的波特率,支持9600、19200、38400、57600、115200。該選項影響了每一位碼元占用的時(shí)間。 校驗位:可選擇沒(méi)有檢驗位、奇校驗和偶校驗。 數據位:可以設置數據位的位數,可選擇4~8位的數據拉。 停止位:可以設置停止位的時(shí)間長(cháng)度。有1位、1.5位和2位可供選擇。 打開(kāi)/關(guān)閉串口:用來(lái)打開(kāi)和關(guān)閉串口。打開(kāi)軟件時(shí),串口默認是關(guān)閉狀態(tài)。注意,一定要設置好參數后,才能打開(kāi)串口;一定要關(guān)閉串口后,才能關(guān)掉教學(xué)板電源和撥掉USB線(xiàn)。 十六進(jìn)制顯示:本軟件支持ASCII顯示和十六進(jìn)制顯示。勾選后,用十六進(jìn)制顯示。例如FPGA發(fā)送8’b00110001,本軟件收到后會(huì )顯示31。如果不勾選,則是用ASCII碼顯示。下圖就是ASCII表。FPGA發(fā)送8’b00110001,即下表中十六進(jìn)制的31,它所對應的圖形為1,所以軟件只會(huì )顯示1。假設FPGA發(fā)送的是8’h00100011,即下表中十六進(jìn)制的23,它所對應的是圖形是#,所示軟件會(huì )顯示#。 十六進(jìn)制發(fā)送:本軟件支持ASCII發(fā)送和十六進(jìn)制發(fā)送。勾選后,用十六進(jìn)制發(fā)送。例如填寫(xiě)“31”,按手動(dòng)發(fā)送,那么FPGA收到的值是8’b00110001。如果不勾選,則是用ASCII碼發(fā)送。例如填寫(xiě)“31”,按下手動(dòng)發(fā)送,軟件將首先發(fā)送ASCII碼“3”所對應的十六進(jìn)制值8’h33,再發(fā)送ASCII碼“1”所對應的十六進(jìn)制值8’h31。也就是FPGA將收到兩個(gè)字節數據:8’h33和8’h31。 2 設計目標 上板效果圖如下圖所示 3 設計實(shí)現3.1 頂層信號 綜上所述,我們這個(gè)工程需要4個(gè)信號,時(shí)鐘clk,復位rst_n,串口輸入信號rx_uart和輸出控制LED燈的8位信號led。 將module的名稱(chēng)定義為uart。并且我們已經(jīng)知道該模塊有四個(gè)信號:clk、rst_n、rx_uart和dout。為此,代碼如下: 其中clk、rst_n和rx_uart是輸入信號,dout是輸出信號,其中clk、rst_n、rx_uart的值是0或者1,一根線(xiàn)即可,dout為8位位寬的,根據這些信息,我們補充輸入輸出端口定義。代碼如下: 3.2 信號設計 我們先分析要實(shí)現的功能,led信號控制了8個(gè)LED燈的亮滅,而具體哪些燈亮哪些燈滅,是取決于串口過(guò)來(lái)的數據。那串口過(guò)來(lái)的數據,是如何告知FPGA,并與led對應起來(lái)呢?我們可以看一下串口過(guò)來(lái)的時(shí)序。 上面波形是CH340控制的信號rx_uart。如果CH340要發(fā)送一個(gè)8位數據data,它首先會(huì )將信號rx_uart變0并持續一段時(shí)間(起啟位),然后發(fā)送data[0]并持續一段時(shí)間,然后發(fā)送data[1]并持續一段時(shí)間,以此類(lèi)推,發(fā)送data[7]并持續一段時(shí)間,最后CH340將rx_uart為1并持續一段時(shí)間(結束位)。這樣CH340就完成了數據的發(fā)送。 例如,CH340要發(fā)送的數據data=8’h00110001,則rx_uart的波形如下。 再考慮一下時(shí)間信息。由于波特率是9600,那么每位持續的時(shí)間是1s/9600=104166ns。將時(shí)間信息補上波形。 本開(kāi)發(fā)板的晶振時(shí)鐘是50Mz,104166ns/20ns 約等于5208個(gè)時(shí)鐘周期。也就是說(shuō)上面波形中,每個(gè)比特的持續時(shí)間約等于5208個(gè)時(shí)鐘周期。需要注意的是,5208只是一個(gè)估計的大概數字,實(shí)際情況會(huì )有偏差。同時(shí),我們還有計數這是第幾個(gè)比特,用于讓我們判斷是開(kāi)始位、數據位和停止位等。 可以看出,我們需要2個(gè)計數器,1個(gè)計數器用于計算1比特的位寬長(cháng)度:5208個(gè)時(shí)鐘周期,命名為cnt0;另一個(gè)用于計算有多少個(gè)比特,命名為cnt1。 很明顯cnt0每次都是數5208個(gè),但cnt0的加1條件需要仔細分析。我們很清楚cnt0的加1區域是下面的灰度地方。 目前沒(méi)有任何信號可以區分出此區域。參考至簡(jiǎn)設計法案例2的方法,設計一個(gè)信號flag_add,當其為1表示上述灰度區域,即cnt0的加1區域。 有了flag_add,我們就很明確,cnt0的加1條件是flag_add==1,數到5208下就結束。為此,可以寫(xiě)出cnt0的代碼。 中間信號,trigger連到觸發(fā)器的信號輸入端D,觸發(fā)器的輸出器連的是tri_ff0。將trigger取反,與tri_ff0相與,就得到信號neg_edge,如果neg_edge=1就表示檢測到trigger的下降沿。將tri_ff0取反,與trigger相與,就得到信號pos_edge,如果pos_edge=1,就表示檢測到trigger的上升沿。 我們來(lái)講解這個(gè)原理,畫(huà)出信號的波形圖。 Tri_ff0是觸發(fā)器的輸出,因此tri_ff0的信號與trigger信號相似,只是相差一個(gè)時(shí)鐘周期。我們也可以這樣理解:每個(gè)時(shí)鐘上升沿看到的tri_ff0的值,其實(shí)就是triffer信號上一個(gè)時(shí)鐘看到的值,也就是tri_ff0是trigg 3.2.2 異步信號同步化 。 這樣,flag_add變1的條件就變成:rx_uart_ff1==0&& rx_uart_ff2==1。 Flag_add變0的條件,可以完成收完9比特數據就變0,不用再計數了。所以變0條件:end_cnt1。 綜上所述,可以寫(xiě)出flag_add的代碼。 設計下data信號,該信號的值來(lái)自于圖中第2~第9比特的值。第2比特的值賦給data[0],第3比特的值賦給data[1],以此類(lèi)推,第9比特的值賦給data[7]。 由于每一個(gè)比特都持續5208個(gè)時(shí)鐘周期,我們必須選定一個(gè)時(shí)刻,將值賦給data。 首先,不能在end_cnt0的時(shí)候賦值,如上圖的點(diǎn)。因為我們這里的5208個(gè)時(shí)鐘周期是理想、估算的數值,實(shí)際上是非常有可能有偏差的。如果我們在end_cnt0的時(shí)候取值,就有可能采錯。 最保險的做法是在中間點(diǎn)取值。這樣,即使有比較多的偏差,都不會(huì )影響到采樣的正確性。 綜上所述,我們在cnt0數到一半時(shí)采到當前rx_uart的值賦給dout,其中第2比特賦給led[0],第3比特賦給led[1],以此類(lèi)推,第9比特賦給led[7]。 進(jìn)一步用信號表示,可翻譯成:數到add_cnt0 && cnt0==5208/2 -1時(shí),如果cnt1==1,則將rx_uart_ff1賦給led[0]。如果cnt1==2,則將rx_uart_ff1賦給led[1],以此類(lèi)推,如果cnt1==8,將rx_uart_ff1賦給led[7]。 那么直接翻譯成代碼。 上面代碼可優(yōu)化,簡(jiǎn)寫(xiě)成如下: 通常我們設計時(shí),首先是想到實(shí)現功能,所以會(huì )先寫(xiě)出前面代碼。在功能實(shí)現的前提下,再考慮有沒(méi)有優(yōu)化空間,從而寫(xiě)出后面代碼。好代碼都是一步步優(yōu)化出來(lái)的。 注意,上面代碼,我們采集的是rx_uart_ff1而不是rx_uart信號。這是因為rx_uart是異步信號,我們只能用同步化后的信號,否則會(huì )引起亞穩態(tài)。所以只能是rx_uart_ff1。 至此,主體程序已經(jīng)完成。接下來(lái)是將module補充完整。 3.3 信號定義 cnt0是用always產(chǎn)生的信號,因此類(lèi)型為reg。cnt0計數的最大值為5208,需要用13根線(xiàn)表示,即位寬是13位。因此代碼如下: add_cnt0和end_cnt0都是用assign方式設計的,因此類(lèi)型為wire。并且其值是0或者1,1個(gè)線(xiàn)表示即可。因此代碼如下: cnt1是用always產(chǎn)生的信號,因此類(lèi)型為reg。cnt1計數的最大值為9,需要用4根線(xiàn)表示,即位寬是4位。因此代碼如下: add_cnt1和end_cnt1都是用assign方式設計的,因此類(lèi)型為wire。并且其值是0或者1,1根線(xiàn)表示即可。因此代碼如下: flag_add是用always方式設計的,因此類(lèi)型為reg。并且其值是0或者1,1根線(xiàn)表示即可。因此代碼如下: rx_uart_ff0、rx_uart_ff1和rx_uart_ff2是用always方式設計的,因此類(lèi)型為reg。并且其值是0或1,需要1根線(xiàn)表示即可。因此代碼如下: 4 綜合工程和上板4.1 新建工程 1.首先在d盤(pán)中創(chuàng )建名為“uart”的工程文件夾,將寫(xiě)的代碼命名為“uart.v”,頂層模塊名為“uart”。 2. 然后打開(kāi)Quartus ,點(diǎn)擊File下拉列表中的New Project Wzard...新建工程選項。 3.在出現的界面中直接點(diǎn)擊最下方的“Next”。 4.之后出現的是工程文件夾、工程名、頂層模塊名設置界面。按照之前的命名進(jìn)行填寫(xiě),第一欄選擇工程文件夾“uart”,第二欄選擇工程文件“uart.v”,最后一欄選擇頂層模塊名“uart”,然后點(diǎn)擊”Next”,再出現的界面選擇empty project。 6. 器件型號選擇界面。在“Device family”處選擇Cyclone E,在“Available devices”處選擇EP4CE15F23C8,然后點(diǎn)擊“Next”。 7. EDA工具界面。該頁(yè)面用默認的就行,直接點(diǎn)擊最下方“Next”。 8.之后出現的界面是我們前面的設置的總結,確認沒(méi)有錯誤后點(diǎn)擊“Finish” 4.2 綜合 1.新建工程步驟完成后,就會(huì )出現以下界面。在“Project Navigator”下選中要編譯的文件,點(diǎn)擊上方工具欄中“Start Compilation”編譯按鈕(藍色三角形) 2.編譯成功后會(huì )出現以下界面,點(diǎn)擊“OK”。 4.3 配置管腳 在菜單欄中,選中Assignments,然后選擇Pin Planner,就會(huì )彈出配置管腳的窗口。 在配置窗口最下方中的location一列,參考下表中最右兩列配置好FPGA管腳。 配置完成后,關(guān)閉Pin Planner,軟件自動(dòng)會(huì )保存管腳配置信息。 4.4 再次綜合 在菜單欄中,選中Processing,然后選擇Start Compilation,再次對整個(gè)工程進(jìn)行編譯和綜合。 出現上面的界面,就說(shuō)明編譯綜合成功。 4.5 連接開(kāi)發(fā)板 圖中,下載器接入電腦USB接口,電源接入電源,uart線(xiàn)連接電腦USB,然后摁下電源開(kāi)關(guān),看到開(kāi)發(fā)板燈亮。 4.6 上板 1.雙擊Tasks一欄中”P(pán)rogram Device” 2.會(huì )出現如下界面,點(diǎn)擊add file添加.sof文件,在右側點(diǎn)擊“Start”,會(huì )在上方的“Progress”處顯示進(jìn)度。 3.進(jìn)度條中提示成功后,即可在顯示器上觀(guān)察到相應的現象。 4.7 串口調試 1,安裝串口調試工具。 2. 開(kāi)發(fā)板連接完成,打開(kāi)電源后,在設備管理器中查看串口名。填寫(xiě)圖片摘要(選填) 3,打開(kāi)串口調試助手,在串口處選擇之前查看的串口名,波特率、校驗位、數據位、停止位根據之前給出的數據進(jìn)行填寫(xiě),發(fā)送和接收都選擇十六進(jìn)制。 4,上板成功之后,在發(fā)送數據欄輸入相應的數據(將8個(gè)LED燈對應的8位二進(jìn)制數轉化為十六進(jìn)制),然后發(fā)送,即可在開(kāi)發(fā)板上看到相應的現象。 |