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