• 方案介绍
  • 附件下载
  • 相关推荐
申请入驻 产业图谱

SPI flash(M25P16芯片)实验设计Verilog代码Quartus AX301开发板

05/08 15:03
1324
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

2-24111120020cM.docx

共1个文件

名称:spi flash(M25P16芯片)实验设计Verilog代码Quartus AX301开发板

软件:Quartus

语言:Verilog

代码功能:

由于 FPGA 是基于 SRAM 结构的,程序掉电后会丢失,所以需要一个外置 Flash 保存程序,FPGA 每次上电后去读取 Flash 中的配置程序,在 ALINX 开发板中,很多使用的是 SPI 接口的 nor flash,这种 flash 只需要 4 根 IO。FPGA 的配置 flash 是特殊的 IO,上电时工作,FPGA 要使用这些IO 来读取 Flash,读取完成后释放这些 IO 交给用户使用。

本实验做一个 SPI 主设备控制器,然后按照 spi Flash 数据手册的命令要求发出擦除、编程、读取等指令,每次上电后将 flash 中第一个字节读取并显示出来,按键按下时,数字加 1 再写回 flash。

主要学习 spi 接口、spi flash 操作等,由于篇幅有限,本文不详细介绍 SPI 协议和 spi flash 的操作时序。

FPGA代码Verilog/VHDL代码资源下载:www.hdlcode.com

本代码已在AX301开发板验证,AX301开发板如下,其他开发板可以修改管脚适配:

AX301开发板.png

设计文档:

SPI Flash 实验

FPGA设计

1 实验简介

由于 FPGA 是基于 SRAM 结构的,程序掉电后会丢失,所以需要一个外置 Flash 保存程序,FPGA 每次上电后去读取 Flash 中的配置程序,在 ALINX 开发板中,很多使用的是 SPI 接口的 nor flash,这种 flash 只需要 4 根 IO。FPGA 的配置 flash 是特殊的 IO,上电时工作,FPGA 要使用这些IO 来读取 Flash,读取完成后释放这些 IO 交给用户使用。

本实验做一个 SPI 主设备控制器,然后按照 spi Flash 数据手册的命令要求发出擦除、编程、读取等指令,每次上电后将 flash 中第一个字节读取并显示出来,按键按下时,数字加 1 再写回 flash。

主要学习 spi 接口、spi flash 操作等,由于篇幅有限,本文不详细介绍 SPI 协议和 spi flash 的操作时序,但这些知识都是本实验基础。

2 实验原理

2.1 硬件介绍

如图所示,AX301、AX4010 开发板上有一个 SPI Flash,通常是做为 FPGA 的程序配置 Flash,但是也可以做为用户 Flash 使用,我们可以把自己的少量数据保存在 Flash 中。

AX301、AX4010 开发板 SPI flash

2.2 Flash 时序和命令

对一个器件进行操作前,我们首先要了解 Flash 的各种特性,特别是和我们操作相关的特性,大部分芯片厂商会提供芯片的数据手册,这些芯片手册一般可以通过芯片厂商网站获取,有些厂商需要签订保密协议才能提供数据手册。所以获取芯片数据手册也是非常重要的学习内容,首先通过搜索引擎搜索,在没有搜索结果时可到芯片厂商官网找找,很多芯片数据手册下载是需要注册登录,然后再下载。注意:在进行试验前请先阅读配套资料芯片手册文件夹下的FLASH datasheet,搞清楚flash 命令,地址和数据之间的时序关系。

2.2.1 SPI 模式

SPI 可以通过 CPOL,CPHA 来配置模式,这对于刚接触 SPI 协议比较费劲,暂且不去理会。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 种数据模式,数据输入都是在串行时钟的上升沿锁存数据,在串行时钟的下降沿送出数据。(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 模式数据波形

2.2.2 Flash 的主要操作

页编程(Page programming)

编程指令就是讲 Flash 的数据位由 1 变成 0,只能由 1 变成 0,如果要从 0 变成 1,只能使用 擦除操作。要编程一个数据字节,需要两个指令:写使能(WREN),这是一个字节和一个页编程(pp)指令,它由四字节加上数据组成。为了提高性能,页编程(PP)指令最多允许 256 字节, 当然这些数据都必须在一页内,不能跨页连续读取。从页编程指令时序图可以看出,SPI 需要先发 送一个字节的指令,再发出 3 个字节的地址,然后再发出数据,最大 256 个数据。将数据写入后 检查状态寄存器 WIP 位(状态寄存器最低位)的值,若为 1 表示处于数据写入周期,若为 0 表示 写入周期完成,可以进行下一步操作。

页编程指令时序

页编程之前需要写使能有效,需要先发送写使能指令,指令时序如下图,写使能只有一个字 节。可以反复发送写使能。

写使能指令时序

块擦除指令(Bulk Erase)

块擦除指令(BE)可以把整个 flash 都变成 1,同样,在块擦除之前需要先发送写使能指令。 Flash 的擦除需要的时间很长,容量不同时间会有差异,一般需要几分钟擦除整片芯片。块擦除指 令发出后,我们通过不断读取状态寄存器(Status Register)来查询擦除是否完成。

hdlcode.com

块擦除指令时序

扇区擦除指令(Sector Erase)

扇区擦除(SE)指令可以按照扇区擦除 Flash。和块擦除不同的是,扇区擦除是要指定扇区地 址,扇区擦除前也需要发送写使能指令。

扇区擦写指令

读数据指令(Read Data Bytes)

读 flash 是非常常见的操作,首先拉低片选信号,然后发出读指令,3 个字节的读地址,然后 就可以持续读出数据,地址自动累加。器件处于擦除或数据写入周期时,数据读取指令无效并且 对当前周期无任何影响。

读数据指令

flash 的其他指令这里不再介绍,其他指令如下图表格。

flash 指令列表

3 程序设计

spi flash 读写相对比较复杂,本实验将 flash 操作分解为 3 层,最底层为 SPI 驱动层,每次写一个字节返回一个字节,然后是 flash 指令层,flash 指令层通过 spi 主控制器读写数据,完成最基本的 flash 各种指令,然后是 flash 擦除、编程、读写层,为其他模块提供可直接操作 flash 的接口。

SPI主设备控制器

(spi master)

Flash擦除、编程、 读写控制

(spi flash ctrl )

spi flash 控制器框图

为了检验 flash 掉电不丢失的功能,实验设计了一个状态机,上电一段时间后读取 flash 的第 一个字节,并通过数码管显示出来,如果按键按下,将数字加 1,再写回 flash,这样下次上电会 保持新写入的数据。

spi master 状态机设计,主要完成一个字节 spi 数据的读写,由于是全双工的,写一个字节的 同时也读一个字节。首先空闲状态“IDLE”接收到写请求后进入“DCLK_IDLE”状态,这个状态为 spi 时钟沿变化保持一定的时间,用来控制 spi 时钟的周期,然后进入 spi 时钟沿的变化状态,一 个字节上升沿和下降沿一共 16 个数据沿。在最后一个数据沿进入“LAST_HALF_CYCLE”状态,为 让最后一个沿也保持一定的时间,再进入应答状态,完成一次写请求。

spi master 模块状态图

spi_master 模块中模拟了一个 spi 时钟,在状态机进入到‘DCLK_EDGE’时进行翻转

在‘spi_flash_top’模块中例化‘spi_master’模块时已经设定‘clk_div’的值为 0,目的是将 模拟的 spi 时钟‘DCLK_reg’进行 4 分频,也就是当‘clk_div=0’整个模块运行时,从状态‘IDLE’ 跑到状态‘DCLE_EDGE’需要 4 个‘sys_clk’周期。至于其他不能够理解的地方请大家详细了解 spi 总线时序和 flash 读写时序后再来看或许会有更深的认识。当然,最直观的方法还是仿真

信号名称 方向 说明
sys_clk in 时钟输入
rst in 异步复位输入,高复位
nCS out spi 片选信号,等于 nCS_ctrl。
DCLK out spi 串行时钟
MOSI out spi 串行数据输出
MISO in spi 串行数据输入
CPOL in Clock Polarity,spi 时钟的极性

0:空闲状态为 0

1:空闲状态为 1

CPHA in Clock Phase,spi 时钟的相位,

0:第一个沿采样,

1:第二个沿采样

nCS_ctrl in nCS 控制
clk_div in spi 时钟频率控制

spi 时钟=系统时钟/(2*(2+ clk_div))

clk_div 最小值可以为 0,当为 0 时,spi 时钟是系统 时钟的 1/4

wr_req in 写一个字节请求
wr_ack out 写应答,高有效
data_in in 数据
data_out out 返回的数据,当写应答时有效

spi master 端口说明

spi _flash_cmd 模块状态机设计,如下图所示,在收到命令请求以后进入“S_CMD_LATCH”命 令锁存状态,将请求的命令记录下来,然后进入“S_CS_LOW”状态,拉低 spi 的片选信号,再进入“S_WR_CMD_CODE”状态,发送一个字节的命令码,如果这个命令只有一个字节,进入“S_KEEP_CS_LOW”状态,保持一个周期的片选拉低,然后进入“S_CS_HIGH”状态,拉高片选。 如果命令后面还有地址等数据,进入“S_WRITE_BYTES”写数据状态,或进入“S_READ_BYTES” 读。需要注意,在 spi 数据接口‘data_recv’向数据输出接口‘data_out’传送数据时,是舍弃了 3 个字节的地址位,只传送数据位。而在产生‘data_req’信号时‘byte_cnt’却是到 2,为了满 足数据写入的时序要求,这里提前了一个时钟周期

spi_flash_cmd 状态机

信号名称 方向 说明
sys_clk in 时钟输入
rst in 异步复位输入,高复位
cmd in 命令编码
cmd_valid in 命令有效
cmd_ack out 命令应答
addr in flash 地址
data_in in 命令有写操作时的数据
size in 命令+数据长度(字节)
data_req out 命令有写操作时请求数据,其他 data_in 一个时钟周 期
data_out out 命令有读操作时读出的数据

 

data_valid out 命令有读操作时读有效
CS_reg out 对 spi master 接口,spi 片选控制
wr_req out 对 spi master 接口,spi 写请求
wr_ack in 对 spi master 接口,spi 写应答
send_data out 对 spi master 接口,spi 写数据
data_recv in 对 spi master 接口,spi 读数据

spi_flash_cmd 模块端口

spi_flash_ctrl 模块主要完成 flash 擦除、编程、读操作。擦除前需要写使能有效、等待擦除完

成等多项 flash 命令。状态机如下图所示:

“S_IDLE”:空闲状态

“S_WREN”:写使能命令状态

“S_READ”:读状态

“S_WRITE”:写状态(编程)

“S_SE”:扇区擦除

“S_BE”:块擦除

“S_CK_STATE”:状态寄存器检查,用来检测是否擦除完成等。

“S_ACK”:请求应答

spi_flash_ctrl 状态机

信号名称 方向 说明
sys_clk in 时钟输入
rst in 异步复位输入,高复位
flash_read in flash 读请求
flash_write in flash 写请求
flash_bulk_erase in 块擦除请求
flash_sector_erase in 扇区擦除请求
flash_read_ack out 读应答
flash_write_ack out 写应答
flash_bulk_erase_ack out 块擦除应答
flash_sector_erase_ack out 扇区擦除应答
flash_read_addr in 读请求地址
flash_write_addr in 写请求地址
flash_sector_addr in 扇区擦除地址
flash_write_data_in in 写请求数据
flash_read_size in 读字节大小
flash_write_size in 写字节大小
flash_write_data_req out 写数据拉取,提前 flash_write_data_in 一个时钟
flash_read_data_out out 读数据
flash_read_data_valid out 读数据有效
cmd out 连接 spi_flash_cmd 模块,命令编码
cmd_valid out 连接 spi_flash_cmd 模块,命令有效
cmd_ack in 连接 spi_flash_cmd 模块,命令应答
addr out 连接 spi_flash_cmd 模块,flash 地址
data_in out 连接 spi_flash_cmd 模块,命令有写操作时的数据
size out 连接 spi_flash_cmd 模块,命令+数据长度(字节)
data_req in 连接 spi_flash_cmd 模块,命令有写操作时请求数 据,其他 data_in 一个时钟周期
data_out in 连接 spi_flash_cmd 模块,命令有读操作时读出的数 据
data_valid in 连接 spi_flash_cmd 模块,命令有读操作时读有效

spi_flash_ctrl 端口

在这个模块状态机的‘S_CK_STATE’状态,进行状态转移的条件不仅有命令应答信号还需要判断‘state_reg’寄存器的最低位,需要知道的是‘state_reg’的最低位就是 WIP 位,显示 SPI 是否在写入状态,为 0 时表示该状态不忙。同时,在 spi_flash_ctrl 模块中,我们调用了一个宏定义模块,和 C 语言里的宏定义类似,宏定义模块里面定义了对 flash 操作的各种命令,其用法和格式请参照例程。

4 实验现象

将程序下载到开发板以后,数码管显示一个数字,这个数字是 flash 的第一个字节,通过按下key1 键,数字会加一,同时擦除了 flash,并将新的数据写入,重新上电后,加载下载程序,数码管将显示最后一次按按键的数字。注意:由于 flash 擦写需求一定的时间,按键不能按的太快。

部分代码展示:

`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

点击链接获取代码文件:http://www.hdlcode.com/index.php?m=home&c=View&a=index&aid=1345

  • 2-24111120020cM.docx
    下载

相关推荐