• 方案介紹
  • 附件下載
  • 相關(guān)推薦
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

SPI flash(M25P16芯片)實(shí)驗(yàn)設(shè)計(jì)Verilog代碼Quartus AX301開發(fā)板

加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

2-24111120020cM.docx

共1個(gè)文件

名稱:spi flash(M25P16芯片)實(shí)驗(yàn)設(shè)計(jì)Verilog代碼Quartus AX301開發(fā)板

軟件:Quartus

語言:Verilog

代碼功能:

由于 FPGA 是基于 SRAM 結(jié)構(gòu)的,程序掉電后會(huì)丟失,所以需要一個(gè)外置 Flash 保存程序,F(xiàn)PGA 每次上電后去讀取 Flash 中的配置程序,在 ALINX 開發(fā)板中,很多使用的是 SPI 接口的 nor flash,這種 flash 只需要 4 根 IO。FPGA 的配置 flash 是特殊的 IO,上電時(shí)工作,F(xiàn)PGA 要使用這些IO 來讀取 Flash,讀取完成后釋放這些 IO 交給用戶使用。

本實(shí)驗(yàn)做一個(gè) SPI 主設(shè)備控制器,然后按照 spi Flash 數(shù)據(jù)手冊的命令要求發(fā)出擦除、編程、讀取等指令,每次上電后將 flash 中第一個(gè)字節(jié)讀取并顯示出來,按鍵按下時(shí),數(shù)字加 1 再寫回 flash。

主要學(xué)習(xí) spi 接口、spi flash 操作等,由于篇幅有限,本文不詳細(xì)介紹 SPI 協(xié)議和 spi flash 的操作時(shí)序。

FPGA代碼Verilog/VHDL代碼資源下載:www.hdlcode.com

本代碼已在AX301開發(fā)板驗(yàn)證,AX301開發(fā)板如下,其他開發(fā)板可以修改管腳適配:

AX301開發(fā)板.png

設(shè)計(jì)文檔:

SPI Flash 實(shí)驗(yàn)

FPGA設(shè)計(jì)

1 實(shí)驗(yàn)簡介

由于 FPGA 是基于 SRAM 結(jié)構(gòu)的,程序掉電后會(huì)丟失,所以需要一個(gè)外置 Flash 保存程序,F(xiàn)PGA 每次上電后去讀取 Flash 中的配置程序,在 ALINX 開發(fā)板中,很多使用的是 SPI 接口的 nor flash,這種 flash 只需要 4 根 IO。FPGA 的配置 flash 是特殊的 IO,上電時(shí)工作,F(xiàn)PGA 要使用這些IO 來讀取 Flash,讀取完成后釋放這些 IO 交給用戶使用。

本實(shí)驗(yàn)做一個(gè) SPI 主設(shè)備控制器,然后按照 spi Flash 數(shù)據(jù)手冊的命令要求發(fā)出擦除、編程、讀取等指令,每次上電后將 flash 中第一個(gè)字節(jié)讀取并顯示出來,按鍵按下時(shí),數(shù)字加 1 再寫回 flash。

主要學(xué)習(xí) spi 接口、spi flash 操作等,由于篇幅有限,本文不詳細(xì)介紹 SPI 協(xié)議和 spi flash 的操作時(shí)序,但這些知識(shí)都是本實(shí)驗(yàn)基礎(chǔ)。

2 實(shí)驗(yàn)原理

2.1 硬件介紹

如圖所示,AX301、AX4010 開發(fā)板上有一個(gè) SPI Flash,通常是做為 FPGA 的程序配置 Flash,但是也可以做為用戶 Flash 使用,我們可以把自己的少量數(shù)據(jù)保存在 Flash 中。

AX301、AX4010 開發(fā)板 SPI flash

2.2 Flash 時(shí)序和命令

對(duì)一個(gè)器件進(jìn)行操作前,我們首先要了解 Flash 的各種特性,特別是和我們操作相關(guān)的特性,大部分芯片廠商會(huì)提供芯片的數(shù)據(jù)手冊,這些芯片手冊一般可以通過芯片廠商網(wǎng)站獲取,有些廠商需要簽訂保密協(xié)議才能提供數(shù)據(jù)手冊。所以獲取芯片數(shù)據(jù)手冊也是非常重要的學(xué)習(xí)內(nèi)容,首先通過搜索引擎搜索,在沒有搜索結(jié)果時(shí)可到芯片廠商官網(wǎng)找找,很多芯片數(shù)據(jù)手冊下載是需要注冊登錄,然后再下載。注意:在進(jìn)行試驗(yàn)前請(qǐng)先閱讀配套資料芯片手冊文件夾下的FLASH datasheet,搞清楚flash 命令,地址和數(shù)據(jù)之間的時(shí)序關(guān)系。

2.2.1 SPI 模式

SPI 可以通過 CPOL,CPHA 來配置模式,這對(duì)于剛接觸 SPI 協(xié)議比較費(fèi)勁,暫且不去理會(huì)。SPI Flash 支持 2 種配置模式(These devices can be driven by a microcontroller with its SPI peripheral running in either of the two following modes):

CPOL=0, CPHA=0

CPOL=1, CPHA=1

這 2 種數(shù)據(jù)模式,數(shù)據(jù)輸入都是在串行時(shí)鐘的上升沿鎖存數(shù)據(jù),在串行時(shí)鐘的下降沿送出數(shù)據(jù)。(For these two modes, input data is latched in on the rising edge of Serial Clock (C), and output data is available from the falling edge of Serial Clock (C)).

2 種 SPI 模式數(shù)據(jù)波形

2.2.2 Flash 的主要操作

頁編程(Page programming)

編程指令就是講 Flash 的數(shù)據(jù)位由 1 變成 0,只能由 1 變成 0,如果要從 0 變成 1,只能使用 擦除操作。要編程一個(gè)數(shù)據(jù)字節(jié),需要兩個(gè)指令:寫使能(WREN),這是一個(gè)字節(jié)和一個(gè)頁編程(pp)指令,它由四字節(jié)加上數(shù)據(jù)組成。為了提高性能,頁編程(PP)指令最多允許 256 字節(jié), 當(dāng)然這些數(shù)據(jù)都必須在一頁內(nèi),不能跨頁連續(xù)讀取。從頁編程指令時(shí)序圖可以看出,SPI 需要先發(fā) 送一個(gè)字節(jié)的指令,再發(fā)出 3 個(gè)字節(jié)的地址,然后再發(fā)出數(shù)據(jù),最大 256 個(gè)數(shù)據(jù)。將數(shù)據(jù)寫入后 檢查狀態(tài)寄存器 WIP 位(狀態(tài)寄存器最低位)的值,若為 1 表示處于數(shù)據(jù)寫入周期,若為 0 表示 寫入周期完成,可以進(jìn)行下一步操作。

頁編程指令時(shí)序

頁編程之前需要寫使能有效,需要先發(fā)送寫使能指令,指令時(shí)序如下圖,寫使能只有一個(gè)字 節(jié)。可以反復(fù)發(fā)送寫使能。

寫使能指令時(shí)序

塊擦除指令(Bulk Erase)

塊擦除指令(BE)可以把整個(gè) flash 都變成 1,同樣,在塊擦除之前需要先發(fā)送寫使能指令。 Flash 的擦除需要的時(shí)間很長,容量不同時(shí)間會(huì)有差異,一般需要幾分鐘擦除整片芯片。塊擦除指 令發(fā)出后,我們通過不斷讀取狀態(tài)寄存器(Status Register)來查詢擦除是否完成。

hdlcode.com

塊擦除指令時(shí)序

扇區(qū)擦除指令(Sector Erase)

扇區(qū)擦除(SE)指令可以按照扇區(qū)擦除 Flash。和塊擦除不同的是,扇區(qū)擦除是要指定扇區(qū)地 址,扇區(qū)擦除前也需要發(fā)送寫使能指令。

扇區(qū)擦寫指令

讀數(shù)據(jù)指令(Read Data Bytes)

讀 flash 是非常常見的操作,首先拉低片選信號(hào),然后發(fā)出讀指令,3 個(gè)字節(jié)的讀地址,然后 就可以持續(xù)讀出數(shù)據(jù),地址自動(dòng)累加。器件處于擦除或數(shù)據(jù)寫入周期時(shí),數(shù)據(jù)讀取指令無效并且 對(duì)當(dāng)前周期無任何影響。

讀數(shù)據(jù)指令

flash 的其他指令這里不再介紹,其他指令如下圖表格。

flash 指令列表

3 程序設(shè)計(jì)

spi flash 讀寫相對(duì)比較復(fù)雜,本實(shí)驗(yàn)將 flash 操作分解為 3 層,最底層為 SPI 驅(qū)動(dòng)層,每次寫一個(gè)字節(jié)返回一個(gè)字節(jié),然后是 flash 指令層,flash 指令層通過 spi 主控制器讀寫數(shù)據(jù),完成最基本的 flash 各種指令,然后是 flash 擦除、編程、讀寫層,為其他模塊提供可直接操作 flash 的接口。

SPI主設(shè)備控制器

(spi master)

Flash擦除、編程、 讀寫控制

(spi flash ctrl )

spi flash 控制器框圖

為了檢驗(yàn) flash 掉電不丟失的功能,實(shí)驗(yàn)設(shè)計(jì)了一個(gè)狀態(tài)機(jī),上電一段時(shí)間后讀取 flash 的第 一個(gè)字節(jié),并通過數(shù)碼管顯示出來,如果按鍵按下,將數(shù)字加 1,再寫回 flash,這樣下次上電會(huì) 保持新寫入的數(shù)據(jù)。

spi master 狀態(tài)機(jī)設(shè)計(jì),主要完成一個(gè)字節(jié) spi 數(shù)據(jù)的讀寫,由于是全雙工的,寫一個(gè)字節(jié)的 同時(shí)也讀一個(gè)字節(jié)。首先空閑狀態(tài)“IDLE”接收到寫請(qǐng)求后進(jìn)入“DCLK_IDLE”狀態(tài),這個(gè)狀態(tài)為 spi 時(shí)鐘沿變化保持一定的時(shí)間,用來控制 spi 時(shí)鐘的周期,然后進(jìn)入 spi 時(shí)鐘沿的變化狀態(tài),一 個(gè)字節(jié)上升沿和下降沿一共 16 個(gè)數(shù)據(jù)沿。在最后一個(gè)數(shù)據(jù)沿進(jìn)入“LAST_HALF_CYCLE”狀態(tài),為 讓最后一個(gè)沿也保持一定的時(shí)間,再進(jìn)入應(yīng)答狀態(tài),完成一次寫請(qǐng)求。

spi master 模塊狀態(tài)圖

spi_master 模塊中模擬了一個(gè) spi 時(shí)鐘,在狀態(tài)機(jī)進(jìn)入到‘DCLK_EDGE’時(shí)進(jìn)行翻轉(zhuǎn)

在‘spi_flash_top’模塊中例化‘spi_master’模塊時(shí)已經(jīng)設(shè)定‘clk_div’的值為 0,目的是將 模擬的 spi 時(shí)鐘‘DCLK_reg’進(jìn)行 4 分頻,也就是當(dāng)‘clk_div=0’整個(gè)模塊運(yùn)行時(shí),從狀態(tài)‘IDLE’ 跑到狀態(tài)‘DCLE_EDGE’需要 4 個(gè)‘sys_clk’周期。至于其他不能夠理解的地方請(qǐng)大家詳細(xì)了解 spi 總線時(shí)序和 flash 讀寫時(shí)序后再來看或許會(huì)有更深的認(rèn)識(shí)。當(dāng)然,最直觀的方法還是仿真

信號(hào)名稱 方向 說明
sys_clk in 時(shí)鐘輸入
rst in 異步復(fù)位輸入,高復(fù)位
nCS out spi 片選信號(hào),等于 nCS_ctrl。
DCLK out spi 串行時(shí)鐘
MOSI out spi 串行數(shù)據(jù)輸出
MISO in spi 串行數(shù)據(jù)輸入
CPOL in Clock Polarity,spi 時(shí)鐘的極性

0:空閑狀態(tài)為 0

1:空閑狀態(tài)為 1

CPHA in Clock Phase,spi 時(shí)鐘的相位,

0:第一個(gè)沿采樣,

1:第二個(gè)沿采樣

nCS_ctrl in nCS 控制
clk_div in spi 時(shí)鐘頻率控制

spi 時(shí)鐘=系統(tǒng)時(shí)鐘/(2*(2+ clk_div))

clk_div 最小值可以為 0,當(dāng)為 0 時(shí),spi 時(shí)鐘是系統(tǒng) 時(shí)鐘的 1/4

wr_req in 寫一個(gè)字節(jié)請(qǐng)求
wr_ack out 寫應(yīng)答,高有效
data_in in 數(shù)據(jù)
data_out out 返回的數(shù)據(jù),當(dāng)寫應(yīng)答時(shí)有效

spi master 端口說明

spi _flash_cmd 模塊狀態(tài)機(jī)設(shè)計(jì),如下圖所示,在收到命令請(qǐng)求以后進(jìn)入“S_CMD_LATCH”命 令鎖存狀態(tài),將請(qǐng)求的命令記錄下來,然后進(jìn)入“S_CS_LOW”狀態(tài),拉低 spi 的片選信號(hào),再進(jìn)入“S_WR_CMD_CODE”狀態(tài),發(fā)送一個(gè)字節(jié)的命令碼,如果這個(gè)命令只有一個(gè)字節(jié),進(jìn)入“S_KEEP_CS_LOW”狀態(tài),保持一個(gè)周期的片選拉低,然后進(jìn)入“S_CS_HIGH”狀態(tài),拉高片選。 如果命令后面還有地址等數(shù)據(jù),進(jìn)入“S_WRITE_BYTES”寫數(shù)據(jù)狀態(tài),或進(jìn)入“S_READ_BYTES” 讀。需要注意,在 spi 數(shù)據(jù)接口‘data_recv’向數(shù)據(jù)輸出接口‘data_out’傳送數(shù)據(jù)時(shí),是舍棄了 3 個(gè)字節(jié)的地址位,只傳送數(shù)據(jù)位。而在產(chǎn)生‘data_req’信號(hào)時(shí)‘byte_cnt’卻是到 2,為了滿 足數(shù)據(jù)寫入的時(shí)序要求,這里提前了一個(gè)時(shí)鐘周期

spi_flash_cmd 狀態(tài)機(jī)

信號(hào)名稱 方向 說明
sys_clk in 時(shí)鐘輸入
rst in 異步復(fù)位輸入,高復(fù)位
cmd in 命令編碼
cmd_valid in 命令有效
cmd_ack out 命令應(yīng)答
addr in flash 地址
data_in in 命令有寫操作時(shí)的數(shù)據(jù)
size in 命令+數(shù)據(jù)長度(字節(jié))
data_req out 命令有寫操作時(shí)請(qǐng)求數(shù)據(jù),其他 data_in 一個(gè)時(shí)鐘周 期
data_out out 命令有讀操作時(shí)讀出的數(shù)據(jù)

 

data_valid out 命令有讀操作時(shí)讀有效
CS_reg out 對(duì) spi master 接口,spi 片選控制
wr_req out 對(duì) spi master 接口,spi 寫請(qǐng)求
wr_ack in 對(duì) spi master 接口,spi 寫應(yīng)答
send_data out 對(duì) spi master 接口,spi 寫數(shù)據(jù)
data_recv in 對(duì) spi master 接口,spi 讀數(shù)據(jù)

spi_flash_cmd 模塊端口

spi_flash_ctrl 模塊主要完成 flash 擦除、編程、讀操作。擦除前需要寫使能有效、等待擦除完

成等多項(xiàng) flash 命令。狀態(tài)機(jī)如下圖所示:

“S_IDLE”:空閑狀態(tài)

“S_WREN”:寫使能命令狀態(tài)

“S_READ”:讀狀態(tài)

“S_WRITE”:寫狀態(tài)(編程)

“S_SE”:扇區(qū)擦除

“S_BE”:塊擦除

“S_CK_STATE”:狀態(tài)寄存器檢查,用來檢測是否擦除完成等。

“S_ACK”:請(qǐng)求應(yīng)答

spi_flash_ctrl 狀態(tài)機(jī)

信號(hào)名稱 方向 說明
sys_clk in 時(shí)鐘輸入
rst in 異步復(fù)位輸入,高復(fù)位
flash_read in flash 讀請(qǐng)求
flash_write in flash 寫請(qǐng)求
flash_bulk_erase in 塊擦除請(qǐng)求
flash_sector_erase in 扇區(qū)擦除請(qǐng)求
flash_read_ack out 讀應(yīng)答
flash_write_ack out 寫應(yīng)答
flash_bulk_erase_ack out 塊擦除應(yīng)答
flash_sector_erase_ack out 扇區(qū)擦除應(yīng)答
flash_read_addr in 讀請(qǐng)求地址
flash_write_addr in 寫請(qǐng)求地址
flash_sector_addr in 扇區(qū)擦除地址
flash_write_data_in in 寫請(qǐng)求數(shù)據(jù)
flash_read_size in 讀字節(jié)大小
flash_write_size in 寫字節(jié)大小
flash_write_data_req out 寫數(shù)據(jù)拉取,提前 flash_write_data_in 一個(gè)時(shí)鐘
flash_read_data_out out 讀數(shù)據(jù)
flash_read_data_valid out 讀數(shù)據(jù)有效
cmd out 連接 spi_flash_cmd 模塊,命令編碼
cmd_valid out 連接 spi_flash_cmd 模塊,命令有效
cmd_ack in 連接 spi_flash_cmd 模塊,命令應(yīng)答
addr out 連接 spi_flash_cmd 模塊,flash 地址
data_in out 連接 spi_flash_cmd 模塊,命令有寫操作時(shí)的數(shù)據(jù)
size out 連接 spi_flash_cmd 模塊,命令+數(shù)據(jù)長度(字節(jié))
data_req in 連接 spi_flash_cmd 模塊,命令有寫操作時(shí)請(qǐng)求數(shù) 據(jù),其他 data_in 一個(gè)時(shí)鐘周期
data_out in 連接 spi_flash_cmd 模塊,命令有讀操作時(shí)讀出的數(shù) 據(jù)
data_valid in 連接 spi_flash_cmd 模塊,命令有讀操作時(shí)讀有效

spi_flash_ctrl 端口

在這個(gè)模塊狀態(tài)機(jī)的‘S_CK_STATE’狀態(tài),進(jìn)行狀態(tài)轉(zhuǎn)移的條件不僅有命令應(yīng)答信號(hào)還需要判斷‘state_reg’寄存器的最低位,需要知道的是‘state_reg’的最低位就是 WIP 位,顯示 SPI 是否在寫入狀態(tài),為 0 時(shí)表示該狀態(tài)不忙。同時(shí),在 spi_flash_ctrl 模塊中,我們調(diào)用了一個(gè)宏定義模塊,和 C 語言里的宏定義類似,宏定義模塊里面定義了對(duì) flash 操作的各種命令,其用法和格式請(qǐng)參照例程。

4 實(shí)驗(yàn)現(xiàn)象

將程序下載到開發(fā)板以后,數(shù)碼管顯示一個(gè)數(shù)字,這個(gè)數(shù)字是 flash 的第一個(gè)字節(jié),通過按下key1 鍵,數(shù)字會(huì)加一,同時(shí)擦除了 flash,并將新的數(shù)據(jù)寫入,重新上電后,加載下載程序,數(shù)碼管將顯示最后一次按按鍵的數(shù)字。注意:由于 flash 擦寫需求一定的時(shí)間,按鍵不能按的太快。

部分代碼展示:

`define CMD_WREN          8'h06
`define CMD_WRDI          8'h04
`define CMD_RDID          8'hAB       //EPCS4 EPCS16 is 0'hab st spi flash is 8'h9f
`define CMD_RDSR          8'h05
`define CMD_WRSR          8'h01
`define CMD_READ          8'h03
`define CMD_FAST_READ     8'h0b
`define CMD_PP            8'h02
`define CMD_SE            8'hd8
`define CMD_BE            8'hc7

點(diǎn)擊鏈接獲取代碼文件:http://www.hdlcode.com/index.php?m=home&c=View&a=index&aid=1345

  • 2-24111120020cM.docx
    下載

相關(guān)推薦