前言
FLASH具有掉电存储数据的功能,通常用来存储启动代码和数据文件。本模块使用verilog设计了基于N25Q系列的QSPI FLASH控制器,将QSPI接口以及镁光flash控制指令进行包装并开放用户自己定义接口,方便对flash器件进行读写擦操作。
目录
一、控制器接口介绍
模块参数列表
| 信号名 | 说明 | 默认值 |
| SYS_CLK | 系统时钟,默认大于等于4倍的SPI_CLK_M | 200 |
| QSPI_CLK | SPI实际传输时钟,最大50Mhz | 25 |
| ADDR_LENGTH | flash地址位宽,128Mflash地址位宽24,256Mflash地址位宽32 | 32 |
端口列表
| 信号名 | 说明 | 方向 |
| O_qspi_cs | Flash片选信号,低有效 | output |
| IO_qspi_io0 | QSPI FLASH, DATA0 | Inout |
| IO_qspi_io1 | QSPI FLASH, DATA1 | Inout |
| IO_qspi_io2 | QSPI FLASH, DATA2 | Inout |
| IO_qspi_io3 | QSPI FLASH, DATA3 | Inout |
| clk | 系统时钟输入,默认200Mhz | Input |
| rst_n | 异步复位信号 | Input |
| flash_init_done | flash初始化完成信号 | output |
| start_erase | 擦除启动信号 | Input |
| start_erase_code | 擦除码: 20h:扇区擦除,按起始地址往后擦除4KB大小的空间4096个字节; d8h:块擦除,16个Sector(扇区)是1个Block(块)64KBytes,按起始地址往后擦除64KB大小的空间65536个字节; c7h:全擦除,容量为16M=128Mbit,共有256个Block,4096个Sector;; | Input |
| start_erase_addr | 擦除起始位置地址 | Input |
| start_erase_length | 从起始地址开始,擦除深度,需要为4096 或 65536的倍数 根据 code来 | Input |
| erase_finish | 擦除完成信号,一个系统时钟脉冲周期 | output |
| start_write_in | 用户开始写启动信号,一个系统时钟脉冲周期 | input |
| start_write_addr | 用户开始写地址,字节为单位 | input |
| start_write_length | 用户开始写长度,字节为单位,必须为256的倍数 | input |
| write_data[7:0] | 用户写数据,位宽为8位 | input |
| write_data_request | 用户写数据有效请求,需要在下个时钟周期将write_data准备好 | output |
| write_finish | 用户写完成信号,一个系统时钟脉冲周期 | output |
| start_read_out | 用户开始读启动信号,一个系统时钟脉冲周期 | input |
| start_read_addr | 用户开始读地址,字节为单位 | input |
| start_read_length | 用户开始读长度,字节为单位,必须为256的倍数 | input |
| read_data | 用户读数据,位宽为8位 | output |
| read_data_valid | 用户读数据有效请求,当拍输出read_data | output |
| read_finish | 用户读完成信号,一个系统时钟脉冲周期 | output |
二、控制器读写擦时序
擦除操作时序图如下:

写操作时序图如下:
写使能信号和数据同步在sys_clk时钟下,写使能信号占1个sys_clk时钟周期,数据周期等于SYS_CLK/QSPI_CLK个sys_clk时钟周期,写使能相对于写数据提前一个sys_clk时钟周期。

读操作时序图如下:

三、N25QSPI flash控制器状态机设计
设计分两层,顶层为指令层,底层为指令执行层(flash驱动层)。
3.1顶层模块设计
顶层模块靠一个主状态机控制,如下图所示,复位放开后先读取flash设备ID号,复位写使能,启动写使能,根据地址位宽配置选择要不要进入四字节地址模式,最后将R_status_reg值02h写入状态寄存器,关闭flash所有扇区的硬件保护。最后进入初始化完成状态等待读写擦启动脉冲信号。
写状态寄存器的值用户可以自由设置,在初始化阶段会将用户配置值打入flash状态寄存器。本模块没有指定硬件保护,所以固定写入02h。

3.2擦除操作状态机设计
擦除状态机设计图如下所示,用户发送启动擦除脉冲(start_erase)后,控制器打开写使能,并根据用户指定的擦除码(start_erase_code)进行判断,对用户设定的擦除深度(start_erase_length)经行切分,如果擦除码20h,那么擦除深度需要为4096的整数倍,如果擦除码为d8h,那么擦除深度需要为65536的整数倍。

3.3写操作状态机设计
写状态机设计图如下所示,用户发送启动写脉冲(start_write_in)后,控制器打开写使能,先进入擦除状态擦掉原有数据,等待擦除完成后根据地址位宽配置选择要不要进入四字节地址模式,开始发送256字节数据,数据发送完成后读取状态寄存器最低位查看写操作是否执行完成。然后进入下一个写256字节流程直至所有字节发送结束。

3.4读操作状态机设计
读状态机设计图如下所示,用户发送启动读脉冲(start_read_out)后,控制器复位写使能,开始一次读取256字节数据,直至用户设置的所有字节读取结束。

3.5驱动层状态机设计
驱动层状态机设计图如下所示,指令层给每种类型的指令设置一个指令类型R_cmd_type_reg,驱动层根据指令类型的低四位判断该条指令发送完8bit指令码后是否需要接着发送地址位以及是否紧接着读取数据。指令码类型如下:
最高位为指令码有效位,默认为1,但本模块并没有对最高位进行判断。
R_cmd_type_reg[3:0]:
B0001,b0100:该类型指令仅发送一个字节指令码;
B0010:该类型指令发送一个字节指令码后发送地址;
B0110:该类型指令发送一个字节指令码后发送一个字节寄存器值;
B1001:该类型指令发送一个字节指令码后发送发送地址,在等待几个时钟后读取用户指定字节的数据;
......
用户可以自定义指令类型并在底层状态机中设置该指令需要的操作。

四、应用demo设计
Demo工程架构图如下图所示。FPGA板上电后,进入复位状态,用户通过复位按键发送复位脉冲,flash进入初始化流程,等待上位机发送控制指令,串口模块根据指令协议解析出控制信号发送给flash控制模块对板载flash芯片进行读写擦操作。试数据为640x512个字节数据提前固化在rom中,写操作时从rom中取数据。

FPGA上电后,按下复位按钮,状态机跳入FLASH_INITIAL_DONE状态,此时flash初始化工作完成,可以通过串口上位机发送flash控制指令。串口上位机如下图所示。

4.1读flash操作
发送指令将读地址设置为200000h,收到反回指令后发送指令将读深度设置为50000h,收到反回指令后将lia抓取flash_read_data_valid==1,并发送指令启动读操作,ila抓取flash读出的数据如下图所示。

4.2写flash操作
发送指令将写地址设置为200000h,收到反回指令后发送指令将写深度设置为50000h,收到反回指令后发送指令启动flash写操作。
发送指令将读地址设置为200000h,收到反回指令后发送指令将读深度设置为50000h,收到反回指令后将lia抓取flash_read_data_valid==1,并发送指令启动读操作,ila抓取flash读出的数据如下图所示。

4.3擦除flash操作
发送指令将擦除地址设置为200000h,收到反回指令后发送指令将擦除深度设置为50000h,收到反回指令后发送指令将擦除码设置为子扇区擦除码,收到反回指令后发送指令启动flash擦除操作。
发送指令将读地址设置为200000h,收到反回指令后发送指令a将读深度设置为50000h,收到反回指令后将lia抓取flash_read_data_valid==1,并发送指令启动读操作,ila抓取flash读出的数据如下图所示。

再次读取200000h地址段,此时读出的数值全部为FF,擦除操作成功。
此外,可以将擦除码设置为C7h,进行整个flash芯片全擦除操作。
1527

被折叠的 条评论
为什么被折叠?



