關珊珊,周潔敏
(南京航空航天大學民航學院,南京210016)
現(xiàn)場可編程門陣列FPGA 常常進行大數(shù)據(jù)量的處理,數(shù)據(jù)的存儲便成了問題,利用SPI Flash 大容量、讀寫速度快、成本低廉以及數(shù)據(jù)在斷電后不丟失的特點,可以將配置數(shù)據(jù)存儲于SPI Flash 中[1]。它比起傳統(tǒng)的并行總線接口Flash 來說節(jié)省了很多的I/O 口資源,從而為系統(tǒng)功能的擴展提供了更多的可能。為此提出了一種基于FPGA 的SPI Flash 控制器的設計方法,并用Verilog HDL 實現(xiàn),在Isim 中得出仿真和驗證結果,最終應用在自行設計的VGA顯示控制電路中得到成功應用,而且可以擴展到所有類似系統(tǒng)中[2]。
FPGA 芯片采用的Spartan-6 系列的xc6slx9 芯片,封裝采用tqg-144,該系列FPGA 能提供高達400 MHz 的工作時鐘,高達5 720 個高效的雙寄存器6 輸入查找表(LUT)和一系列豐富的內置系統(tǒng)級模塊,采用成熟的45 nm 低功耗銅制程技術制造,實現(xiàn)了性價比與功耗的完美平衡。該芯片有9152 個邏輯單元(Logic Element),32 個18 kbyte 的Block RAM 模塊,16 個18×18 bit 嵌入式乘法器,2 個鎖相環(huán)(PLL)和4個時鐘管理模塊(DCM)。在這款144 針tqg 封裝的FPGA 中,用戶可用I/O 為102 個[3],可以滿足本系統(tǒng)的需求。
Flash 芯片采用的配置芯片是Winbond 公司的W25Q80BV 系列8 M bit 容量的SPI Flash,該芯片共由16 部分組成,每一部分有256 頁,每頁有256 個字節(jié)。該系列芯片具有先進的寫保護機制,讀取數(shù)據(jù)的最大時鐘速率為50 MHz。工作的電壓范圍為2.7 V ~3.6 V,具有整體擦除和扇區(qū)擦除、靈活的頁編程指令和寫保護功能,數(shù)據(jù)保存至少20 y(year),每個扇區(qū)可承受100 000 次擦寫循環(huán)。SPI Flash 具有掉電保存能力,在系統(tǒng)上電時,F(xiàn)PGA 首先從配置芯片SPI Flash 中讀取編程數(shù)據(jù),并對FPGA 進行加載。SPI Flash 的HOLD#和WP#管腳要接上拉電阻,因為FPGA 上電時管腳為高阻態(tài),如無此上拉電阻,F(xiàn)LASH 的HOLD#和WP#輸入為浮置狀態(tài),沒有確定的電平,進而導致數(shù)據(jù)總線電平也不確定,這是不允許的。
本系統(tǒng)由串口、FPGA 和SPI Flash 構成,系統(tǒng)整體框圖如圖1 所示。
圖1 系統(tǒng)框圖
圖1中,F(xiàn)PGA 為電路核心,一方面接收來自PC 串口的數(shù)據(jù),并將數(shù)據(jù)寫入Flash 中;一方面從Flash 中讀出數(shù)據(jù);另一方面產(chǎn)生系統(tǒng)所需的各種控制信號。作為現(xiàn)場可編程器件,F(xiàn)PGA 能方便地燒入程序來改變它的功能,所以在設計調試時,可將.bit 文件燒入FPGA 進行在線調試,也可將.mcs 文件程序直接下載到SPI Flash 中進行功能驗證。
FPGA 的頂層文件包括七個模塊,如圖2 所示。
圖2 FPGA 內部構成框圖
圖2 中,復位信號主要是同步外部的復位信號;DCM 模塊主要是倍頻和管理時鐘;串口接收模塊把從串口得到的數(shù)據(jù)緩存到FIFO;Flash 控制模塊主要是控制對外部SPI Flash 的讀寫,把從串口得到的數(shù)據(jù)存入到SPI Flash,并不斷把SPI Flash 中的數(shù)據(jù)送到串口發(fā)送模塊;CoreRAM 是Xilinx 專用的一個IP 核,本設計中用于FPGA 內部數(shù)據(jù)的緩存;SPI 接口模塊為SPI Flash 提供串行時鐘,并實現(xiàn)數(shù)據(jù)的串并轉換。當上層用戶發(fā)送指令要將FPGA 的配置數(shù)據(jù)存入SPI Flash 時,配置數(shù)據(jù)從串口接收模塊輸出給Flash 模塊,F(xiàn)lash 模塊將數(shù)據(jù)不斷提取到CoreRAM 中,CoreRAM 中的數(shù)據(jù)經(jīng)過Flash 模塊寫入到SPI Flash 中。當系統(tǒng)重新上電要對FPGA 進行配置時,將SPI Flash 中的數(shù)據(jù)讀入到Flash 模塊中,再將Flash 模塊中數(shù)據(jù)緩存在CoreRAM 中,最后將CoreRAM 中的數(shù)據(jù)提取給上層相應的模塊,完成對FPGA 的配置。
從以上分析可以知道,F(xiàn)PGA 內部的數(shù)據(jù)流向非常的明朗,模塊之間的關系也很確切,所以這個框圖的劃分具有一定的科學性。如果總體的框圖沒有劃分好,調試成功的可能性也是非常小的。另外,在升級的時候如果要改變數(shù)據(jù)的獲得方式,只要用新的程序替換串口接收模塊即可;如果要改變數(shù)據(jù)的顯示方式,只要用新的程序替換串口發(fā)送模塊即可。下面分別介紹各功能模塊的實現(xiàn)。
串口發(fā)送和接收部分相似,串口接收部分是將來自PC 的串口數(shù)據(jù)發(fā)送到Flash 控制器中,而串口發(fā)送部分是將從Flash 中讀到的數(shù)據(jù)發(fā)送給PC 機,是串口接收的逆向過程,下面以串口發(fā)送部分為例進行分析。串口接收模塊的框圖如圖3 所示。
圖3 串口接收部分框圖
圖3 中包含3 個子模塊,串口接收模塊接收來自PC 串口的數(shù)據(jù),為了使速度盡可能的快,設計用的波特率為115 200 bit/s;緩存接口主要是把串口接收到的數(shù)據(jù)緩存到FIFO;FIFO 是例化的一個模塊,用作數(shù)據(jù)緩存。
2.1.1 串口接收
串口接收程序按照UART 的傳輸原理進行程序設計,本設計省略了奇偶校驗部分,是按照10 bit 的串口傳輸方式設計的。串口程序的核心是一個接收狀態(tài)機,另外還包括接收同步、采樣時能生成和標志位控制模塊。工作原理是來自串口的信號經(jīng)兩級寄存器同步后不斷被采樣,采樣后的信號到接收狀態(tài)機控制獲得串口數(shù)據(jù),如果接收完數(shù)據(jù),把接收到數(shù)據(jù)的標志位置高告訴相關模塊已經(jīng)接收到新數(shù)據(jù),標志位在標志清零輸入置高后被清零,這時候標志位再次置高說明接收到下一個的數(shù)據(jù)。標志位清零的控制要注意清零位的置高周期數(shù),最好為一個周期,不能無限制地永遠置高。串口接收模塊的核心狀態(tài)機的狀態(tài)轉換圖如圖4 所示。
圖4 串口接收狀態(tài)轉移圖
idle:閑置狀態(tài)每個時鐘周期都采樣接收同步信號的值,一旦該信號的值為0 則轉入到下一個狀態(tài)。
first:準備接收狀態(tài)采樣串口接收的起始位,在波特率的16 倍時鐘下采樣,如果6、7、8 次采樣中有兩次為低電平說明是起始位,轉入到下一個狀態(tài)(rxd),否則認為該信號是干擾信號而轉入閑置狀態(tài)(idle)。
rxd:接收狀態(tài)把數(shù)據(jù)接收到并存入暫存寄存器,并產(chǎn)生標志位的原始信號,接收結束是根據(jù)暫存寄存器的最低位來判斷結束的,同時在結束的時候判斷結束位是否為0,如果不為0,則拋棄接收到的數(shù)據(jù)后轉入到閑置狀態(tài)。
2.1.2 緩存接口
緩存接收模塊是一個相對簡單的模塊,它主要是把串口接收模塊接收到的數(shù)據(jù)存入到FIFO,由于串口接收的是8 bit 的數(shù)據(jù),F(xiàn)IFO 的寬度是16 bit,因此每次接收2 bit 數(shù)據(jù)再存入FIFO。緩存接口模塊包含一個控制狀態(tài)機,工作原理是一旦檢測到串口接收模塊的標志位為高時就接收1 字節(jié)的數(shù)據(jù),并轉到接收下1 字節(jié)狀態(tài),這個狀態(tài)接收到第二個數(shù)據(jù),并把整個16 bit 的數(shù)據(jù)存入到FIFO,每次接收1 字節(jié)數(shù)據(jù)后都把清零標志位置高清除串口接收模塊的標志位。
FIFO 是在開發(fā)軟件中例化的一個模塊,為保持較高的速度,剛好用了一個M4K 塊,數(shù)據(jù)的寬度為16 bit,數(shù)據(jù)的存儲深度是256 個。本FIFO 讀數(shù)據(jù)和寫數(shù)據(jù)工作在不同的頻率上,讀數(shù)據(jù)的操作工作在較高的頻率上,寫數(shù)據(jù)的操作工作在較低的頻率上。本FIFO 也把內部的其他模塊和跟數(shù)據(jù)的獲得模塊分離,如果要把串口獲得數(shù)據(jù)模塊改為其他方式就可以直接修改這部分即可。
2.1.3 寫緩沖FIFO
寫緩沖FIFO 指的是串口數(shù)據(jù)的暫存FIFO,在FLASH 主控制模塊中將用到的信號是這個FIFO 的“近空”信號(w_fifo_aempty)。在每行顯示開始的時候都要檢測這個信號,如果w_fifo_aempty 信號為高電平,說明寫緩存FIFO 已經(jīng)有足夠的數(shù)據(jù)用來寫,這時候把FIFO 中的數(shù)據(jù)寫到FLASH 中,當w_fifo_aempty 信號為低電平說明數(shù)據(jù)即將被讀空,這時候通過置w_fifo_re 使能停止向FLASH 寫數(shù)據(jù)。每一次這樣的一個過程至少寫入了突發(fā)數(shù)據(jù)傳輸?shù)臄?shù)據(jù)個數(shù)。
寫緩沖FIFO 的寫是uart_inf 這個模塊來控制的,只有在uart_rxd 接受完兩個字節(jié)的數(shù)據(jù)后把這個數(shù)據(jù)合成一個16 bit 的數(shù)據(jù)存入到FIFO,準備好數(shù)據(jù)的同時把FIFO 的寫使能置為低電平一個周期即可以把數(shù)據(jù)寫入到FIFO 中。
Flash 正常工作時必須嚴格按照Flash 的時序控制信號,F(xiàn)lash 主控制模塊在兩個有限狀態(tài)機的控制下來進行,寫Flash 狀態(tài)機和讀Flash 狀態(tài)機。
由于Flash 的寫操作只能將數(shù)據(jù)1 改寫成為0,擦除操作才能將數(shù)據(jù)0 改寫為1。所以FPGA 剛上電時,程序首先對Flash 進行擦除操作,將指定區(qū)域全寫為1。當需要執(zhí)行寫Flash 的操作時,應該首先把數(shù)據(jù)寫到FPGA 內部的BlockRAM 中,然后按照Flash Datasheet 中的頁面編程時序向Flash 中寫入數(shù)據(jù)。Xilinx 公司為用戶提供了功能豐富的IP 核,設計中需要的BlockRAM 模塊可直接在ISE 中調用IP 核,F(xiàn)lash 主控制模塊可以控制存取BlockRAM 的地址和時間,并且按照Flash 的頁編程時序,將并行數(shù)據(jù)通過SPI 接口模塊轉換為串行數(shù)據(jù)后送入到Flash 中。W25Q80BV 的頁面編程指令的時序圖如圖5 所示。
圖5 W25Q80BV 頁面編程指令時序圖
圖5 中,首先拉低/CS(片選信號),第1 個時鐘上升沿將頁面編程指令02H 送入Flash 內,然后輸入3 個字節(jié)的首地址,緊接著輸入編程數(shù)據(jù)。頁面編程一次最多可以輸入256 個字節(jié)的數(shù)據(jù),若超出256 個字節(jié),則僅保留最后輸入的256 個字節(jié)的數(shù)據(jù)。如果輸入低8 bit 不全為零的地址,從輸入的地址進行編程,一直編程到該頁的最后,接著從該頁的起始地址進行編程。同樣,輸入完數(shù)據(jù)后片選信號也必須拉高,否則頁面編程指令不被執(zhí)行[4]。
按照寫Flash 的時序設計狀態(tài)機,當寫使能有效時,狀態(tài)機由閑置狀態(tài)(idle)進入傳輸寫使能指令狀態(tài)(tx_cmd),經(jīng)過寫使能指令等待狀態(tài)(wait1)進入到傳輸擦除指令狀態(tài)(tx_erase),然后經(jīng)過傳輸擦除指令等待狀態(tài)(wait2)后,擦除命令執(zhí)行完畢。接著執(zhí)行寫Flash 的操作,首先還是進入傳輸寫使能指令狀態(tài)(tx_cmd)和寫使能等待狀態(tài),然后進入傳輸頁面編程指令狀態(tài)(tx_pro),經(jīng)過三個字節(jié)的傳輸?shù)刂窢顟B(tài)(txadd)進入到傳輸數(shù)據(jù)狀態(tài)(txdata),輸入完256 個字節(jié)的數(shù)據(jù)后,進入到清除指令(clr_cmd)狀態(tài),最后恢復到閑置(idle)狀態(tài)。寫Flash 狀態(tài)機如圖6 所示。
圖6 寫Flash 狀態(tài)機
當需要執(zhí)行讀Flash 的操作時,應該首先按照Flash 的讀數(shù)據(jù)指令時序將串行數(shù)據(jù)轉化為并行數(shù)據(jù)讀入FPGA 的BlockRAM 中,然后從BlockRAM 中將數(shù)據(jù)讀入到上層用戶。W25Q80BV 的讀數(shù)據(jù)指令的時序圖如圖7 所示。
圖7 W25Q80BV 的讀數(shù)據(jù)指令時序圖
由圖7 可以看出,W25Q80BV 的讀數(shù)據(jù)指令時序比較簡單,在/CS(片選信號)信號拉低以后的時鐘第一個上升沿,按照高位在前低位在后的順序將讀數(shù)據(jù)指令03H 送到Flash 中,接著將所需讀取內容的3 個字節(jié)的首地址送入Flash,在輸入完畢后的第一個時鐘下降沿,該首地址所指向的8 bit 數(shù)據(jù)便會按照從高位到低位的順序輸出。輸出完畢后,地址會自動遞增,然后指向下一個地址。接著輸出下一個地址所指向的數(shù)據(jù),并且當?shù)刂返竭_最高位后將會自動轉回到首地址000000h,按照上述操作循環(huán)執(zhí)行,就可讀出Flash 中所有的內容,一直到拉高/CS 片選信號為止[5]。
按照讀Flash 的時序設計狀態(tài)機,F(xiàn)lash 中的數(shù)據(jù)只要按照讀時序要求就可以順利讀入FPGA 中進行運算。狀態(tài)機由閑置狀態(tài)(idle)進入傳輸讀數(shù)據(jù)指令狀態(tài)(tx_cmd),讀數(shù)據(jù)指令同樣需要3 個字節(jié)的地址數(shù)據(jù)來指定讀取據(jù)存儲空間的起始地址,當芯片被選中時,就可以一直不斷地從SPI Flash 中讀取數(shù)據(jù)。接著SPI Flash 控制器經(jīng)過傳輸?shù)刂?txadd)狀態(tài)進入到讀數(shù)據(jù)(rxdata)狀態(tài),如果還有未傳輸完的數(shù)據(jù)(即byte_count 未計數(shù)到256),SPI Flash 控制器則繼續(xù)留在讀數(shù)據(jù)狀態(tài),直到所需讀取的數(shù)據(jù)都傳輸完后,再進入到清除指令(clr_cmd)狀態(tài),最后恢復到閑置(idle)狀態(tài)。讀Flash 狀態(tài)機如圖8 所示。
圖8 讀Flash 狀態(tài)轉移圖
由于本設計選用的Flash 容量較大,一般FPGA 沒有這么大的存儲空間,所以FPGA 中需要調用數(shù)據(jù)緩沖存儲器BlockRAM。它是由Xilinx 提供的IPCore,設計比較方便,而且靈活、高效、不容易出錯。BlockRAM有兩個完全獨立的端口科技進入共享的存儲空間,兩個端口都有讀/寫接口。IP 允許使用者在FPGA 內部快速建立優(yōu)化的存儲器資源,本系統(tǒng)采用單端口設計,在BlockRAM 屬性選擇中將端口A 的寬度選為8,將深度選為256,配置選項選為Read And Write(讀和寫),寫模式選為Write After Read。當向BlockRAM 中寫數(shù)據(jù)時,將WEA 和ENA 置位,并輸入地址和數(shù)據(jù)即可;當需要從BlockRAM 中讀數(shù)據(jù)時,由于采用了Read And Write 模式,所以只要將地址輸入給BlockRAM,就會順利的將指定地址的數(shù)據(jù)讀出[6]。
在此模塊中將設計分為三大塊:并行數(shù)據(jù)串行移位,分頻,串行數(shù)據(jù)并行移位。SPI Flash 的工作時鐘是由外部控制器提供的,本設計中主時鐘為48 MHz,取4 點進行采樣,每到一個采集點,時鐘翻轉一次,完成分頻,分頻得到的時鐘1 MHz 作為SPI Flash 的時鐘輸入。
由從Flash 控制器中得到的數(shù)據(jù)為并行數(shù)據(jù),但SPI Flash 為串行接口,所以SPI 接口模塊主要功能是將FPGA 發(fā)送的并行數(shù)據(jù)轉化為串行數(shù)據(jù)輸出給SPI Flash,系統(tǒng)由閑置狀態(tài)進入并行數(shù)據(jù)串行移位狀態(tài),啟動延時模塊,s_do 的值要保持48×8 個系統(tǒng)周期才能使得mosi 在一個SPI 周期輸出1 bit 數(shù)據(jù),同時移位寄存器左移1 bit,將最高位賦給mosi 輸出,如此反復直到輸出8 bit 數(shù)據(jù),為滿足SPI Flash 的響應時間,系統(tǒng)增加傳輸?shù)却隣顟B(tài),經(jīng)過傳輸?shù)却隣顟B(tài)又回到閑置狀態(tài),完成了一個字節(jié)數(shù)據(jù)的寫入。
同樣,當需要讀SPI Flash 中的數(shù)據(jù)時,將SPI Flash 中的串行數(shù)據(jù)轉化為并行數(shù)據(jù)送入FPGA 中,系統(tǒng)由閑置狀態(tài)進入串行數(shù)據(jù)并行移位狀態(tài),在此狀態(tài)啟動延時模塊,SPI Flash 輸出1 bit 數(shù)據(jù)需要48個系統(tǒng)周期,輸出8 bit 數(shù)據(jù)就要48×8 個系統(tǒng)周期,即s_di 要保持48×8 個系統(tǒng)周期,首先將miso 的值賦給s_di[0],將s_di 左移一位,當延時48 個周期后,反復上述操作,直到將8 bit miso 數(shù)據(jù)都輸出給s_di,經(jīng)過傳輸?shù)却隣顟B(tài)回到閑置狀態(tài),完成了一個字節(jié)數(shù)據(jù)的讀出。
SPI Flash 控制器在Xilinx ISE12.2 編程環(huán)境下實現(xiàn),結合自帶的仿真軟件Isim 進行仿真。板上調試時鐘選為48 MHz,經(jīng)測試數(shù)據(jù)傳輸準確無誤。由于篇幅有限,本文僅對寫Flash 和讀Flash 給出仿真波形圖并進行分析。
寫Flash 仿真波形如圖9 所示。
圖9 寫Flash 仿真波形
由圖9 可以看出,當SPI Flash 控制器進入到傳輸數(shù)據(jù)(tx_data)狀態(tài),這時s_wr 變高(s_wr 在傳輸指令及數(shù)據(jù)地址時也保持為高電平狀態(tài)),并在整個字節(jié)的寫入程中保持高電平狀態(tài),在s_df 的控制下開始傳輸數(shù)據(jù),經(jīng)過8 個clk 周期SPI Flash 控制器通過一個移位寄存器將從s_do 獲取的用戶端數(shù)據(jù)逐位輸出給SPI Flash。
讀Flash 仿真波形如圖10 所示。
圖10 讀Flash 仿真波形
由圖10 可以看出,當SPI Flash 控制器進入到讀數(shù)據(jù)(rxdata)狀態(tài)時,spi_rd 變高,并在整個字節(jié)的讀數(shù)據(jù)過程中保持高電平狀態(tài),經(jīng)過8 個clk 周期SPI Flash 控制器通過一個移位寄存器將從SPI Flash 中讀取得的1 字節(jié)數(shù)據(jù)寄存起來,最后在通過s_di 輸出給用戶。
本文以實際應用為出發(fā)點,實現(xiàn)了一個基于FPGA 的SPI Flash 控制器,并重點分析了其工作狀態(tài)轉換過程。該控制器能夠很好地實現(xiàn)對FPGA 芯片進行在線配置,具有廣泛的應用價值。該方法具有較高的可移植性,以及簡單方便的用戶接口,并且控制器經(jīng)過簡單的修改就可以用于控制其它型號的SPI Flash 芯片,因此具有很高的可兼容性。
[1] 鄭川.Step By Step 現(xiàn)場可編程門陣列設計入門與進階[M].西安:西安電子科技大學出版社,2008:104-122.
[2] 王小峰,周吉鵬. 一種FPGA 在線配置FLASH 的方法[J]. 電子器件,2006,29(3):902-904.
[3] 張力為,鐘慧敏.實現(xiàn)基于FPGA 的SPI Flash 控制器設計[J].微計算機信息,2010,26(6-2):124-126.
[4] 韋燕.基于FPGA 的SPI 接口時序模擬[J]. 科技信息,2010,21:79-80.
[5] Winbond,Inc.8M-BIT SERIAL FLASH MEMORY WITH DUAL AND QUAD SPI. http://www. Winbond. com/NR/rdonlyres/4D2BF674-7427-4FC8-AEF-1A534DF74F16/0/W25Q80BV.pdf.2009.
[6] Xilinx,Inc.Spartan-6 FPGA Datasheet:DC and Switching Characteristics. http://china. xilinx. com/support/documentation/data_sheets/ds162.pdf.2011.