//注意:下降沿写数据
module SD_Read
(
//输入
rst_n,
SD_in, //读SD数据
//内部输入
SD_25M, //SPI时钟25M
//按键内部输入
write_ctl, //按键控制写启动(注意要在初始化完毕后)//低位1代表启动写,高位1代表读
//输出到Top
SD_out, //往SD写
SD_CS, //片选
SD_tasnfer_r, //切换发送线路控制权
SD_R_reg //随便对应
);
//---------------------------------------------------------------------------
//-- 外部端口声明
//---------------------------------------------------------------------------
input SD_25M;
input SD_in; //读
input rst_n;
input write_ctl;//低位1代表启动写,高位1代表读
output reg[7:0] SD_R_reg; //稳定的读到的数据
output reg SD_tasnfer_r;
output reg SD_out;
output reg SD_CS;
//---------------------------------------------------------------------------
//-- 内部端口声明/*synthesis keep*/
//---------------------------------------------------------------------------
reg SD_tasnfer_r_n;
reg SD_in_n;
reg SD_out_n; //写的下位时刻寄存器
reg [7:0] SD_R; //读寄存器(变化过程)
reg [7:0] SD_R_n;
reg [7:0] SD_R_reg_n;
reg SD_CS_n; //写的下位时刻寄存器
reg [3:0] fsm_s;
reg [3:0] fsm_s_n;
reg [9:0] time_cnt; //计时器脉冲数
reg [9:0] time_cnt_n; //下一时刻的计时器脉冲式
reg [5:0] bit_cnt; //记录写或者读到第几个bit了,最多64个,实际48个就行
reg [5:0] bit_cnt_n;
reg [9:0] byte_cnt; //每一个字节的索引,最多512个,
reg [9:0] byte_cnt_n;
//--------------------------------------------------------------------
//--定义参数
//-------------------------------------------------------------------
//**状态机参数
parameter idle=4'b0000; //状态为idle
parameter send_cmd17=4'b0001; //状态为发送CMD17
parameter wait_00=4'b0010; //状态为等待CMD17应答8'h00
parameter wait_fe=4'b0011; //状态为等待接收到0xfe
parameter read_data=4'b0100; //接收数据512bytes数据
parameter read_end=4'b0101; //状态为等待8个时钟后,返回idle态
parameter Erro_end=4'b0110; //状态为写数据失败,等待8个时钟,返回idle态
//**命令8'h00,8'h00,8'h21,8'h00
// parameter CMD17={8'h51,8'h00,8'h00,8'h50,8'h00,8'hff}; //block读命令CMD17的字节序列
parameter CMD17={8'h51,8'h00,8'h00,8'h21,8'h00,8'hff}; //block读命令CMD17的字节序列,地址是8448
// parameter SD_Add_R=32'd8448; //要读取的地址 debug:字节的顺序
//--------------------------------------------------------------------
//--逻辑实现
//-------------------------------------------------------------------
//**************SD_tasnfer_r切换发送线路控制权***************
//时序电路
always @(negedge SD_25M or negedge rst_n)
begin
if(!rst_n)
SD_tasnfer_r<=1'b0;
else
SD_tasnfer_r<=SD_tasnfer_r_n;
end
//组合电路
always @(*)
begin
if(write_ctl) //来一次采集到就保持控制权
SD_tasnfer_r_n=1'b1;
else if(fsm_s==read_end) //读成功后,交还控制权
SD_tasnfer_r_n=1'b0;
else //保持
SD_tasnfer_r_n=SD_tasnfer_r;
end
//**************状态机***************
//时序电路,----------有限状态机状态切换-------------------
always @(negedge SD_25M or negedge rst_n)
begin
if(!rst_n)
fsm_s<=idle; //默认是空闲状态
else
fsm_s<=fsm_s_n;
end
//组合电路 ---有限状态机核心
always@(*) //状态机内部仅仅执行状态的跳转,不进行状态的内部操作
begin
case(fsm_s)
idle: //空闲态,判断是否有写命令
if(write_ctl) //仅仅一个上升沿,1时进入读
fsm_s_n=send_cmd17; //进入下一态
else
fsm_s_n=fsm_s; //保持当前状态
send_cmd17: //状态为发送CMD17
if(bit_cnt==6'd48) //发送完6个字节的控制指令,进入下一态
fsm_s_n=wait_00; //进入下一态
else
fsm_s_n=fsm_s; //保持当前状态
wait_00: //状态为等待CMD17应答8'h00
if(time_cnt>=10'd8&&SD_R==8'h00) //至少发送了1个8位的同步时钟且判断此时是否接收到了0x00
fsm_s_n=wait_fe; //进入下一态
else if(time_cnt>=10'd32) //32个bits的时间还没有收到0x00则响应失败
fsm_s_n=Erro_end; //进入下一态
else
fsm_s_n=fsm_s; //保持当前状态
wait_fe: //状态为等待0xfe //要等很久
if(time_cnt>=10'd8&&SD_in==0) //至少发送了1个8位的同步时钟且判断此时是否接收到了0xfe
fsm_s_n=read_data; //进入下一态
else
fsm_s_n=fsm_s; //保持当前状态
read_data: //状态为接收512字节
if(byte_cnt==10'd512) //等待接收了512个字节
fsm_s_n=read_end; //进入下一态
else
fsm_s_n=fsm_s; //保持当前状态
read_end: //状态为等待8个时钟后,返回idle态
if(time_cnt==8)
fsm_s_n=idle; //进入下一态
else
fsm_s_n=fsm_s; //保持当前状态
Erro_end: //状态为写数据失败,等待8个时钟,返回idle态
if(time_cnt==8)
fsm_s_n=send_cmd17; //重新发送
else
fsm_s_n=fsm_s; //保持当前状态
default:fsm_s_n=idle; //默认在空闲态
endcase
end
//**************SD状态时钟计数器***************
//时序电路
always @(negedge SD_25M or negedge rst_n)
begin
if(!rst_n)
time_cnt<=10'b0;
else
time_cnt<=time_cnt_n;
end
//组合电路
always @(*)
begin
//每次进入新的态后或者加满了,计数器清零
if(fsm_s!=fsm_s_n||fsm_s==10'd1023)
time_cnt_n=10'b0;
else
time_cnt_n=time_cnt+1'b1;
end
//**************片选SD_CS***************
//时序电路
always @(negedge SD_25M or negedge rst_n)
begin
if(!rst_n)
SD_CS<=1'b1; //默认为1,不选中SD卡
else
SD_CS<=SD_CS_n;
end
//组合电路
always @(*)
begin
//只需判断第一个变换点就行,其他保持
//idle态、read_end态(else保持)...时,拉高,不选中
if(fsm_s==idle||fsm_s==read_end)
SD_CS_n=1'b1;
else if(fsm_s==send_cmd17) //发送CMD17态拉低,紧接的几个都保持低
SD_CS_n=1'b0; //拉低,选中
else //否则保持
SD_CS_n=SD_CS;
end
//**************bit_cnt,计数每次收发的bit数***************
//时序电路
always @(negedge SD_25M or negedge rst_n)
begin
if(!rst_n)
bit_cnt<=1'b0;
else
bit_cnt<=bit_cnt_n;
end
//组合电路
always @(*)
begin
//状态改变,或者数据接收态,bit_cnt等于7就清零
if(fsm_s!=fsm_s_n||(fsm_s==read_data&&bit_cnt==6'd7))
bit_cnt_n=1'b0;
else
bit_cnt_n=bit_cnt+1'b1; //记录字节的位数
end
//**************byte_cnt,计数接收了多少字节了***************
//时序电路
always @(negedge SD_25M or negedge rst_n)
begin
if(!rst_n)
byte_cnt<=10'b0;
else
byte_cnt<=byte_cnt_n;
end
//组合电路
always @(*)
begin
//每发送完一个字节,数据加1,直到发送512字节数据态时
if(fsm_s==read_data&&bit_cnt==6'd7&&byte_cnt<10'd512)
byte_cnt_n=byte_cnt+1'b1; //记录每个状态的脉冲数
else if(fsm_s==wait_fe||byte_cnt==10'd512) //在read_data的前一个状态清零
byte_cnt_n=1'b0;
else //保持
byte_cnt_n=byte_cnt;
end
//**************向SD卡发送数据端SD_out***************
//时序电路
always @(negedge SD_25M or negedge rst_n)
begin
if(!rst_n)
SD_out<=1'b1; //默认为1
else
SD_out<=SD_out_n;
end
//组合电路
always @(*)
begin
//连续的态只用判断第一个,其他保持
//除了发送CMD17外,保持高
if(fsm_s==idle||fsm_s==wait_00)
SD_out_n=1'b1;
else if(fsm_s==send_cmd17&&bit_cnt<6'd48) //发送CMD17态
SD_out_n=CMD17[6'd47-bit_cnt]; //先发最高位
else //否则保持
SD_out_n=SD_out;
end
//**************向SD卡接收数据寄存器SD_R***************
//时序电路
always @(posedge SD_25M ) //只有此处是上升沿,接收数据的上升沿
begin
SD_in_n=SD_in;
end
//时序电路
always @(negedge SD_25M or negedge rst_n) //只有此处是上升沿,接收数据的上升沿
begin
if(!rst_n)
SD_R<=8'd0; //默认接收的数据为0
else
SD_R<=SD_R_n;
end
//组合电路
always @(*)
begin
if(fsm_s==wait_00||fsm_s==wait_fe||fsm_s==read_data) //在读数据态时
SD_R_n={SD_R[6:0],SD_in_n};
else //否则保持
SD_R_n=SD_R;
end
//**************向SD卡接收到的*稳定*数据寄存器SD_R_reg***************
//时序电路
always @(negedge SD_25M or negedge rst_n) //只有此处是上升沿,接收数据的上升沿
begin
if(!rst_n)
SD_R_reg<=8'h2A; //默认接收的数据为"*"
else
SD_R_reg<=SD_R_reg_n;
end
//组合电路
always @(*)
begin
if(fsm_s==read_data&&bit_cnt==6'd7) //在读数据态时
SD_R_reg_n={SD_R[6:0],SD_in_n};
else //否则保持
SD_R_reg_n=SD_R_reg;
end
endmodule
简单的SD卡读逻辑的实现
原创
©著作权归作者所有:来自51CTO博客作者加载忠ing的原创作品,请联系作者获取转载授权,否则将追究法律责任
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
Android SD卡简单的文件读写操作
最近有这样的需求,把每次统计到的数据,以txt形式保存到手机SD卡或是手机内存中
java 换行符 System -
android sd卡 数据 sd卡上的android文件
Android系统中SD卡各文件夹功能详解1、.android_secure 是官方app2sd的产物,删了之后装到sd卡中的软件就无法使用了,小心别误删。 2、.Bluetooth 用蓝牙之后就会有这个。 3、.mobo
android sd卡 数据 android 文件管理器 浏览器 输入法