FLASH控制器设计
AI summary
本文讨论了Flash控制器的设计,分为两部分。第一部分介绍了Flash操作的步骤,包括检测WIP、读取设备ID、擦除和编程等操作,并详细描述了控制器的架构设计和实现。第二部分则探讨了通过选择器控制常用指令的整体设计架构,分析了各个指令的功能实现及其在Flash操作中的应用。最后,文中还进行了设计分析和测试验证,确保Flash操作的顺序和正确性。
Last edited time
Oct 11, 2024 02:48 PM
Last edited by
Tags
Serial Communication
Communication Protocols
Data Transmission Methods
Flash控制器第一部分
在各个命令可以实现的情况下(WREN/RDID/BE/RDSR PP/READ/SE),考虑SPI协议控制各个命令,完成Flash操作:
先考虑如果能正常实现Flash操作(按照M25P16执行规则:先BE/SE/再PP/最后READ),进行控制各个模块的实现。
步骤:(注:在进行新的指令之前,都需要检测WIP)
- 检测WIP,判断Flash是否在工作(Flash忙/不忙),可以忽略…
- 读器件ID
- 判断ID正确性(ID正确再去完成Flash操作,ID不正确就不能对Flash进行操作)
- 检测WIP(完成RDSR指令,检测接收数据最低位(WIP=0/1))
- 等待WIP(判断WIP=1时)
- Flash处于空闲状态(WIP=0)
- 扇区/块擦除(SE/BE),先进行WREN,再进行SE/BE
- 检测WIP(完成RDSR指令,检测接收数据最低位(WIP=0/1))
- 页编程(PP:WIP=0),先进行WREN,再进行PP
- 检测WIP(完成RDSR指令,检测接收数据最低位(WIP=0/1))
- 读数据(READ:WIP=0),直接读数据即可。
- 检测WIP(完成RDSR指令,检测接收数据最低位(WIP=0/1))
一:架构设计
flash_ctrl输入就很多,比如输入可以有读ID指令,PP指令,读数据指令或者擦除指令…
将各种各样的指令经过分析,然后把指令分配给SPI发送器和接收器去执行,由于指令较多,如果发送的指令为读ID指令,那么控制器接收到外部的读ID指令,应该首先将CS_N信号拉低,拉低后把RDID指令给到SPI发送器(
en_tx
),等待SPI发送器发送完RDID指令后,立刻启动SPI接收器(en_rx
),然后等待SPI接收器接收第一个字节数据,然后继续接收第二个字节和第三个字节数据,看Flash_ctrl接收过来的数据是不是ID数据就完事了。- 控制器分析(flash_ctrl):
复位结束后,第一件事考虑 读ID的指令,先判断当前flash正确/不正确,所以读ID指令,就要分成好几个步骤,第一个步骤把RDID指令先发送出去(启动一次发送器),然后接收RDID,分为为RDrx1,RDrx2,RDrx3,等把这三个字节数据接收完成后,然后再去判断当前ID的正确性,如果ID正确,那么使得Flash进入到IDLE状态(空闲),其实才开始正题,看看到底是写/读/擦除,如果是读那就很简单,第一件事就是发送READ的指令,然后发送3个字节地址,最后读取数据即可。读取完数据后也让Flash回到空闲状态IDLE,对于写而言,因为现在不考虑写保护区,如果来写,必须先擦除当前区域,擦除没有页擦除,只有扇区擦除或者块擦除,那么当前区域需不需要擦除,如果要完成擦除,第一步打开写使能,然后第二步擦除,第三步检测WIP,因为你也不知道擦除有没有完成,检测完WIP以后(WIP=0),再次完成写操作,第一步打开写使能,然后第二步再写,第三步检测WIP(WIP=0),写操作完成,最后flash回到空闲状态IDLE。
- 控制器实现(flash_ctrl):
采用FSM实现。
- BE和PP测试
- READ测试
- 下板验证1:处于块擦除进程中(WIP=1),等待擦除和写数据。
- 下板验证2:读取写入数据(0地址:8’h55)
Flash控制器第二部分
通过Flash控制器来控制各个指令能够实现的情况下,使其完成M25P16手册执行规则。
讨论下述的架构:采用选择器来对其常用的指令进行控制。
(WREN/RDID/RDSR/PP/SE/BE/READ)。
- 整体设计架构
pp_en
(启动)和pp_done
(完成):wren_en
和wren_done
(xx_en
和xx_done
)。每个指令模块中都会存在
xx_en
和xx_done
。在上述正题设计架构中,再次分为3个部分进行讨论:
(1):选择器和SPI协议间的
(2):选择器和各个指令间的
(3):控制器和各个指令间的
- 通过多路选择器选择对应的指令
- 各个指令间
wr_len
:写入Flash的数据长度read_len
:读取Flash的数据长度- 设计分析1
- WREN指令实现
- BE指令实现
- SE指令实现
- RDID指令实现
- RDSR指令实现
- PP指令功能实现
- READ指令功能实现
各个指令功能实现(WREN/RDID/RDSR/SE/BE/PP/READ)
当前写使能模块接收到
wren_en
信号后,需要发送对应的使能wren_send_en
和数据wren_send_data[7:0]
,等待发送完成后spi_send_done
,等待需要发送wren_done
信号。由于WREN/BE/SE指令只需要SPI发送器,所以在处理起来动作一致,以SE指令为例进行分析:
当前扇区擦除模块接收到se_en信号后,需要发送对应的使能se_send_en和数据se_send_data[7:0],等待发送完成后spi_send_done,需要再次发送3个字节地址(高字节,中间字节和低字节地址)。全部发送完成后,需要发送se_done信号。
当前读ID模块接收到rdid_en信号后,需要发送对应的使能rdid_send_en和数据rdid_send_data[7:0],等待发送完成后spi_send_done,需要读取3个字节ID,包括高8位ID,中间8位ID和低8位ID(24’h202015/24’hEF4015)。ID全部读完后,需要检测ID的正确性。
当前读状态寄存器模块接收到rdsr_en信号后,需要发送对应的使能rdsr_send_en和数据rdsr_send_data[7:0],等待发送完成后spi_send_done,需要读取一个字节数据。
WIP:正在进行进程中。如果WIP=1,代表在进程中;如果WIP=0,代表进程结束,所以建议在进行新的指令前,需要检测一次WIP。
如果检测时WIP=1,需要等待一段时间(详见手册),然后再次读取WIP位,直到WIP=0为止(在WRSR/PP/SE/BE时)。
当前页编程模块接收到pp_en信号后,需要发送对应的使能pp_send_en和数据pp_send_data[7:0],等待发送完成后spi_send_done,接着继续发送3个字节地址,包括高字节地址,中间字节地址和低字节地址,最后需要发送写入Flash的数据(最多不超过256个)。
当前读数据模块接收到read_en信号后,需要发送对应的使能read_send_en和数据read_send_data[7:0],等待发送完成后spi_send_done,接着继续发送3个字节地址,包括高字节地址,中间字节地址和低字节地址,最后读取Flash的数据(从基地址一直读取数据直到最后一个地址:保证最后一个地址上有数据)。
当前READ模块主要完成对Flash的数据读取(读取的数据写入FIFO中)。
- 设计分析2
多路选择器功能实现(7选1选择器)
WREN/RDID/RDSR/BE/SE/PP/READ都有发送器,RDID/RDSR/READ都有接收器。
Flash控制器(sel:0/1/2/3/4/5/6) | Mux7_1(多路选择器:用于选择哪一个指令) | 说明 |
0:WREN | spi_send_en=wren_send_en;spi_send_data=wren_send_data; | 只有SPI发送器 |
1:RDID | spi_send_en=rdid_send_en;spi_send_data=rdid_send_data;spi_rec_en=rdid_rec_en; | 不仅有SPI发送器,还有SPI接收器 |
2:RDSR | ||
3:BE | ||
4:SE | ||
5:PP | ||
6:READ |
- 设计分析3
主控制器(flash_ctrl)功能:根据外部的命令,按照M25P16的执行规则,进行Flash的工作(进行各个模块的执行)。
对于spi_cs_n在发送指令时需要拉低,在指令结束时需要拉高。
- 设计分析4
测试/下板验证过程中,对其Flash操作顺序进行规定(se_flag/be_flag,pp_flag,read_flag)。
先进行擦除,擦除时可以选择使用SE/BE均可以。等待擦除结束后,然后执行PP,等待PP结束后,最后完成READ。
擦除选择SE(扇区擦除),对仿真库模型中扇区进行擦除(最后一个扇区:24'hFF0000)
扇区地址区间可以自行指定(给其扇区地址基地址即可);对扇区擦除中的某一页进行写入数据(WR_LEN=100,最大不超过256);对写入扇区的数据进行读取(READ_LEN=100,读取数据没有长度要求,取决于写数据的长度),判断读取数据是否为写入数据。
测试PP功能:
整体测试功能:先SE,再PP,最后READ。
下板验证时:需要将主控制器中spi_cs_n在完成某一个指令后需要拉高最少100ns。
可以将READ读取数据存入FIFO后,读取FIFO的数据,看数据是不是写入的数据(最后一个数据正确即可)。
Loading...