FPGA之sd卡初始化

module sd_init(
       Clk,
         Rst_n,
         
         sd_miso,
         sd_mosi,
         sd_cs_n,
         sd_clk,
         init_done
         );
         input Clk;
         input Rst_n;
          
         input sd_miso;
         output reg sd_mosi;
         output reg sd_cs_n;
         output  sd_clk;
         output reg init_done;
         
         reg [7:0]div_cnt;
         reg Clk_ref;
         
         
         reg [47:0]res_data;   
         reg res_flag;   
         reg [5:0]res_bit_cnt;
         reg res_en;//SD卡回应使能
         reg [47:0]cmd_bit_cnt;
         reg FF;
         reg [47:0]cmd;
         reg [9:0]delay_cnt;
         reg delay_done;
         reg [19:0]over_time_cnt;
         reg over_time;
         reg [3:0]wait_cnt;
         reg [6:0]state;
         
       parameter div=8'd200;
        //命令
        parameter cmd0  = {8'h40,8'h00,8'h00,8'h00,8'h00,8'h95},
                  cmd8  = {8'h48,8'h00,8'h00,8'h01,8'haa,8'h87},
                     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};
        //状态
        parameter idle       =7'b0000_001,
                  cmd0_send  =7'b0000_010,
                     clk_wait   =7'b1000_000,
                  cmd8_send  =7'b0000_100,
                     cmd55_send =7'b0001_000,
                     acmd41_send=7'b0010_000,
                     done       =7'b0100_000;
                     
        //时钟
        assign sd_clk=~Clk_ref;
      always@(posedge Clk or negedge Rst_n)
       if(!Rst_n)begin
         div_cnt<=8'd0;
          Clk_ref<=1'b0;
        end
        else if(div_cnt==div/2-1'b1)begin
          div_cnt<=8'd0;
          Clk_ref<=~Clk_ref;
        end
        else begin
          div_cnt<=div_cnt+1'b1;
          Clk_ref<=Clk_ref;
        end
        //上电延迟
        always@(posedge sd_clk or negedge Rst_n)
       if(!Rst_n)begin
          delay_cnt <=10'd0;
          delay_done<=1'b0;
        end
        else if(delay_cnt==10'd500)begin
          delay_cnt <=10'd500;
          delay_done<=1'b1;
        end
        else begin
          delay_cnt<=delay_cnt+1'b1;
          delay_done<=delay_done;
        end
        //SD卡回应超时计数
        always@(posedge sd_clk or negedge Rst_n)
       if(!Rst_n)
          over_time_cnt<=20'd0;
        else if(res_en)
          over_time_cnt<=over_time_cnt+1'b1;
        else
          over_time_cnt<=20'd0;
          
        always@(posedge sd_clk or negedge Rst_n)
       if(!Rst_n)
          over_time<=1'b0;
        else if(over_time_cnt>20'd50000)
          over_time<=1'b1;
        else if(over_time_cnt==20'd0)
          over_time<=1'b0;
        else
          over_time<=over_time;
        
        
        
       //读取数据
       always@(posedge sd_clk or negedge Rst_n)
       if(!Rst_n)begin
         res_data   <=48'd0;
          res_flag   <=1'b0;
          res_bit_cnt<=6'd0;
        end
        else if(!sd_miso&&!res_flag&&res_en)begin
          res_flag<=1'b1;
          res_data<={res_data[46:0],sd_miso};
        end
        else if(res_flag)begin
          res_data<={res_data[46:0],sd_miso};
          res_bit_cnt<=res_bit_cnt+1'b1;
          if(res_bit_cnt==6'd46)
            res_flag<=1'b0;
        end
        else
          res_bit_cnt<=6'd0;
        //写命令
      always@(posedge Clk_ref or negedge Rst_n)
       if(!Rst_n)begin
        state      <=idle;
          cmd_bit_cnt<=48'd0;
          FF         <=1'b1;
          res_en     <=1'b0;
          sd_cs_n    <=1'b1;
          sd_mosi    <=1'b1;
          wait_cnt   <=4'd0;
          init_done  <=1'b0;
      end
      else if(!over_time)
          case(state)
            idle     :begin
                        if(delay_done)begin
                             cmd  <=cmd0;
                                state<=cmd0_send;                                
                           end
                           else
                             state<=idle;
                                
                          end
             cmd0_send:begin
                      if(FF)
                          cmd_send;
                        else    if(res_bit_cnt==6'd47)begin
                               FF    <=1'b1;
                                res_en<=1'b0;
                           if(res_data[47:40]==8'h01)begin
                              state  <=clk_wait;
                                    cmd    <=cmd8;
                                    sd_cs_n<=1'b1;
                                    
                                end
                            else
                             state<=idle;
                           end
                       end
             clk_wait :begin
                         if(wait_cnt==4'd10)begin
                               wait_cnt<=4'd0;
                                state  <=cmd8_send;
                               
                             end
                             else
                               wait_cnt<=wait_cnt+1'b1;
                          end
             cmd8_send:begin
                      if(FF)
                          cmd_send;
                        else    if(res_bit_cnt==6'd47)begin
                               FF    <=1'b1;
                                res_en<=1'b0;
                           if(res_data[19:16]==4'h1)begin
                              state  <=cmd55_send;
                                    cmd    <=cmd55;
                                    sd_cs_n<=1'b1;
                                    
                                end
                            else
                             state<=idle;
                           end
                       end
            cmd55_send:begin
                      if(FF)
                          cmd_send;
                        else    if(res_bit_cnt==6'd47)begin
                               FF    <=1'b1;
                                res_en<=1'b0;
                           if(res_data[47:40]==8'h01)begin
                              state  <=acmd41_send;
                                    cmd    <=acmd41;
                                    sd_cs_n<=1'b1;
                                    
                                end
                            else
                             state<=idle;
                           end
                       end
          acmd41_send:begin
                      if(FF)
                          cmd_send;
                        else    if(res_bit_cnt==6'd47)begin
                               FF    <=1'b1;
                                res_en<=1'b0;                                
                           if(res_data[47:40]==8'h00)begin
                              state  <=done;
                                    sd_cs_n<=1'b1;
                                    init_done<=1'b1;
                                end
                            else begin
                             state<=cmd55_send;
                                  cmd  <=cmd55;
                                end
                                  
                           end
                        end
                  done:begin
                            if(wait_cnt==4'd10)begin
                                wait_cnt <=4'd0;
                                 init_done<=1'b1;
                              end
                              else if(!init_done)
                                wait_cnt<=wait_cnt+1'b1;
                      end
          default     :begin
                         state      <=idle;
                         cmd_bit_cnt<=48'd0;
                         FF         <=1'b1;
                         res_en     <=1'b0;
                         sd_cs_n    <=1'b1;
                         sd_mosi    <=1'b1;
                         wait_cnt   <=4'd0;
                         init_done  <=1'b0;
                            end
       endcase                  
       else begin
        state      <=idle;
          cmd_bit_cnt<=48'd0;
          FF         <=1'b1;
          res_en     <=1'b0;
          sd_cs_n    <=1'b1;
          sd_mosi    <=1'b1;
          wait_cnt   <=4'd0;
          init_done  <=1'b0;
      end
                                            
                    
                      
                  
task cmd_send;
begin
  if(cmd_bit_cnt==6'd48)begin
    cmd_bit_cnt<=6'd0;
     FF         <=1'b0;
     sd_mosi    <=1'b1;
     res_en     <=1'b1;
  end 
  else begin
    sd_cs_n    <=1'b0;
    cmd_bit_cnt<=cmd_bit_cnt+1'b1;
     sd_mosi    <=cmd[6'd47-cmd_bit_cnt];
  end
end                    
            
endtask        
            
            
            
        
          
        
endmodule    
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SDIO2.0 的初始化流程可以分为以下几步: 1. 确定时钟频率:SDIO2.0 的时钟频率可以达到 208 MHz,需要根据具体的应用场景确定时钟频率。 2. 发送 CMD0 命令:CMD0 是 SD 的软件复位命令,它用于将 SD 复位到初始状态。FPGA初始化时需要向 SD 发送 CMD0 命令,以确保 SD 处于正确的状态。 3. 发送 CMD8 命令:CMD8 用于向 SD 查询它是否支持高容量存储和供电电压范围等信息。如果 SD 支持高容量存储和所选的电压范围,则会回复一个 R7 响应。FPGA 需要解析 R7 响应,以确定 SD 的特性和电压范围。 4. 发送 ACMD41 命令:ACMD41 用于向 SD 发送初始化命令,该命令会触发 SD 初始化流程。FPGA 需要向 SD 发送 ACMD41 命令,并等待 SD 的响应。如果 SD 成功初始化,则会回复一个 R3 响应。 5. 设置数据总线宽度:FPGA 需要根据 SD 的特性和所选的数据总线宽度,设置数据总线宽度为 1 位或 4 位。 6. 设置时钟频率:FPGA 需要根据 SD 的特性和所选的时钟频率,设置时钟频率。 7. 发送 CMD2 命令:CMD2 用于向 SD 查询它的 CID,即 SD 的厂商信息和序列号等信息。FPGA 需要向 SD 发送 CMD2 命令,并解析 SD 的响应。 8. 发送 CMD3 命令:CMD3 用于向 SD 查询它的 RCA,即 SD 的相对地址。FPGA 需要向 SD 发送 CMD3 命令,并解析 SD 的响应。 以上是 SDIO2.0 的初始化流程的大致步骤,具体实现需要参考 SDIO2.0 协议和 FPGA 开发板的硬件和软件特性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值