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