本文接續(xù)上一篇《FPGA雜記基礎(chǔ)篇》,繼續(xù)為大家分享IP例化和幾個(gè)基于FPGA芯片實(shí)現(xiàn)的Demo工程。
IP例化
IP即是一個(gè)封裝好的模塊,集成在相應(yīng)的開發(fā)環(huán)境里面,以安路的TD軟件為例,不同系列的芯片集成了不同的IP模塊,可以通過軟件例化調(diào)用。
以下是安路TD4.6.5集成的EF3L40CG332B的相關(guān)IP。
1.1 PLL&RAM
以例化PLL和RAM為例,實(shí)現(xiàn)兩個(gè)異步雙口 RAM。
讀寫時(shí)鐘都設(shè)置 100Mhz, 兩個(gè) RAM 為 RAMA 和RAMB, 深度為 1024,位寬為 8bit,寫入數(shù)據(jù)為 8bit,100Mhz 持續(xù)數(shù)據(jù)流, 當(dāng) RAMA被寫入 1024 字節(jié)數(shù)據(jù)后切換到寫 RAMB, RAMB 被寫入 1024 字節(jié)后切換 RAMA。以此循環(huán)類推。
當(dāng) RAMA 被寫入 1024 字節(jié)時(shí), 給讀時(shí)序提供一個(gè)啟動(dòng)信號(hào)讀取 RAMA 的數(shù)據(jù), 讀取完 RAMA 的 1024 字節(jié)數(shù)據(jù)時(shí), 切換讀 RAMB 以此類推。
這個(gè)工程的工程結(jié)構(gòu)如下圖:
首先EF3L40CG332B_DEV開發(fā)板提供了25Mhz的晶振時(shí)鐘輸入到EF3L40CG332B的時(shí)鐘管腳。
想要得到100Mhz的讀寫速率,需要先用PLL得到倍頻時(shí)鐘。
在tools目錄下點(diǎn)擊IP Generator進(jìn)入IP core頁面,并選擇PLL,輸入時(shí)鐘填入板子晶振25Mhz。
輸出時(shí)鐘填入所需要的100Mhz,并從C0輸出。
設(shè)置完成后,生成的module聲明如下(完整模塊可參考代碼)
再生成ram的IP模塊。
在IP core中選擇RAM。
Memory type選擇簡單雙口ram,memory size設(shè)置位寬8bit深度1024。
設(shè)置完成后,生成的module聲明如下。(完整模塊可參考代碼)
然后編寫頂層文件并且在頂層例化PLL和RAMA、RAMB。
頂層文件中主要是對(duì)ram的輸入口進(jìn)行時(shí)序操作,包括ramA、ramB的讀地址,寫地址、使能信號(hào)和輸入輸出數(shù)據(jù),詳細(xì)代碼筆記中不再贅述,可以直接參考代碼。
可綜合模塊編寫完成后,編寫仿真模塊并使用仿真軟件進(jìn)行仿真。
由于本次工程使用到了安路的IP庫,因此也需要在modelsim中添加相應(yīng)的安路仿真庫,添加方法如下:
首先在modelsim的安裝目錄下面編輯modelsim的初始化文件modelsim.ini,右鍵屬性后,將它的只讀屬性取消,然后用文本文件(本工程使用的是notepad++)編輯。
在modelsim.ini的[library]列表下添加安路的仿真庫文件目錄,安路所有的仿真庫文件都在安路的編譯軟件TD安裝目錄下的sim文件夾中,此處將其所有的庫文件都復(fù)制進(jìn)了modelsim的文件夾里,若不復(fù)制,也可直接輸入安路文件夾的路徑。
保存后退出,打開modelsim并創(chuàng)建工程,編譯通過后,進(jìn)入仿真步驟,在simulate狀態(tài)欄下選擇start simulate,如下圖:
選擇后進(jìn)入到如下頁面:
選擇仿真的頂層并且關(guān)閉優(yōu)化選項(xiàng)。
同一個(gè)窗口打開libraries頁面并在search libraries欄右側(cè)選擇add,下拉列表選擇對(duì)應(yīng)的ef3的庫文件。
設(shè)置完成后點(diǎn)擊OK進(jìn)入仿真即可。
本次實(shí)驗(yàn)中遇見問題和調(diào)試如下:
01
剛開始pll沒有輸出信號(hào),因此打開了pll查看波形發(fā)現(xiàn)pll波形如下:
發(fā)現(xiàn)是置位了reset信號(hào)導(dǎo)致的,查看代碼發(fā)現(xiàn)如下:
復(fù)位信號(hào)直接連接到了pll的置位信號(hào),由于復(fù)位信號(hào)是低電平有效而置位信號(hào)是高電平有效,因此導(dǎo)致了pll一直處于復(fù)位的情況。更改后,直接將pll復(fù)位信號(hào)置0,代碼和仿真結(jié)果正常,如下所示:
02
PLL問題解決后,觀測數(shù)據(jù)整體讀寫情況。
初步觀測可以發(fā)現(xiàn),rama讀使能信號(hào)只轉(zhuǎn)變了一次,而ramb的讀使能始終未能跳變,返回代碼查看發(fā)現(xiàn):
邏輯判斷時(shí)未將rama的寫使能信號(hào)置1的條件寫出來。
ramb的寫使能同理:
修改后,代碼如下:
波形仿真如下:
粗看基本符合rama、ramb交替讀寫的功能,觀測rama、ramb時(shí)序交替細(xì)節(jié)。
在rama和ramb寫使能信號(hào)轉(zhuǎn)換時(shí),發(fā)現(xiàn)空了一拍,再查看代碼,發(fā)現(xiàn)rama、ramb寫使能在條件判斷時(shí),使用的判斷邏輯是不一樣的,導(dǎo)致ramb_wren的置位會(huì)在rama_wren置位后的下一拍進(jìn)行。
因此更改ramb_wren的判斷條件,使之與rama_wren的一樣,都以寫地址為條件判斷再仿真。
可觀測到,時(shí)序正常。
quick start & GPIO Demo
本次demo實(shí)現(xiàn)功能如下:FPGA控制LED D1閃爍,MCU控制LED D2常亮。
2.1 keil工程環(huán)境創(chuàng)建
創(chuàng)建文件夾目錄如下:
圖1
其中板級(jí)支持包直接由原廠提供。
先創(chuàng)建keil工程,打開keil,創(chuàng)建工程,保存在對(duì)應(yīng)的MCU→project目錄下。
器件選擇ARM cortex M3器件。
工程建好后,添加必要的BSP包中的文件如下,創(chuàng)建好后的工程目錄如左欄:
其中,startup組下的文件分別來自MCU\ELF2_BSP\Device\ELF2\Source和MCU\ELF2_BSP\Device\ELF2\Source\ARM目錄下;lib組的文件來自MCU\ELF2_BSP\Driver;log組文件保存在MCU\ELF2_BSP\Debug和MCU\ELF2_BSP\Debug\RTT目錄下。
新建main.c文件并保存在圖1所示的總文件目錄瀏覽的MCUàsrc文件夾下并添加main.c到工程main組中。
下面設(shè)置一些工程的環(huán)境,打開options for target對(duì)話框。
切換到user欄,設(shè)置如下參數(shù),這些參數(shù)會(huì)影響輸出keil工程的*.asm 和*.bin 文件,我們需要通過添加這兩條指令得到bin文件并最終提供給FPGA。
添加的語句分別如下:
fromelf -c -v -a --output=@P.asm Objects\%L
fromelf --bin --output=@P.bin Objects\%L
再切換到C++++++++/C++欄,設(shè)置頭文件路徑如下:
也可以直接添加如下目錄
..\ELF2_BSP;..\ELF2_BSP\CMSIS\Core\Include;..\ELF2_BSP\Debug;..\ELF2_BSP\Debug\RTT;..\ELF2_BSP\Driver;..\ELF2_BSP\Driver\regmap;..\ELF2_BSP\Device\ELF2\Include;..\ELF2_BSP\Device\ELF2\Source\ARM
其余設(shè)置如下圖:
添加分散加載文件elf2_example.sct(elf2_example.sct文件具體代碼可參考工程)
環(huán)境設(shè)置完畢后可以開始編寫工程代碼。
2.2 C代碼編輯
在main函數(shù)中編寫對(duì)GPIO的操作。
先對(duì)GPIO初始化結(jié)構(gòu)體賦值,再調(diào)用GPIO初始化函數(shù),HAL_GPIO_WritePin函數(shù)對(duì)相應(yīng)的GPIO進(jìn)行高低賦值。
本次使用C代碼對(duì)GPIO1_0的操作是置低,GPIO1_0具體含義會(huì)在下一節(jié)(1.3)進(jìn)行說明。
2.3 TD工程創(chuàng)建和代碼編輯
打開TD4.6.5或其他版本創(chuàng)建新的工程。
保存在總目錄的FPGA→project目錄下,并選擇對(duì)應(yīng)的器件類型。
添加或者編輯源文件,本次工程模塊聲明如下:
其中hw_led是由FPGA邏輯控制的led,sw_led是由MCU代碼控制的led(即1.2中的gpio1_0)。hw_led的控制代碼如下,sw_led的控制代碼詳見1.2:
然后例化MCU和PLL,PLL例化主要得到輸入到MCU的系統(tǒng)時(shí)鐘,例化過程略,這里貼上在頂層中調(diào)用的結(jié)果:
輸出的200M的時(shí)鐘接到MCU的系統(tǒng)時(shí)鐘。
例化MCU界面如下:
如圖所示,MCU支持最大 32 個(gè)GPIO,其中低16位,即GPIO_L0~GPIO_L15是直接連接至pad的;而GPIOH0~GPIOH15則是通過FPGA連接至外部,因此,當(dāng)使用這16個(gè)GPIO的時(shí)候,需要在FPGA工程的管教約束文件中指定具體連接至哪個(gè)腳。
在例化MCU時(shí),使用到哪個(gè)腳就可以打開對(duì)應(yīng)的開關(guān),例如本例中,打開了L0、L1和H0,PPM_CLK,其中PPM_CLK是FPGA Fabric 輸入時(shí)鐘,連接至FPGA的PLL輸出clk200;L0、L1連接至PAD,觀察原理圖。
GPIO0和GPIO1連接的是調(diào)試口;最后H0連接至FPGA 中sw_led并通過管腳約束連接至LED D2。
工程的管教約束文件如下:
查開發(fā)板原理圖,D2連接至FPGA的16腳,且從原理圖可觀察,keil工程中對(duì)該GPIO的操作是置低,具體顯示是D2常亮。
設(shè)置完畢后,完成結(jié)果聲明如下:
并在頂層中調(diào)用:
2.4 下載
Keil和TD的工程都創(chuàng)建編寫完成后,編譯工程。其中,keil生成的工程bin文件需要與TD關(guān)聯(lián)并通過TD下載至芯片或開發(fā)板中。
關(guān)聯(lián)的步驟如下:
在HDL2Bit Flow欄右鍵選擇properties。
在generate bitstream的第六項(xiàng)instruct ram中選擇keil工程生成的bin文件的目錄(此時(shí)keil工程已經(jīng)編譯通過),并保存。
保存后,雙擊generate bitstream編譯TD工程,假如在選擇路徑前已經(jīng)編譯過TD工程了,需要右鍵選擇rerun重新編譯(注意:假如修改了keil的C文件而TD的HDL文件沒有變化,建議也rerun后再將文件下載至開發(fā)板)
下載:
板子現(xiàn)象如圖:
D1持續(xù)閃爍,D2常亮:
FPGA串口通信
本Demo案例基于安路的EF2M45LG48_MINI_DEV2開發(fā)板,通過測試板的uart口和PC機(jī)的uart口連接來形成一個(gè)閉環(huán)回路,即PC機(jī)發(fā)送數(shù)據(jù)至FPGA測試板,F(xiàn)PGA接收并返回相同的數(shù)據(jù)。實(shí)驗(yàn)結(jié)果通過PC機(jī)的串口調(diào)試助手調(diào)試查看。
3.1 UART協(xié)議
UART 是一種通用串行數(shù)據(jù)總線,用于異步通信,將數(shù)據(jù)在串行通信和并行通信間的傳輸轉(zhuǎn)換。通俗的講就是把多比特的數(shù)據(jù)轉(zhuǎn)化為單比特的數(shù)據(jù)(tx端),或者把單比特的數(shù)據(jù)轉(zhuǎn)化為多比特的數(shù)據(jù)(rx端)。工作原理是將數(shù)據(jù)的每個(gè) bit 一位接一位地傳輸。
rx,接收端,位寬為 1 比特, pc 機(jī)通過串口往 FPGA 發(fā) 8 比特?cái)?shù)據(jù)時(shí),F(xiàn)PGA 通過串口線 rx 一位一位地接收,從最低位到最高位依次接收,最后在 FPGA 里面位拼接成8 比特?cái)?shù)據(jù)。
tx,發(fā)送端,位寬為 1 比特, FPGA 通過串口往 pc 機(jī)發(fā) 8 比特?cái)?shù)據(jù)時(shí), FPGA 把 8 比特?cái)?shù)據(jù)通過 tx 線一位一位的傳給 pc 機(jī),從最低位到最高位依次發(fā)送,最后上位機(jī)通過串口助手把這一位一位的數(shù)據(jù)位拼接成 8 比特?cái)?shù)據(jù)。
注意點(diǎn):
1、串行數(shù)據(jù)的發(fā)送和接收都是從低位到高位。
2、在不發(fā)送或者不接收數(shù)據(jù)的情況下, rx 和 tx 處于空閑狀態(tài),此時(shí) rx 和 tx 線都保持【高電平】,如果有數(shù)據(jù)傳遞,首先會(huì)有一個(gè)起始位0,然后是 8 比特的數(shù)據(jù)位,接著有 1 比特的停止位(高電平),如果停止位以后不再發(fā)數(shù)據(jù),將進(jìn)入空閑狀態(tài),否則又將數(shù)據(jù)線拉低(進(jìn)入起始位狀態(tài))。
3、波特率計(jì)算:uart傳輸有不同的波特率,使用HDL語言描述時(shí),通常使用計(jì)數(shù)器來實(shí)現(xiàn)不同波特率的數(shù)據(jù)傳播。計(jì)數(shù)器的計(jì)數(shù)值與具體波特率有關(guān),以常見的115200為例,假設(shè)系統(tǒng)時(shí)鐘是25Mhz,則傳輸1bit所需要的時(shí)鐘周期為25 * 1000 *1000 /115200 = 217個(gè),因此計(jì)數(shù)器計(jì)數(shù)值即216(從0開始計(jì)數(shù))。
3.2 模塊總框架
模塊的總體框架如下:
top層除了時(shí)鐘和復(fù)位信號(hào)的輸入,還有輸入信號(hào)rx和輸出信號(hào)tx,分別來自PC機(jī)和輸出到PC機(jī),形成閉環(huán)。子模塊中,Rx信號(hào)再作為uart_rx模塊的輸入,經(jīng)過uart_rx模塊的處理,轉(zhuǎn)換成八位并行數(shù)據(jù)o_data輸出;對(duì)于uart_tx模塊,主要將輸入的i_data并行信號(hào)轉(zhuǎn)換成串行數(shù)據(jù)再輸出到PC機(jī)。
3.3 代碼實(shí)現(xiàn)
1. Rx端
2.Tx端
3.4 頂層
3.5 仿真
本次仿真使用到了task語句,task語句通常在當(dāng)仿真時(shí)需要給輸入變量特定的輸入值時(shí)使用,例如本次仿真對(duì)rx端進(jìn)行賦值。
3.6 仿真結(jié)果及問題排查
Rx端:
整體波形如圖:
查看細(xì)節(jié)如下:
當(dāng)rx=1時(shí),輸出的o_data并行數(shù)據(jù)在o_flag = 1(即表示傳輸結(jié)束)時(shí)也為1,結(jié)果正常。
Tx端:
整體波形如下:
上圖很明顯可以看出tx端傳輸有問題,當(dāng)tx發(fā)送起始位(即拉低)后,沒有將數(shù)據(jù)輸出。觀測其他信號(hào)波形,基本正常。可見問題大概率出現(xiàn)在tx賦值部分,一開始以為是發(fā)送數(shù)據(jù)位的條件判斷有問題,檢查代碼,數(shù)據(jù)傳輸時(shí)的判斷條件如下:
查看波形發(fā)現(xiàn)該條件可以被滿足。
后來查看起始位的發(fā)送條件時(shí)發(fā)現(xiàn)了錯(cuò)誤:
起始位發(fā)送要與tx_en同步。假設(shè)條件使用tx_en判斷,則會(huì)比tx_en慢一拍。
另外,不能使用tx_en == 1'b1作為發(fā)送起始位的判斷條件,因?yàn)閠x_en 在數(shù)據(jù)發(fā)送時(shí)一直為1,這樣tx端會(huì)恒為0,修改后代碼如下:
再觀察波形正常。
3.7 上板最終效果
代碼下載進(jìn)開發(fā)板后,在串口調(diào)試助手中可以正常收發(fā)數(shù)據(jù),如下:
fqj
-
FPGA
+關(guān)注
關(guān)注
1629文章
21748瀏覽量
603795 -
芯片
+關(guān)注
關(guān)注
456文章
50879瀏覽量
424132
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論