当前位置:   article > 正文

FPGA之sd卡初始化_fpga如何切换到sd卡模式

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    
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/163047
推荐阅读
相关标签
  

闽ICP备14008679号