基于FPGA的SD NAND读写测试(图文并茂+源代码+详细注释)

2025-02-19 16:41:05 雷龙发展

  什么是SD NAND?

  1.SD NAND 卡介绍

  SD NAND 卡是一种基于 NAND 闪存技术的存储设备,其外观和接口类似于标准的 SD 卡。它将 NAND 闪存芯片和必要的控制电路集成在一个小型的封装内,以 SD 卡的形式提供数据存储功能。

  2.SD NAND 卡与其他SD卡的对比

SD NAND卡与SD卡的对比

  与原始的 NAND(闪存)相比,该产品有许多优势,它有具有以下功能

  嵌入式坏块管理功能:这意味着它可以自己检测和标记坏块,在数据存储和读取过程中自动避开这些坏块。例如,当写入数据时,产品会先检查目标块是否为坏块,如果是,就会选择其他正常的块来存储数据,从而提高了数据存储的可靠性和效率。

  更强的嵌入式纠错码(ECC)功能:ECC 是一种用于检测和纠正数据传输或存储过程中错误的技术。在 NAND 闪存中,数据可能会因为各种因素(如电气干扰、闪存单元老化等)而出现错误。原始的 NAND 闪存可能只有基本的 ECC 功能或者需要依赖外部的 ECC 机制。该产品具有更强的嵌入式 ECC 功能,能够更有效地检测和纠正更多的数据错误。例如,它可以纠正多位数据错误,确保从闪存中读取的数据的准确性,降低数据出错导致系统故障或数据丢失的风险。

  即使是异常断电,它仍然能保持你的数据安全。

  3.SD NAND卡的物理结构如下:

  SD 卡主要由以下几个部分组成,存储单元作为存储数据的核心部件,通过存储单元接口与卡控制单元实现数据传输。电源检测单元能够确保 SD 卡工作在适宜的电压范围内,一旦出现掉电或上电的情况,它会促使控制单元和存储单元接口进行复位操作。卡及接口控制单元负责掌控 SD 卡的运行状态,其中包含6个寄存器。接口驱动器则对 SD 卡引脚的输入输出进行控制。

SD NAND的物理结构

  4.引脚分配图如下:

SD NAND引脚分配图
SD NAND物理结构图

  SD NAND卡的读写控制主要有两种模式: SD模式和SPI模式

  在SD模式下:SD 卡共使用到 SCLK、CMD、SDD[3:0]六根 信号线;SDIO 总线与多张 SD 卡连接时,可以共用 SCLK 时钟信号线,对于 CMD、SDD[3:0]信号线,每张 SD 卡都要独立连接.

  在 SPI 模式下,SD 卡共使用到 CS、SCLK、DI(MISO)、DO(MOSI)四 根信号线;SPI 总线与多张 SD 卡连接时,除 CS 片选信号线不可共用外,其他信号均可共用。

SD NAND分别两种模式:SD模式和SPI模式

  5.SD卡的寄存器

SD卡的寄存器

  对于SD卡寄存器的详细介绍,读者可参考以下文章                                     《Part1_Physical_Layer_Simplified_Specification_Ver7.10》  

  6.SD NAND卡的读写控制时序

  以下所有内容皆是基于SPI模式下,读者注意区分!

  6.1.命令与响应时序

  SD NAND卡传输过程中有SCLK和DATA。下图的DATAIN指的是DI,DATAOUT指的是DO。当主机发送指令时,SD NAND卡接收到命令后,产生响应给主机。

SD NAND卡传输过程中有SCLK和DATA

  主机发送的命令可以让SD NAND卡中的数据读出,并且通过CRC校验数据的正确性(注意CRC是由SD NAND卡硬件设备生成的),此时只对某一块(block)读数据。

主机发送的命令可以让SD NAND卡中的数据读出

  主机发送的命令除了可以让数据读出,还可以让数据写入,而且每次的读/写都是按块进行的,即每次读写一般为512 字节。

主机发送的命令可以让SD NAND卡中的数据写入

  6.2.SD NAND卡的读写命令

  发送的命令格式为:48bit,通过CMD命令线发送。

    SD NAND卡的读写命令

  每一个命令都有一个起始位("0")和停止位("1")

  传输标志:用于区分传输方向,主机传输到 SD 卡时为1;SD 卡传输到主机时为0;

  命令号:它固定占用 6bit,总共有2^6=64条命令

  地址/参数:这 32bit 用于指定目标 SD 卡的地址

  CRC7 校验:长度为 7bit 的校验位用于验证命令传输内容正确性

  6.3.SPI模式下常用的命令信息

SD NAND,贴片式TF卡,贴片式SD卡,北京君正,nor flash,存储,芯片,主控,小尺寸emmc,大容量SLC Nand

SD NAND,贴片式TF卡,贴片式SD卡,北京君正,nor flash,存储,芯片,主控,小尺寸emmc,大容量SLC Nand

  6.4.响应命令类型

  可参阅《Part1_Physical_Layer_Simplified_Specification_Ver6.00》一文。

  实验目标

  PC 机使用串口助手通过串口 RS232 协议向 SD  NAND卡(基于SPI模式)指定扇区写入 512 字节数据,随后读出写入数据回传到 PC 机,验证数据正确性。 

  硬件资源 

  SD NAND卡的型号为深圳市雷龙发展有限公司的CSNP64GCR01-BOW,容量为64Gb

创世SD NAND 64Gbit型号
CSNP64GCR01-BOW
深圳市雷龙发展有限公司

  将SD NAND 芯片焊接至测试板,测试板可直接 插入TF卡座或读卡器进行测试及调试,预留 的第二组焊盘可用于飞线。

SD NAND测试板
创世SD卡测试板

  读写测试时直接将芯片焊接到测试板后,将测试板插到TF卡座部分,即可读写测试。

SD NAND测试板插到TF卡座即可读写测试

将SD卡芯片焊接到SD NAND测试板后,将测试板插到TF卡座即可读写测试

  模块设计

  这里主要介绍一下SD NAND卡的读写控制模块:

  首先上电后,需要对SD NAND 卡进行初始化,初始化模块输出一个初始化完成信号,用于指示SD NAND卡的读和写模块的进行。

SD NAND卡的读写控制模块

  代码实现

module  data_rw_ctrl

(

    input   wire            sys_clk     ,   //输入工作时钟,频率50MHz

    input   wire            sys_rst_n   ,   //输入复位信号,低电平有效

    input   wire            init_end    ,   //SD卡初始化完成信号

    

    input   wire            rx_flag     ,   //写fifo写入数据标志信号

    input   wire    [7:0]   rx_data     ,   //写fifo写入数据

    input   wire            wr_req      ,   //sd卡数据写请求

    input   wire            wr_busy     ,   //sd卡写数据忙信号

 

    output  wire            wr_en       ,   //sd卡数据写使能信号

    output  wire    [31:0]  wr_addr     ,   //sd卡写数据扇区地址

    output  wire    [15:0]  wr_data     ,   //sd卡写数据

 

    input   wire            rd_data_en  ,   //sd卡读出数据标志信号

    input   wire    [15:0]  rd_data     ,   //sd卡读出数据

    input   wire            rd_busy     ,   //sd卡读数据忙信号

    output  reg             rd_en       ,   //sd卡数据读使能信号

    output  wire    [31:0]  rd_addr     ,   //sd卡读数据扇区地址

    output  reg             tx_flag     ,   //读fifo读出数据标志信号

    output  wire    [7:0]   tx_data         //读fifo读出数据

);

 

//parameter define

parameter   DATA_NUM    =   12'd256     ;   //读写数据个数

parameter   SECTOR_ADDR =   32'd1000    ;   //读写数据扇区地址

parameter   CNT_WAIT_MAX=   16'd60000   ;   //读fifo输出数据时间间隔计数最大值

//wire  define

wire    [11:0]  wr_fifo_data_num    ;   //写fifo内数据个数

wire            wr_busy_fall        ;   //sd卡写数据忙信号下降沿

wire            rd_busy_fall        ;   //sd卡读数据忙信号下降沿

//wire            rd_fifo_rd_en       ;   //读fifo读使能信号

//reg   define

reg             wr_busy_dly         ;   //sd卡写数据忙信号打一拍

reg             rd_busy_dly         ;   //sd卡读数据忙信号打一拍

reg             send_data_en        ;   //串口发送数据使能信号

reg     [15:0]  cnt_wait            ;   //读fifo输出数据时间间隔计数

reg     [11:0]  send_data_num       ;   //串口发送数据字节数计数

reg             rd_fifo_rd_en       ;

//wr_en:sd卡数据写使能信号

assign  wr_en = ((wr_fifo_data_num == (DATA_NUM)) && (init_end == 1'b1))

                ? 1'b1 : 1'b0;

 

//wr_addr:sd卡写数据扇区地址

assign  wr_addr = SECTOR_ADDR;

 

//wr_busy_dly:sd卡写数据忙信号打一拍

always@(posedge sys_clk or negedge sys_rst_n)

    if(sys_rst_n == 1'b0)

        wr_busy_dly <=  1'b0;

    else

        wr_busy_dly <=  wr_busy;

 

//wr_busy_fall:sd卡写数据忙信号下降沿

assign  wr_busy_fall = ((wr_busy == 1'b0) && (wr_busy_dly == 1'b1))

                        ? 1'b1 : 1'b0;

 

//rd_en:sd卡数据读使能信号

always@(posedge sys_clk or negedge sys_rst_n)

    if(sys_rst_n == 1'b0)

        rd_en   <=  1'b0;

    else    if(wr_busy_fall == 1'b1)

        rd_en   <=  1'b1;

    else

        rd_en   <=  1'b0;

//rd_addr:sd卡读数据扇区地址

assign  rd_addr = SECTOR_ADDR;

//rd_busy_dly:sd卡读数据忙信号打一拍

always@(posedge sys_clk or negedge sys_rst_n)

    if(sys_rst_n == 1'b0)

        rd_busy_dly <=  1'b0;

    else

        rd_busy_dly <=  rd_busy;

//rd_busy_fall:sd卡读数据忙信号下降沿

assign  rd_busy_fall = ((rd_busy == 1'b0) && (rd_busy_dly == 1'b1))

                        ? 1'b1 : 1'b0;

//send_data_en:串口发送数据使能信号

always@(posedge sys_clk or negedge sys_rst_n)

    if(sys_rst_n == 1'b0)

        send_data_en    <=  1'b0;

    else    if((send_data_num == (DATA_NUM * 2) - 1'b1)

                && (cnt_wait == CNT_WAIT_MAX - 1'b1))

        send_data_en    <=  1'b0;

    else    if(rd_busy_fall == 1'b1)

        send_data_en    <=  1'b1;

    else

        send_data_en    <=  send_data_en;

 

//cnt_wait:读fifo输出数据时间间隔计数

always@(posedge sys_clk or negedge sys_rst_n)

    if(sys_rst_n == 1'b0)

        cnt_wait    <=  16'd0;

    else    if(send_data_en == 1'b1)

        if(cnt_wait == CNT_WAIT_MAX)

            cnt_wait    <=  16'd0;

        else

            cnt_wait    <=  cnt_wait + 1'b1;

    else

        cnt_wait    <=  16'd0;

 

//send_data_num:串口发送数据字节数计数

always@(posedge sys_clk or negedge sys_rst_n)

    if(sys_rst_n == 1'b0)

        send_data_num   <=  12'd0;

    else    if(send_data_en == 1'b1)

        if(cnt_wait == CNT_WAIT_MAX)

            send_data_num   <=  send_data_num + 1'b1;

        else

            send_data_num   <=  send_data_num;

    else

        send_data_num   <=  12'd0;

//rd_fifo_rd_en:读fifo读使能信号

//assign  rd_fifo_rd_en = (cnt_wait == CNT_WAIT_MAX) ? 1'b1 : 1'b0;

always@(posedge sys_clk or negedge sys_rst_n)

    if(sys_rst_n == 1'b0)

        rd_fifo_rd_en   <=  1'b0;

    else    if(cnt_wait == (CNT_WAIT_MAX - 1'b1))

        rd_fifo_rd_en   <=  1'b1;

    else

        rd_fifo_rd_en   <=  1'b0;

 

//tx_flag:读fifo读出数据标志信号

always@(posedge sys_clk or negedge sys_rst_n)

    if(sys_rst_n == 1'b0)

        tx_flag <=  1'b0;

    else

        tx_flag <=  rd_fifo_rd_en;

 

 

fifo_wr_data   fifo_wr_data_inst

(

    .wrclk      (sys_clk            ),  //数据写时钟

    .wrreq      (rx_flag            ),  //数据写使能

    .data       (rx_data            ),  //写入数据

 

    .rdclk      (sys_clk            ),  //数据读时钟

    .rdreq      (wr_req             ),  //数据读使能

    .q          (wr_data            ),  //读出数据

    .rdusedw    (wr_fifo_data_num   )   //fifo内剩余数据个数

);

 

fifo_rd_data    fifo_rd_data_inst

(

    .wrclk      (sys_clk        ),  //数据写时钟

    .wrreq      (rd_data_en     ),  //数据写使能

    .data       (rd_data        ),  //写入数据

 

    .rdclk      (sys_clk        ),  //数据读时钟

    .rdreq      (rd_fifo_rd_en  ),  //数据读使能

    .q          (tx_data        )   //读出数据

);

 

endmodule


  代码部分篇幅过长,详细源代码可参考本人主页资源部分自行学习

  实验结果

  PC机通过串口调试助手往SD NAND卡写入数据后,FPGA再将SD NAND卡中的数据读出通过UART发送模块发送给PC机后,可以发现写入和读出的数据位数都是512byte,而且输入数据和读出数据完全正确。

FPGA再将SD NAND卡中的数据实验结果

亲爱的卡友们,欢迎光临雷龙官网,如果看完文章之后还是有疑惑或不懂的地方,请联系我们,自己去理解或猜答案是件很累的事,请把最麻烦的事情交给我们来处理,术业有专攻,闻道有先后,雷龙发展专注存储行业13年,专业提供小容量闪存解决方案。

SD NAND,贴片式TF卡,贴片式SD卡,nor flash,存储,芯片,深圳市雷龙发展联系方式

服务电话&邮箱

Tel:13691982107(优先)17727831243

QQ:1302648372 | line@longsto.com

对外联系邮箱:info@longsto.com

投诉:ceo@longsto.com |13923450403

地址:深圳市龙华区民治街道展滔科技大厦B座1907室

首页
产品
资讯
联系