FPGA 20个例程篇:7.FLASH读写断电存储
三、數(shù)據(jù)斷電存儲,工程必備
7.FLASH讀寫斷電存儲
? ? ? ?這個例程主要是說明怎么設(shè)計FPGA時序邏輯來實現(xiàn)FLASH的頁面數(shù)據(jù)擦除、讀寫等,例程本身有著非常深刻地學(xué)習(xí)價值,大家不妨回想一些嵌入式工作中的常見開發(fā)場景:1.做單片機STM32開發(fā),KEIL編譯過后下載直接通過ST-LINK,J-LINK等把bin文件燒寫到單片機的內(nèi)部FLASH里,斷電重啟后STM32即運行剛才燒寫過的程序;2.同樣地我們也可以把一些希望斷電存儲的大批量數(shù)據(jù)保存到STM32內(nèi)部FLASH里,用到后面程序段未使用的扇區(qū)空間即可;3.STM32外掛一顆FLASH,把需要顯示的圖像二進(jìn)制數(shù)據(jù)預(yù)先存入FLASH里,上電后再把數(shù)據(jù)讀出,重新繪制到顯示屏的指定坐標(biāo)上即可;4.FPGA外掛一顆QSPI-FLASH,通過下載器把mcs文件燒寫到FLASH里,開機上電后FPGA即讀出FLASH的配置,再按照該配置去重新綜合其內(nèi)部的電路來達(dá)到預(yù)期設(shè)計等,所以毫不夸張地說掌握FLASH的讀寫在嵌入式開發(fā)中是一項必備技能。
? ? ? ?這里和朋友們簡單討論一些題外話,對于很多工程項目因為拆機不便,都會有著遠(yuǎn)程更新程序的現(xiàn)實性需求,例如上位機對STM32的IAP串口程序升級;4G網(wǎng)絡(luò)遠(yuǎn)程升級ARM LIUNX等,雖然具體的升級接口方式隨著硬件變化而變化,但其實核心內(nèi)容不變依舊是進(jìn)入Bootloader,通過各類通信協(xié)議接收到bin文件的二級制數(shù)據(jù),逐一寫入FLASH的對應(yīng)扇區(qū)內(nèi),最后從Bootloader跳轉(zhuǎn)到Application。
? ? ? ? 大家有沒有想過對FPGA而言,本身只是時序邏輯,那么它怎樣才能實現(xiàn)遠(yuǎn)程升級呢?這是一個很有意思也很有價值的問題,現(xiàn)實項目中如果需要對FPGA遠(yuǎn)程設(shè)計,一般需要通過上位機或者ARM端的協(xié)助,上位機可以通過常見的LAN、USB2.0、RS232等不同的外設(shè)接口把bin文件打報數(shù)據(jù)發(fā)送給FPGA,FPGA接收后按照時序邏輯去把數(shù)據(jù)寫入外掛QSPI-FLASH的對應(yīng)頁面(此時FPGA已上電從QSPI-FLASH中讀出電路配置內(nèi)容,按照程序給定的時序邏輯工作),也可以預(yù)先把FPGA的bin文件預(yù)先拷入U盤里,ARM或STM32通過移植FATS32,把U盤里的bin文件讀出并打報數(shù)據(jù)扔給FPGA,同樣的FPGA再去寫入數(shù)據(jù)到外掛的QSPI-FLASH里,這個例程先暫且不去討論具體FPGA遠(yuǎn)程升級的實現(xiàn)方案,而是提供一套擦除、讀寫FPGA外掛的鎂光QSPI-FLASH的設(shè)計方法,如圖1所示是豌豆開發(fā)板板載的一顆鎂光N25Q128芯片,利用這顆QSPI-FLASH芯片,既可以支持mcs文件燒寫即完成程序的斷電保存,也可以實現(xiàn)其他大批量數(shù)據(jù)的存儲記憶。
圖1 豌豆開發(fā)板Artix7上N25Q128電路
? ? ? ?談過FLASH的實戰(zhàn)背景意義后,在這個例程里,筆者想詳細(xì)地向大家介紹FPGA驅(qū)動IC設(shè)計的大體方法,只有當(dāng)理解并掌握一般性方法后,再去做其他相關(guān)IC驅(qū)動研發(fā)時才能舉一反三、靈活自如。但可能正應(yīng)了那句老話,一萬個讀者就有一萬個哈姆雷特,這里只是筆者的多年工作積累供參考,并沒有像數(shù)學(xué)考試一樣一個標(biāo)準(zhǔn)的答案,仁者見仁智者見智,可能不是最優(yōu)解,但確實是合理解。
? ? ? ?這里我們還是先來仔細(xì)閱讀N25Q128的芯片手冊,在提取程序設(shè)計中的用到關(guān)鍵信息后,再來和朋友們探討FPGA去驅(qū)動IC芯片的一般性方法!本例程的代碼是從轉(zhuǎn)產(chǎn)項目中摘錄的也具有很大參考價值,需要特殊說明的是QSPI-FLASH的引腳應(yīng)該接到Artix7芯片的固定IO上,否則無法用下載器下載mcs文件。
? ? ? ?寫到這里,筆者不由自主地想和大家分享一些親身研發(fā)經(jīng)歷,也是這個例程代碼的原型,當(dāng)時項目開發(fā)需要實現(xiàn)Artix7斷電存儲一些數(shù)據(jù),XILINX官方手冊也推薦鎂光的外擴QSPI-FLASH芯片,PCB投板并焊接回來,卻發(fā)現(xiàn)QSPI-FLASH芯片不管怎么驅(qū)動都好像不工作,就不斷地用讀取ID號做測試始終沒任何反應(yīng),因為物料是立創(chuàng)上面買的沒有懷疑,所以花了大量精力去排查其他地方,索性買來一塊低端外掛FLASH的Spartan6開發(fā)板,經(jīng)過測試讀取ID號成功了,但型號是W25Q128,所以仍舊無法確定具體原因,當(dāng)時感到束手無策,仔細(xì)核對了兩個FLASH的芯片手冊差別不大,但相同的邏輯代碼放在Artix7板上依舊不行,最后沒有辦法直接把Artix7板上的N25Q128芯片用烙鐵拆了,也把Spartan6開發(fā)板的W25Q128拆了換上鎂光的N25Q128芯片再試,結(jié)果再試居然好了!于是矛頭直指Artix7芯片,當(dāng)然現(xiàn)在看來確實走了很多彎路,因為過于相信XILINX下的ILA在線調(diào)試工具,實際沒有用示波器或邏輯分析儀去實際測量SPI總線協(xié)議上的信號,雖然在ILA下觀察SPI總線的時鐘一直作為輸出在線觀察有波形產(chǎn)生,但該引腳事實上沒有任何輸出只是被ILA調(diào)試欺騙,最后查閱了XILINX的官方手冊證明是連接該引腳的CCLK_0是特殊引腳,即使在.xdc文件里定義,也不能被直接驅(qū)動,需要參考XILINX手冊用特殊的原語去驅(qū)動該引腳!
? ? ? ?如圖2所示是芯片手冊上對N25Q128的引腳說明,大家可以對照圖1的電路來看,除了VCC和GND兩個引腳外,SO8W 封裝的N25Q128芯片,還有D0-D3,SCK時鐘信號和CS#片選信號六個引腳,朋友們可以注意到對于這顆QSPI-FLASH芯片有extended spi、dual spi、quad spi三種讀寫模式,即單線SPI、雙線SPI、四線SPI通信,其中單線SPI的一根數(shù)據(jù)線只用來發(fā)送,另一根數(shù)據(jù)線只用來接收,即為全雙工;雙線 SPI的兩根線都具有收發(fā)功能,但在同一時刻只能是發(fā)送或者是接收,即為半雙工;而四線 SPI與雙線 SPI相類似,只是數(shù)據(jù)線數(shù)量上有所區(qū)別,也為半雙工。
? ? ? ?其實筆者對單線SPI、雙線SPI、四線SPI通信模式下驅(qū)動N25Q128芯片都有嘗試過,平心而論單線SPI則更具有廣泛地實用性,因為一方面在雙線SPI、四線SPI通信中均為半雙工,即引腳需要定義成inout類型這也增加了程序設(shè)計的復(fù)雜性,另一方面芯片手冊對雙線SPI、四線SPI通信做了詳細(xì)說明,不難發(fā)現(xiàn)在這兩種模式下的命令發(fā)送和數(shù)據(jù)接收都有一些很容易大意的地方。
? ? ? ?當(dāng)然在這里也有朋友會反問,如果用雙線SPI、四線SPI通信不也提高了數(shù)據(jù)讀寫速度嗎?答案是肯定會有所提高,但大家想一想在整個設(shè)計,首先我們對SPI總線協(xié)議使用25Mhz的時鐘,對現(xiàn)實項目中讀寫FLASH數(shù)據(jù)的需求已經(jīng)完全可以滿足了;其次對FLASH的讀寫頻率不會很頻繁,不管是遠(yuǎn)程更新程序還是斷電記憶數(shù)據(jù);再次在項目設(shè)計上,往往FPGA是作為計算、接口、采集后端的,而ARM作為顯示、工控、通信的前端,這時還需要通過各種總線、協(xié)議等把數(shù)據(jù)報文發(fā)送給FPGA,FPGA才會觸發(fā)讀寫FLASH操作,而通常情況下25Mhz的SPI通信相對于Modbus 485總線、CAN總線等通信來說,速度方面已經(jīng)足夠用了,即讀寫FLASH速度通常情況下要快于報文接收的速度,所以在這里再去糾結(jié)雙線SPI、四線SPI通信來提升FLASH讀寫速度,實際上現(xiàn)實意義并不大。
?圖2 N25Q128引腳的說明
? ? ? ?如圖3所示,是芯片手冊對N25Q128存儲空間的詳細(xì)描述,大家可以看到N25Q128標(biāo)明的是128Mb空間,即128*1024*1024=134217728位,也就是手冊中所寫的16777216字節(jié),對FLASH以及下一個例程的SD卡里都有扇區(qū)的概念,手冊說明了一顆N25Q128芯片含有256個扇區(qū),每個扇區(qū)是64K字節(jié),即256*64*1024=16777216字節(jié);含有4096個子扇區(qū),每個子扇區(qū)是4K字節(jié),即4096*4*1024=16777216字節(jié);含有65536頁,每頁是256字節(jié),即65536*256=16777216字節(jié),所以要搞清楚這些基本概念,對于FLASH擦除、讀寫最小的操作是以頁為單位,當(dāng)然也能以扇區(qū)和子扇區(qū)為單位,在這個例程設(shè)計中我們以頁為操作的基本單位。
?圖3 N25Q128的存儲空間示意圖
? ? ? ?如下圖4所示是N25Q128芯片的操作指令表格,筆者把程序上常用的指令用紅圈標(biāo)注了出來。在表格中非常詳細(xì)地說明了Command具體內(nèi)容,Code對應(yīng)指令,是否支持Extended、Dual I/O、Quad I/O即單線SPI、雙線SPI、四線SPI通信和注意事項,這里因為程序設(shè)計中選擇了單線SPI,所以我們更加關(guān)注Extended欄中的項目。大家注意到表格下面的Notes,只需要看2、4、8三條即可,其中有的指令需要發(fā)送1字節(jié)的指令信息后再發(fā)送3字節(jié)的地址信息,有的指令則直接發(fā)送1字節(jié)的指令信息即可,有的指令還需要在發(fā)送前再發(fā)送write enable指令,下面我們結(jié)合芯片手冊上每種操作指令的時序邏輯圖,來為大家展開更加細(xì)致的說明,這些信息也關(guān)系到程序設(shè)計。
圖4 N25Q128芯片的操作指令表格
? ? ??筆者在這里按照芯片手冊的排版順序,為大家介紹程序設(shè)計上需要用到指令的時序邏輯,如圖5到圖10所示,分別是SPI單線模式下N25Q128芯片的讀取狀態(tài)寄存器指令、讀取ID指令、頁讀取指令、頁寫入指令、寫使能和寫禁止指令、頁擦除指令時序圖。
?圖5 SPI單線模式下N25Q128芯片的讀取狀態(tài)寄存器指令時序圖
?圖6 SPI單線模式下N25Q128芯片的讀取ID指令時序圖
?圖7 SPI單線模式下N25Q128芯片的頁讀取指令時序圖
圖8 SPI單線模式下N25Q128芯片的頁寫入指令時序圖
圖9 SPI單線模式下N25Q128芯片的寫使能和寫禁止指令時序圖
?圖10 SPI單線模式下N25Q128芯片的頁擦除指令時序圖
? ? ? ?如圖11所示是N25Q128芯片的狀態(tài)寄存器的說明,這里特別應(yīng)該去注意的是,在頁寫入和頁擦除操作后,需要輪詢地發(fā)送讀狀態(tài)寄存器指令以確定N25Q128是否執(zhí)行完成、準(zhǔn)備就緒,當(dāng)讀到一字節(jié)的狀態(tài)寄存器最低位是0時,即代表芯片準(zhǔn)備就緒可以執(zhí)行后續(xù)的其他操作,否則當(dāng)讀到最低位是1則代表尚未準(zhǔn)備就緒,這時再發(fā)送其他操作指令則會被視為無效操作,感興趣的同學(xué)可以在看看芯片手冊對其他寄存器的描述,N25Q128芯片確實有不止一個寄存器,例如有Status Register、Nonvolatile Configuration Register、Enhanced Volatile Configuration Register、Flag Status Register等,對這些寄存器的讀寫也會產(chǎn)生不同的效果,但在本例程中就用到最常見的一個即可。
?圖11 N25Q128芯片的狀態(tài)寄存器(Status Register)的說明
? ? ? ?如表1所示,是筆者總結(jié)的N25Q128芯片驅(qū)動指令列表,在這個列表中注明了指令的具體內(nèi)容和編號,和在各個指令下FPGA與FLASH通信時是否需要發(fā)送指令和地址內(nèi)容、是否需要在此后繼續(xù)讀寫數(shù)據(jù)等,在這里也定義了一個空指令CMD_NULL便于程序設(shè)計。(“√”代表該指令下通信需要發(fā)送命令、地址、寫數(shù)據(jù)或者接收數(shù)據(jù)等)搞清楚整個表格的內(nèi)容,對于flash_driver模塊的狀態(tài)機設(shè)計很有幫助。
| commad | instruction | cmd | addr | rd | wr |
| CMD_RD_DEVICE_ID 讀芯片信息 | 9F | √ | √ | ||
| CMD_WR_DISABLE/WR_ENABLE 寫禁止/寫使能 | 04/06 | √ | |||
| CMD_PAGE_PROGRAM 頁編程(寫數(shù)據(jù)) | 02 | √ | √ | √ | |
| CMD_RD_DATA 讀數(shù)據(jù) | 03 | √ | √ | √ | |
| CMD_SECTOR_ERASE 扇區(qū)擦除 | 20 | √ | √ | ||
| CMD_RD_STATUS_REGISTER 讀狀態(tài)寄存器 | 05 | √ | √ | ||
| CMD_NULL 空指令 | 00 |
表1 N25Q128芯片驅(qū)動指令列表
? ? ? ?詳細(xì)閱讀過N25Q128芯片手冊并提取出關(guān)鍵信息后,就如前面所說筆者想通過這個例程和朋友們一起去探討使用FPGA驅(qū)動一顆IC芯片的一般性程序設(shè)計方法。這個例程中,我們?nèi)崿F(xiàn)如下功能:通過按下豌豆開發(fā)板上的按鍵,觸發(fā)一次讀寫FLASH的過程,為了驗證相關(guān)的操作指令,我們依次去進(jìn)行如下操作:讀取ID、寫禁止、寫使能、寫擦除、讀取狀態(tài)寄存器、寫使能、頁寫入、讀取狀態(tài)寄存器、頁讀取,為了方便測試,這里選擇在FLASH的頁地址(每頁是256字節(jié))0下的,依次寫入0-255的256個字節(jié)數(shù)據(jù),然后再去讀取頁地址0下的256個數(shù)據(jù)通過串口打印到上位機。
? ? ? 這時朋友們可以想一想應(yīng)該怎么去實現(xiàn)整個代碼設(shè)計,當(dāng)然FPGA設(shè)計本身具有很大的靈活性,可能每個人都有不同的看法,筆者在這里給大家分享一種一般性的驅(qū)動IC的方法,也是從多年工作經(jīng)驗中總結(jié)歸納而來的,比如在這個例程中,通過對例程功能的描述,對于操作FLASH則需要一個狀態(tài)機去實現(xiàn)指令之間的跳轉(zhuǎn);通過對芯片手冊的分析,表3-3也詳細(xì)總結(jié)了不同指令下的數(shù)據(jù)發(fā)送和接收數(shù)量上不完全相同;通過對協(xié)議總線的學(xué)習(xí),SPI底層還需要驅(qū)動邏輯的支持才能正常工作,這樣一想就會感覺整個設(shè)計起來會很復(fù)雜、很困難,那么我們應(yīng)該如何去化繁為簡呢?
? ? ? ?通過模塊劃分的思想,我們可以把很多復(fù)雜煩瑣的設(shè)計做得簡單明了,一般性地我們可以把FPGA對IC驅(qū)動細(xì)劃分成驅(qū)動層、控制層、邏輯層,比如在本例程中可以對應(yīng)地劃分成flash_driver、flash_control、qspi_flash_rw_top三個層,這樣就可以把很多東西簡化。驅(qū)動層實現(xiàn)對FLASH不同指令下的SPI總線上數(shù)據(jù)收發(fā)的時序邏輯;控制層則把驅(qū)動層例化到本模塊,根據(jù)工程需求實現(xiàn)操作FLASH指令之間的跳轉(zhuǎn);邏輯層再把控制層例化過來,簡單修改就可以滿足整個代碼邏輯上對FLASH的控制,這樣就很大程度上減少編碼的復(fù)雜度,相反如果所有的驅(qū)動層、控制層、邏輯層的時序邏輯都放到一個模塊實現(xiàn),那么肯定很復(fù)雜易出錯,而且也不易排查問題。
? ? ? ?其次這里還有個小技巧,細(xì)心的同學(xué)會發(fā)現(xiàn)幾乎大部分IC芯片都有支持讀取ID操作,用讀取ID來作為驗證驅(qū)動層時序邏輯設(shè)計是否正確,往往在實際項目中被證明是最為簡單快捷的驗證方法。
? ? ? ?如上表1所示,對于flash_driver驅(qū)動模塊,需要用到FLASH操作指令如下:讀取ID(9F);寫禁止(04);寫使能(06);頁編程(02);頁讀取(03);頁擦除(20);讀取狀態(tài)寄存器(05),對于這些指令操作,可以把它歸納成幾個步驟:發(fā)送CMD命令、發(fā)送ADDR地址、讀取數(shù)據(jù)和寫入數(shù)據(jù),針對到具體指令操作有些步驟是跳過的,但不失一般性我們把flash_driver模塊劃分成6個狀態(tài)的狀態(tài)機,即IDLE、CMD_SEND、ADDR_SEND、RD_DATA、WR_DATA、DONE。
? ? ? ?flash_driver驅(qū)動模塊根據(jù)上游flash_control控制模塊發(fā)來的具體指令做狀態(tài)機的跳轉(zhuǎn)即可,如表2所示是flash_driver模塊信號列表,設(shè)計非常直觀明了給出詳細(xì)代碼供參考,對照代碼和說明很容易就可以動手還原出來,這里強調(diào)幾個設(shè)計上容易忽略的地方:
1. 對于FLASH的SPI時鐘的驅(qū)動設(shè)計,直接在本模塊從50Mhz時鐘分頻到25Mhz,但這里需要通過XILINX原語驅(qū)動CCLK_0引腳,CCLK_0引腳是特殊引腳,即使在xdc文件中定義也不生效;
2. 這個模塊中筆者使用的是單線SPI讀寫,感興趣的同學(xué)可以嘗試雙線SPI和四線SPI讀寫,從而結(jié)合具體工程練習(xí),提高了FPGA的設(shè)計能力;
3. 市面上各種教程對于SPI總線的設(shè)計,其實很多是有些瑕疵的地方,筆者在項目當(dāng)中之前也參考別的代碼SPI設(shè)計,存在一些實際問題,在這個例程中也詳細(xì)分享給大家,確實很多細(xì)節(jié)真的需要自己靜下心來思考才能體會到。
? ? ? ? 通過第4個例程“ 串行DAC輸出模擬電壓控制LED亮度的學(xué)習(xí)實踐 ”,朋友們也都了解到SPI是有極性和相位一說的,即在上升沿和下降沿時接收或者發(fā)送數(shù)據(jù),當(dāng)然接收和發(fā)送數(shù)據(jù)通過兩根獨立的數(shù)據(jù)線,即mosi和miso實現(xiàn)全雙工通信,對于SPI時序邏輯筆者見過主流的幾種設(shè)計方式:1. 從上游模塊產(chǎn)生一個SPI總線時鐘和一個相對偏移180度時鐘,再用這兩個時鐘的上升沿分別做數(shù)據(jù)的收發(fā)時鐘參考,這樣猛地一看貌似沒有問題,但實際增加了代碼的復(fù)雜度,同時因為兩個時鐘存在相位差,在和上游模塊進(jìn)行數(shù)據(jù)交互的時候,人為引入了跨時鐘域的問題;2. 直接用always模塊的posedge clk和negedge clk兩個時鐘去收發(fā)數(shù)據(jù),因為FPGA里的D觸發(fā)器默認(rèn)是用時鐘上升沿,雖然語法上支持用時鐘下降沿的方法當(dāng)從底層配置上來說不太友好;3. 通過時序邏輯產(chǎn)生一個時鐘,再通過時序邏輯去向mosi總線上發(fā)送數(shù)據(jù),因為時序邏輯是存在一拍的延時誤差,這樣做在分頻大的情況下,比如50Mhz分頻到6.25Mhz時,SPI的mosi和miso總線的建立和保持時間是足夠的,但在50Mhz分頻到25Mhz時,也是不可行的,所以筆者在flash_driver模塊中直接去產(chǎn)生SPI總線時鐘,并用組合邏輯從SPI總線上收發(fā)數(shù)據(jù),這樣從代碼層面上就合理規(guī)避了可能出現(xiàn)的問題和人為增加的設(shè)計復(fù)雜度,如圖12所示是本模塊詳細(xì)代碼設(shè)計。
| 信號列表 | ||
| 信號名 | I/O | 位寬 |
| clk | I | 1 |
| rst_n | I | 1 |
| flash_driver_en | I | 1 |
| flash_cmd | I | 8 |
| flash_addr | I | 24 |
| flash_dqout | I | 1 |
| flash_dqin | O | 1 |
| flash_cs | O | 1 |
| flash_cmd_done | O | 1 |
| flash_dout | O | 8 |
| flash_dout_vld | O | 1 |
表2 flash_driver模塊信號列表
圖12 FLASH驅(qū)動模塊的代碼設(shè)計
? ? ? ? 在完成FLASH驅(qū)動模塊的編寫后,我們就需要再動手編寫FLASH控制模塊,前面也提起過在控制模塊中例化驅(qū)動模塊,再用一個狀態(tài)機完成各個指令之間的切換,依次去進(jìn)行如下操作:讀取ID、寫禁止、寫使能、寫擦除、讀取狀態(tài)寄存器、寫使能、頁寫入、讀取狀態(tài)寄存器、頁讀取,即對應(yīng)程序設(shè)計中的狀態(tài)機:IDLE、RD_DEVICE_ID、WR_DISABLE、WR_ENABLE_FIRST、SECTOR_ERASE、RD_STATUS_REGISTER_FIRST、WR_ENABLE_SECOND、PAGE_PROGRAM、RD_STATUS_REGISTER_SECOND、RD_FLASH_DATA,如表3所示是flash_ control模塊的信號列表,其中flash_control_en信號由按鍵產(chǎn)生。
| 信號列表 | ||
| 信號名 | I/O | 位寬 |
| clk | I | 1 |
| rst_n | I | 1 |
| flash_control_en | I | 1 |
| flash_rdfifo_rdy | I | 8 |
| flash_dqout | I | 1 |
| flash_dqin | O | 1 |
| flash_cs | O | 1 |
| flash_cmd | O | 8 |
| flash_rd_dout | O | 8 |
| flash_rd_dout_vld | O | 1 |
表3 flash_ control模塊信號列表
? ? ? ? 如圖13所示是FLASH控制模塊的代碼設(shè)計,和上個例程讀寫EEPROM類似,這里也需要一個FIFO用來緩存從FLASH的0地址頁內(nèi)讀出的256字節(jié)數(shù)據(jù),本模塊中例化了FLASH驅(qū)動模塊,通過向下游模塊發(fā)送flash_driver_en使能和flash_cmd命令和FLASH驅(qū)動模塊數(shù)據(jù)交互,狀態(tài)機的跳轉(zhuǎn)按照前面芯片手冊提取出的信息設(shè)計即可,沒有太多復(fù)雜的東西。
圖13 FLASH控制模塊的代碼設(shè)計
? ? ? ? 如圖14所示是FLASH讀寫頂層文件的例化,這里只需要把幾個模塊相關(guān)信號例化到一起即可,如圖15所示是串口助手讀取FLASH頁的數(shù)據(jù)實驗截圖,用戶去按下豌豆開發(fā)板上的按鍵,就會觸發(fā)FLASH控制模塊的一系列指令操作,通過先擦除再寫入后讀取的方式,即首先擦除0地址頁內(nèi)的數(shù)據(jù),接著從0-255依次寫入0地址頁內(nèi)256字節(jié)數(shù)據(jù),最后從0地址頁內(nèi)讀取256字節(jié)的數(shù)據(jù)打印到串口助手上顯示。
圖14 FLASH讀寫頂層文件的例化
圖15 串口助手讀取FLASH頁的數(shù)據(jù)
源工程代碼下載鏈接(含datasheet):
鏈接:https://pan.baidu.com/s/1R_Bsakz545CfCZgco-vzwg?
提取碼:cdug?
總結(jié)
以上是生活随笔為你收集整理的FPGA 20个例程篇:7.FLASH读写断电存储的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LearnOpenGL - 纹理贴图 源
- 下一篇: IIS6/IIS7无法打开IIS管理器的