SD卡读写——Verilog实现SD卡读写
本文主要介绍如何设计Verilog程序实现SD卡读写。现在的很多FPGA开发板中都预留了sd卡槽,常见的卡槽包括标准的SD卡以及TF卡两种,某些情况下,我们可能需要利用FPGA实现sd卡存储数据,针对这种需求,整理本篇博客内容供大家参考,共同学习。
SD卡相关知识介绍
目前常见的SD卡有两种形式,一种是标准的SD卡,另外一种是tf卡,无论标准的SD卡或者TF卡,其基本协议是相同的,因此对于程序设计来说,这两种类型的SD卡的读写方式是相同的。
SD卡引脚接口介绍
针对两种不同类型的SD卡,其引脚接口信号定义如下图所示:
标准SD卡:
TF卡:
对于上述的两种类型的SD卡,都支持两种操作模式,分别是SD模式和SPI模式,通过这两种模式都可以实现对SD卡的读写,本文主要介绍现在常用的SPI模式。而SD卡的引脚接口在不同的模式下分别表示不同的功能,具体方式如下表所示:
因此,对于SPI模式,除电源和地信号外,我们只需要四个数据线分别是CLK、CS、MISO和MOSI,对应SD的接口分别是CLK、CS/DAT3、DAT0和CMD。
SD卡命令协议
我们在实际应用中,常用的一些重要的SD命令及其响应数据格式如下:
SD卡初始化流程
- 首先延时74个CLK(SPI时钟频率是25Mhz),等到SD卡内部操作完成;
- 片选CS低电平选中SD卡;
- 然后发送CMD0({8’h40, 8’h00, 8’h00, 8’h00, 8’h00, 8’h95} )命令,需要得到返回值0X01,进入Idle状态;
- 然后进入卡类型检验,为了检验卡的类型,首先发送只有V2.0版的SD卡才具有的命令CMD8({8’h48, 8’h00, 8’h00, 8’h01, 8’haa, 8’h87} ),然后检测返回值;
返回值若是0X01,则表示此卡为V2.0卡,然后再发送循环命令CMD55({8’h77, 8’h00, 8’h00, 8’h00, 8’h00, 8’hff})+ACMD41({8’h69, 8’h40, 8’h00, 8’h00, 8’h00, 8’hff}),直到返回0x00,确定SD2.0卡初始化成功;然后再发送CMD58命令,接收返回的OCR 寄存器的数据,其中第31位用于判断V2.0的卡是否为SDHC类型(初始化成功后,也可以不验证是否为SDHC类型)。
若返回值不为0X01,则进一步判断是V1.0卡还是MMC卡;先发送循环命令CMD55+ACMD41,如果返回0x00,则为V1.0卡并且初始化成功;
否则考虑是MMC卡,再使用CMD1进行初始化,如果无返回错误,则表明是MMC卡并且初始化成功;否则表示是无法识别的卡。
从上面的初始化过程可以看出主要涉及到几个特殊的命令:CMD8、CMD55、ACMD41和CMD58。对于CMD55和ACMD41的讲解,有很多文章都有,不多解释,此复位命令的返回值和CMD1的返回值相同,成功复位时返回0X00;对于CMD58,其命令码格式是标准格式,其中数据填充0即可,CRC也可省略,只要最后加上停止位‘1’即可,不作详解;其返回值为R3类型,首先接收到一个字节应该为0X00,表示SD卡响应命令成功,然后接收4字节的OCR寄存器值;OCR寄存器的第30位(CCS)指示了卡的类型是否为SDHC,此位为1则为SDHC,为0则为SDSC;
SD卡的读操作:
其中,CMD17 指令的具体内容是 {8’h51,read_sec_i[31:24],read_sec_i[23:16],read_sec_i[15:8],read_sec_i[7:0],8’hff};sec_i是一个32bit的数据,表示的是读SD卡的扇区的地址。
SD卡的写操作:
其中,CMD24 指令的具体内容是 {8’h58,sec_i[31:24],sec_i[23:16],sec_i[15:8],sec_i[7:0],8’hff};sec_i是一个32bit的数据,表示的是写SD卡的扇区的地址。