赞
踩
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。