SD-Host 数据控制模块
SD-Host 数据控制模块
- SD_DATA_FSM
- 状态转换图
- 信号描述
- verilog实现
- sd_data_send_shift_register
- 信号描述
- verilog 实现
- sd_data_receive_shift_register
- 信号描述
- verilog实现
SD_DATA_FSM
数据发送/接收控制模块,根据输入的控制信号,进行状态机的跳转判定,以控制sd_data_send_shift_register和sd_data_receive_shift_register模块进行符合SD协议的数据处理过程。
状态转换图
PS:右边SEND_END_BIT状态后应该加入一个CRC_STATUS_WAIT (等对方发Start bit,然后再接收crc 状态)
STATE_STOP :停止状态,in_data_ready高有效时(写:sd_fifo_full, 读:命令发送完),状态机进入STATE_IDLE状态;
STATE_IDLE: 读写判断状态,in_data_direction高有效时,表示host准备开始发送数据,进入STATE_END_WAIT状态,反之,则表示host准备开始接收数据,进入RECEIVE_WAIT状态
STATE_WAIT_RECEIVE : 读操作准备状态,首先判断已接收的数据块是否满足要求,若满足,则跳入STATE_STOP,状态机停止工作,并给出状态信号read_to_error.最后,检测数据线data[0]是否低有效,有效则跳入STATE_RECEIVE状态,否则保持;
STATE_RECEIVE :数据读操作处理过程,并需要判断每块byte数据是否读完(has_receive_bit == need_to_receive_bit-1),满足则跳入STATE_RECEIVE_CRC状态,否则保持;
STATE_RECEIVE_CRC :判断每块crc数据是否读完(receive_crc_counter ==15,数据的时候对应CRC16,命令CRC7),满足则跳入STATE_RECEIVE_END_BIT状态,否则保持;
STATE_RECEIVE_END_BIT :首先判断已接收的数据块是否满足要求,若满足,则跳入STATE_STOP,状态机停止工作。不满足,则跳入STATE_WAIT_RECEIVE状态;
PS:STATE_RECEIVE 和 STATE_RECEIVE_END_BIT状态都进行已读取数据块的判断,但其作用不同:(下面DATA_STATE_WAIT_SEND和STATE_SEND_BUSY类似)STATE_RECEIVE 状态的判断,是允许提前结束读操作的。此状态内,软件修改参数need_to_receive_block(大小为has_receive_blcok+1),使得硬件状态机结束;STATE_RECEIVE_END_BIT状态的判断是正常情况下的操作,即软件配置操作值need_to_receive_block之后,host硬件必须从device读取相等大小数据块;
DATA_STATE_WAIT_SEND :数据输出等待状态,在条件fifo已被写满情况下,判断所有数据块是否发送完成,满足则跳入STATE_STOP状态,状态机停止工作。否则进行data[0]数据判断,高有效,跳入DATA_STATE_SNED_Z状态,否则保持;
DATA_STATE_SNED_Z:不做任何数据处理,进入DATA_STATE_SNED_P状态;
DATA_STATE_SNED_P:总线方向改变方向;
DATA_STATE_SNED_BIT:开始数据发送状态,跳入STATE_SEND状态;
DATA_SEND:数据发送状态,单块数据所有bit发送完成后(has_send_bit==need_to_send_bit-1),进入STATE_SEND_CRC状态,否则保持;
STATE_SEND_CRC:CRC数据发送状态,完成后,跳入STATE_SEND_END_BIT;
STATE_SEND_END_BIT:结束位发送状态,并用于数据线的方向切换(状态中间点),进入STATE_RECEIVE_CRC_STATUS状态;
STATE_SEND_BUSY:数据块传输结束判断状态,所有block发送结束,跳入STATE_STOP状态,停止操作。否则,进入DATA_STATE_WAIT_SEND状态,等待下一次块数据传输的开始。
信号描述
signals | I/O | Width | from | to | declaration |
---|---|---|---|---|---|
in_sd_clk | input | 1 | sd_clk | ||
hrst_n | input | 1 | AHB bus | 异步复位 | |
in_soft_reset | input | 1 | 软件复位 | ||
in_data_ready | input | 1 | sd_if | 状态机启动信号 | |
in_sd_data | input | [3:0] | sd_card | 数据读入端口 | |
in_data_direction | input | 1 | sd_if | host读写控制信号:1/write 0/read | |
need_to_receive_byte | input | [10:0] | sd_if | 控制器每块接收的数据量 | |
need_to_send_byte | input | [10:0] | sd_if | 控制器每块发送的数据量 | |
need_to_receive_block | input | [31:0] | sd_if | 控制器 | |
need_to_send_block | input | [31:0] | sd_if | 控制器需发送的块数据大小 | |
in_data_width | input | 1 | sd_if | host使用数据线判定信号:1/4 data line | |
in_read_to | input | [31:0] | sd_if | host读操作time out时间,超出则状态机返回STOP状态 | |
current_state | output | [3:0] | sd_if sd_data_send sd_data_receive | 当前状态标志位 | |
next_state | output | [3:0] | sd_data_send | 次状态标志位 | |
has_send_bit_counter_en | output | 1 | 发送bit数计数器使能 | ||
send_crc_counter | output | [3:0] | sd_data_send | 已发送crc数据的bit大小,作为sd_data_send_shift_register模块的CRC输出控制信号 | |
has_send_bit | output | [13:0] | sd_data_send | Host已发送的数据bit大小 | |
receive_crc_status_counter | output | [1:0] | 计数接收crc status的周期(时序) | ||
has_receive_bit | output | [13:0] | sd_data_receive | Host已接收的数据bit大小 | |
out_transfer_complete | output | 1 | sd_if | 数据传输结束状态标志位 | |
interval_counter | output | [1:0] | sd_data_send | 单块block写结束位时钟计数器,用于数据端口方向位的控制 | |
out_read_to_error | output | 1 | sd_if | 读操作timeout标志位,ISR位 | |
one_bk_re_end | output | 1 | sd_if | 一个block数据读操作结束状态位,用于硬件停时钟 |
verilog实现
module (in_sd_clk, //clock for sd cardhrst_n, //ahb reset signalin_soft_reset, //software resetin_data_ready, //data fsm ready signalsd_fifo_full,in_sd_data, //data input from sd cardin_data_direction, //data direction 1:write 0:readneed_to_receive_byte, //block lengthneed_to_receive_block, //block numberneed_to_send_byte, //block lengthneed_to_send_block, //block numberin_data_width, //data width 1:4bit 0:1bitin_read_to, //time of read data fsmcurrent_state, //current state of data fsmnext_state, //next state of data fsmhas_send_bit_counter_en,//has send bit counter enablesend_crc_counter, //has sent crc bits counterhas_send_bit, //has send data bits counterreceive_crc_status_counter, //has receive crc status bits counterhas_receive_bit, //has receive data bits counterout_transfer_complete, //indicate data transfer has completed interval_counter, //time interval between data end bit and crc statusout_read_to_error, //read timeout error flagone_bk_re_end
);
input in_sd_clk; //clock for sd card
input hrst_n; //ahb reset signal
input in_soft_reset; //software reset
input in_data_ready;
input sd_fifo_full;
input [3:0] in_sd_data; //data input from sd card
input in_data_direction; //data direction 1:write 0:read
input [10:0] need_to_receive_byte; //block length
input [10:0] need_to_receive_block; //block number
input [31:0] need_to_send_byte; //block length
input [31:0] need_to_send_block; //block number
input in_data_width; //data width 1:4bit 0:1bit
input [31:0] in_read_to; //time of read data fsmoutput [3:0] current_state; //current state of data fsm
output [3:0] next_state; //next state of data fsm
output has_send_bit_counter_en;//has send bit counter enable
output [3:0] send_crc_counter; //has sent crc bits counter
output [13:0] has_send_bit; //has send data bits counter
output [1:0] receive_crc_status_counter; //has receive crc status bits counter
output [13:0] has_receive_bit; //has receive data bits counter
output out_transfer_complete; //indicate data transfer has completed
output [1:0] interval_counter; //time interval between data end bit and crc status
output out_read_to_error; //read timeout error flag
output one_bk_re_end;out_transfer_complete;
reg [3:0] eurrent_state;
reg [3:0] next_state;
reg has_receive_bit_counter_en;
reg has_send_bit_counter_en;
reg has_receive_block_counter_en;
reg has_send_block_counter_en;
reg receive_crc_counter_en;
reg read_resp_time_counter_en;
reg send_crc_counter_en;
reg interval_counter_en;
reg receive_crc_status_counter_en;
reg [13:0] has_receive_bit;
reg [13:0] has_send_bit;
reg [31:0] has_receive_block;
reg [31:0] has_send_block;
reg [3:0] receive_crc_counter;
reg [31:0] read_resp_time_counter;
reg [31:0] send_crc_counter;
reg [1:0] interval_counter;
reg [1:0] receive_crc_status_counter;
reg out_read_to_error;wire one_bk_re_end_tp;
reg one_bk_re_end;wire [13:0] need_to_send_bit;
wire [13:0] need_to_receive_bit;
wire [13:0] need_to_send_bit_4;
wire [13:0] need_to_receive_bit_4;//--------------------------------------------------------
// Beginning of main code
//--------------------------------------------------------
//将要接收/发送的字节数转化为bit数,用于计数比较
assign need_to_send_bit = {need_to_send_byte,3'b0};
assign need_to_receive_bit = {need_to_receive_byte,3'b0};
assign need_to_send_bit_4 = {2'b0,need_to_send_byte,1'b0};
assign need_to_receive_bit_4 = {2'b0,need_to_receive_byte,1'b0};//----------------------------------------------------------------------
// Data fsm
//----------------------------------------------------------------------
// State description:
//
// DATA_STATE_STOP is the reset state of data fsm
// DATA_STATE_IDLE determines the data direction
// DATA_STATE_WAIT_RECEIVE waits for the start bit of data from sd card
// DATA_STATE_RECEIVE receives payload data from sd card
// DATA_STATE_RECEIVE_CRC receives crc of data from sd card
// DATA_STATE_RECEIVE_END_BIT receives the end bit of data from sd card and
// determines if all blocks have sent
// DATA_STATE_WAIT_SEND waits to send data to sd card until sd is not busy
// DATA_STATE_SEND sends payload data to sd card
// DATA_STATE_SEND_CRC send crc of data to sd card
// DATA_STATE_SEND_END_BIT send the end bit of the data to sd card
// DATA_STATE_RECEIVE_CRC_STATUS receives the crc status of data sent from sd
// card
// DATA_STATE_SEND_BUSY determines if all blcks have been sent
// DATA_STATE_START_BIT sends the start bit of data to sd card
// DATA_STATE_SEND_Z sends a Z bit to sd card
// DATA_STATE_SEND_P sends a P bit to sd card//fsm1
always @ (posedge in_sd_clk or negedge hrst_n) beginif(!hrst_n)current_state <= `CMD_STATE_STOP;else if(!in_soft_reset)current_state <= `CMD_STATE_STOP;else current_state <= next_state;
end//fsm2
always @(*) beginout_read_to_error = 1'b0;case (current_state)`DATA_STATE_STOP: //0beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;if(in_data_ready)next_state = `DATA_STATE_IDLE;elsenext_state = `DATA_STATE_STOP;end`DATA_STATE_IDLE: //1//IDLE状态判断读/写sd,进入读写等待状态beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;if(!in_data_direction)next_state = `DATA_STATE_WAIT_RECEIVE;elsenext_state = `DATA_STATE_WAIT_SEND;end`DATA_STATE_WAIT_RECEIVE: //2//数据等待接收状态:所有blcok收完STOP;读超时STOP;//接收到数据的开始位data[0]==0,进入数据接收模式beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;if (has_receive_block == need_to_receive_block)beginnext_state = `DATA_STATE_STOP;out_transfer_complete = 1'b1;endelse if (read_resp_time_counter == in_read_to)beginnext_state = `DATA_STATE_STOP;out_read_to_error = 1'b1;endelse beginif(!in_sd_data[0])next_state = `DATA_STATE_RECEIVE;else beginnext_state = `DATA_STATE_WAIT_RECEIVE;read_resp_time_counter_en = 1'b1;endendend`DATA_STATE_RECEIVE: //3//数据接收状态,启用接收bit计数器,需要接收的bit全接收了//进入接收crc的状态,begin//has_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;if(!in_data_width) beginif (has_receive_bit == need_to_receive_bit - 1)beginnext_state = `DATA_STATE_RECEIVE_CRC;has_receive_bit_counter_en = 1'b0;endelse beginnext_state = `DATA_STATE_RECEIVE;has_receive_bit_counter_en = 1'b1;endendelse beginif (has_receive_bit_4 == (need_to_receive_bit_4 - 1))beginnext_state = `DATA_STATE_RECEIVE_CRC;has_receive_bit_counter_en = 1'b0;endelse beginnext_state = `DATA_STATE_RECEIVE;has_receive_bit_counter_en = 1'b1;endendend`DATA_STATE_RECEIVE_CRC: //4//接收crc状态,启用接收crc计数器,接收完成进入,接收end_bit状态beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;//receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;if(receive_crc_counter == 15) beginnext_state =`DATA_STATE_RECEIVE_END_BIT;receive_crc_counter_en = 1'b0;endelse beginnext_state = `DATA_STATE_REVEIVE_CRC;receive_crc_counter_en = 1'b1;endend`DATA_STATE_RECEIVE_END_BIT: //5//接收end_bit,全部block接收完则回到STOP//否则blcok计数器启用,调到等待接收,启用被释放,相当于block计数只加了1beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;//has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;if(has_receive_block == (need_to_receive_block - 1)) beginnext_state = `DATA_STATE_STOP;has_receive_block_counter_en = 1'b0;out_transfer_complete = 1'b1;endelse beginnext_state = `DATA_STATE_WAIT_RECEIVE;has_receive_block_counter_en = 1'b1;endend`DATA_STATE_WAIT_SEND: //6beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;if(sd_fifo_full) beginif(has_send_block == need_to_send_block)beginnext_state = `DATA_STATE_STOP;out_transfer_complete = 1'b1;endelse begin// if (!in_sd_data[0])if (in_sd_data[0])next_state = `DATA_STATE_WAIT_SEND;elsenext_state = `DATA_STAET_SEND_Z;endendelsenext_state = `DATA_STATE_WAIT_SEND;end`DATA_STATE_SEND: //7//启用发送bit计数,发送完数据准备发crc,beginhas_receive_bit_counter_en = 1'b0;//has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;if (!in_data_width)beginif (has_send_bit == (need_send_bit - 1))beginnext_state = `DAYA_STATE_SEND_CRC;has_send_bit_counter_en = 1'b0;endelse beginnext_state = `DATA_STATE_SEND;has_send_bit_counter_en = 1'b1;endendelse beginif (has_send_bit == (need_to_seed_bit_4 - 1))beginnext_state = `DAYA_STATE_SEND_CRC;has_send_bit_counter_en = 1'b0;endelse beginnext_state = `DATA_STATE_SEND;has_send_bit_counter_en = 1'b1;endendend`DATA_STATE_SEND_CRC: //8//启用发送crc bit计数,发送完crc准备发end bitbeginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; //send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;if (send_crc_counter == 15)beginnext_state = `DATA_STATE_SEND_END_BIT;send_crc_counter_en = 1'b0;endelse beginnext_state = `DATA_STATE_SEND_CRC;send_crc_counter_en = 1'b1;endend`DATA_STATE_SEND_END_BIT: //9//发送完endbit ,准备接收数据是否正确的信号,//这里应该增加一个状态更好,而不是用计数的方式beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;//这里4个周期接收EZZSif (interval_counter == 3)beginnext_state = `DATA_STATE_RECEIVE_CRC_STATUS;interval_counter_en = 1'b0;endelse beginnext_state = `DATA_STATE_SNED_END_BIT;interval_counter_en = 1'b1;endend`DATA_STATE_RECEIVE_CRC_STATUS ://10beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;//这里4个周期接收status(3bit)+Eif (receive_crc_status_counter == 3)beginnext_state = `DATA_STATE_SEND_BUSY;receive_crc_status_counter_en = 1'b0;endelse beginnext_state = `DATA_STATE_RECEIVE_CRC_STATUS;receive_crc_status_counter_en = 1'b1;endend`DATA_STATE_SEND_BUSY: //11//数据块传输结束判断状态,所有block发送结束,//跳入STATE_STOP状态,停止操作。//否则,进入DATA_STATE_WAIT_SEND状态,等待下一次块数据传输的开始。beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;//has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;if (has_send_block == (need_to_send_block - 1))beginnext_state = `DATA_STATE_STOP;has_send_block_counter_en = 1'b0;out_transfer_complete = 1'b1;endelse beginnext_state = `DATA_STATE_WAIT_SEND;has_send_block_counter_en = 1'b1;endend`DATA_STATE_SEND_START_BIT: //12beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;next_state = `DATA_STATE_SEND;end`DATA_STATE_SEND_Z:beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;next_state = `DATA_STATE_SEND_P;end`DATA_STATE_SEND_P:beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;next_state = `DATA_STATE_SEND_START_BIT;enddefault:beginhas_receive_bit_counter_en = 1'b0;has_send_bit_counter_en = 1'b0;has_receive_block_counter_en = 1'b0;has_send_block_counter_en = 1'b0;receive_crc_counter_en = 1'b0;read_resp_time_counter_en = 1'b0; send_crc_counter_en = 1'b0;interval_counter_en = 1'b0;receive_crc_status_counter_en = 1'b0;out_transfer_complete = 1'b0;next_state = `DATA_STATE_STOP;endendcase
endassign one_bk_re_end_tp = (current_state == `DATA_STATE_RECEIVE_END_BIT);always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)one_bk_re_end <= 1'b0;else one_bk_re_end <= one_bk_re_end_tp;//---------------------------------------------------------------------
// Has received data bits from sd card counter
//---------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)has_receive_bit <= 14'b0;else if (!in_soft_reset)has_receive_bit <= 14'b0;else if (current_state == `DATA_STATE_RECEIVE_CRC)has_receive_bit <= 14'b0;else if (has_receive_bit == (need_to_send_block - 1))has_receive_bit <= 14'b0;else if (has_receive_bit_counter_en)has_receive_bit <= has_receive_bit + 1;
end//---------------------------------------------------------------------
// Read data from sd card response time counter
//---------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)read_resp_time_counter <= 32'b0;else if (!in_soft_reset)read_resp_time_counter <= 32'b0;else if (current_state == `DATA_STATE_STOP)read_resp_time_counter <= 32'b0;else if (read_resp_time_counter == in_read_to)read_resp_time_counter <= 32'b0;else if (read_resp_time_counter_en)read_resp_time_counter <= read_resp_time_counter + 1;
end //---------------------------------------------------------------------
// Has sent data bits counter
//---------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)has_send_bit <= 14'b0;else if (!in_soft_reset)has_send_bit <= 14'b0;else if (current_state == `DATA_STATE_SEND_CRC)has_send_bit <= 14'b0;else if (has_send_bit_counter_en)has_send_bit <= has_send_bit + 1;
end//---------------------------------------------------------------------
// Has received crc number counter
//---------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)receive_crc_counter <= 14'b0;else if (!in_soft_reset)receive_crc_counter <= 14'b0;else if (receive_crc_counter == 15)receive_crc_counter <= 14'b0;else if (receive_crc_counter_en)receive_crc_counter <= receive_crc_counter + 1;
end//---------------------------------------------------------------------
// Has received block number counter
//---------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)has_receive_block <= 32'b0;else if (!in_soft_reset)has_receive_block <= 32'b0;else if (current_state == `DATA_STATE_STOP)has_receive_block <= 32'b0;else if (has_receive_block_counter_en)has_receive_block <= has_receive_block + 1;
end//---------------------------------------------------------------------
// Has sent block number counter
//---------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)has_send_block <= 32'b0;else if (!in_soft_reset)has_send_block <= 32'b0;else if (current_state == `DATA_STATE_STOP)has_send_block <= 32'b0;else if (has_send_block_counter_en)has_send_block <= has_send_block + 1;
end//---------------------------------------------------------------------
// Time interval between the end bit of sent data and crc status counter
//---------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)interval_counter <= 2'b0;else if (!in_soft_reset)interval_counter <= 2'b0;else if (interval_counter == 3)interval_counter <= 2'b0;else if (interval_counter_en)interval_counter <= interval_counter + 1;
end//---------------------------------------------------------------------
// Has receive crc status bits counter
//---------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)receive_crc_status_counter <= 2'b0;else if (!in_soft_reset)receive_crc_status_counter <= 2'b0;else if (receive_crc_status_counter == 3)receive_crc_status_counter <= 14'b0;else if (receive_crc_status_counter_en)receive_crc_status_counter <= receive_crc_status_counter + 1;
end//---------------------------------------------------------------------
// Has sent crc bits counter
//---------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)send_crc_counter <= 14'b0;else if (!in_soft_reset)send_crc_counter <= 14'b0;else if (send_crc_counter == 15)send_crc_counter <= 14'b0;else if (send_crc_counter_en)send_crc_counter <= send_crc_counter + 1;
endendmodule
sd_data_send_shift_register
data数据的发送模块,根据sd_data_fsm模块状态机的状态,读取内部fifo数据和CRC数据,拆分成bit数据,送入data line。并根据接收的状态数据,判定一块数据发送是否正确
功能描述:
1、数据线方向控制,根据状态信息,判定数据IO线是输入还是输出;
下图所示的是在低速时钟下,host数据发送和方向控制时序。在下降沿对输出的方向控制寄存器,得到下降沿输出数据。根据信号in_high_speed_clk (host是否工作在高速时钟情况),判定是下降沿输出还是上升沿输出。
2、数据的输出:
a. fifo数据的swap,fifo数据是地址顺序存储的(the first byte is the least significant byte ),但host数据的输出就是FIFO数据左移数来的最高位,不符合sd协议,输出前需要4个byte的swap调整;
b. 读入FIFO数据和模块生成的CRC数据左移输出。
3、CRC数据的生成;
4、数据输出错误判定;
信号描述
signals | I/O | Width | from | to | declaration |
---|---|---|---|---|---|
in_sd_clk | input | 1 | sd_clk | 时钟信号 | |
hrst_n | input | 1 | 异步复位 | ||
in_soft_reset | input | 1 | 软件复位 | ||
in_sd_data | input | [3:0] | 数据读入端口(接收crc) | ||
sd_fifo_rdata | input | [31:0] | fifo数据读出数据端口 | ||
in_current_state | input | [3:0] | sd_data_fsm | 数据当前状态标志位 | |
in_next_state | input | [3:0] | sd_data_fsm | 数据次状态标志位 | |
in_data_width | input | 1 | sd_if | host使用数据线判定信号:1/4 data line | |
in_send_crc_counter | input | [3:0] | sd_data_fsm | host已发送crc数据的bit大小 | |
in_has_send_bit | input | [13:0] | sd_data_fsm | Host已发送的数据bit大小 | |
in_interval_counter | input | [1:0] | sd_data_fsm | 单块block写结束位时钟计数器,用于数据端口方向位的控制 | |
in_high_speed_clk | input | 1 | sd_if | 数据输出方式,1:高速 0:低速 | |
out_serial_data | output | [3:0] | sd_card | 向sd card 输入数据 | |
sd_fifo_re | output | 1 | fifo | fifo读请求信号 | |
out_crc_status_wrong | output | 1 | sd_if | 数据发送crc检验错误 | |
out_data_dir | output | [3:0] | 数据方向控制端口 1 发送到sd card | ||
out_data_half_delay | output | [3:0] | 数据输出端口(高速:上升沿 低速:下降沿) | ||
in_TestMode | output | 1 | 测试模式 |
verilog 实现
module sd_data_send_shift_register (in_sd_clk,hrst_n,in_soft_reset,in_sd_data,sd_fifo_rdata,in_current_state,in_next_state,in_data_width,in_send_crc_counter,in_has_send_bit,in_interval_counter,in_high_speed_clk,out_serial_data,sd_fifo_re,out_crc_status_wrong,out_data_dir,out_data_half_delay
);input in_sd_clk; //clock for sd card
input hrst_n; //ahb signal
input in_soft_reset; //software reset
input [3:0] in_sd_data; //data input drom sd card
input [31:0] sd_fifo_rdata; //parallel data from tx fifo
input [3:0] in_current_state; //current state of data fsm
input [3:0] in_next_state; //next state of data fsm
input in_data_width; //data width 1:4bit 0:1bit
input [3:0] in_send_crc_counter; //has sent crc bits
input [13:0] in_has_send_bit; //has sent data bits
input [1:0] in_interval_counter; //time interval
input in_high_speed_clk; output [3:0] out_serial_data; //original serial output data
output sd_fifo_re; //tx fifo read enable
output out_crc_status_wrong; //crc status wrong flag
output [3:0] out_data_dir; //data direction 1:send
output [3:0] out_data_half_delay; //serial output data to sd cardreg [3:0] out_serial_data;
reg [31:0] shift_reg0;
reg [15:0] crc_reg0;
reg [15:0] crc_reg1;
reg [15:0] crc_reg2;
reg [15:0] crc_reg3;
reg [15:0] crc_shift_reg0;
reg [15:0] crc_shift_reg1;
reg [15:0] crc_shift_reg2;
reg [15:0] crc_shift_reg3;
reg [0:31] data_for_send;
reg [3:0] crc_status_reg;
reg sd_fifo_re;
reg out_crc_status_wrong;
reg [3:0] out_data_half_delay_tp;
reg [3:0] data_dir_nes;wire [31:0] sd_fifo_rdata_tp;
wire [3:0] data_dir_pos;//-------------------------------------------------------------------
// Beginning of main code
//---------------------------------------------------------------------
// Overview of the data send shift register operation
// The following key signals are used in the command send shift register
// out_data_dir is the data direction
// out_data_half_delay is the output data to sd card
// crc_reg3 is the denerated data crc register
// crc_reg2 is the denerated data crc register
// crc_reg1 is the denerated data crc register
// crc_reg0 is the denerated data crc register
// sd_fifo_rdata is the parallel data from tx fifo
// sd_fifo_re is the tx fifo read enable signal
// crc_status_reg is the crc status from sd card after sending data//-----------------------------------------------------------------------
// Output data to sd card
//---------------------------------------------------------------------
//the data was sent at negedge
always @(negedge in_sd_clk or negedge hrst_n) beginif (!hrst_n) beginout_data_half_delay_tp <= 4'b1111;endelse beginout_data_half_delay_tp <= out_serial_data;//用clk下降沿打拍,延迟半个周期end
end
//数据输出端口(高速:上升沿 低速:下降沿) ??讲者说考虑timing 切换相位可以满足时序
assign out_data_half_delay = in_high_speed_clk ? out_serial_data : out_data_half_delay_tp;
//-----------------------------------------------------------------------------
// Data direction 0:receive 1:send
//------------------------------------------------------------------------------
//输出使能,向sd方向
assign data_dir_pos[0] = ( (in_current_state == `DATA_STATE_SEND_P) ||(in_current_state == `DATA_STATE_SEND_START_BIT) ||(in_current_state == `DATA_STATE_SEND) ||(in_current_state == `DATA_STATE_SEND_CRC) ||((in_current_state == `DATA_STATE_SEND_END_BIT) &&((in_interval_counter == 0) || (in_interval_counter == 1))));assign data_dir_pos[1] = in_data_width && ((in_current_state == `DATA_STATE_SEND_P) ||(in_current_state == `DATA_STATE_SEND_START_BIT) ||(in_current_state == `DATA_STATE_SEND) ||(in_current_state == `DATA_STATE_SEND_CRC) ||((in_current_state == `DATA_STATE_SEND_END_BIT) &&((in_interval_counter == 0) || (in_interval_counter == 1))));assign data_dir_pos[2] = in_data_width && ((in_current_state == `DATA_STATE_SEND_P) ||(in_current_state == `DATA_STATE_SEND_START_BIT) ||(in_current_state == `DATA_STATE_SEND) ||(in_current_state == `DATA_STATE_SEND_CRC) ||((in_current_state == `DATA_STATE_SEND_END_BIT) &&((in_interval_counter == 0) || (in_interval_counter == 1))));assign data_dir_pos[3] = in_data_width && ((in_current_state == `DATA_STATE_SEND_P) ||(in_current_state == `DATA_STATE_SEND_START_BIT) ||(in_current_state == `DATA_STATE_SEND) ||(in_current_state == `DATA_STATE_SEND_CRC) ||((in_current_state == `DATA_STATE_SEND_END_BIT) &&((in_interval_counter == 0) || (in_interval_counter == 1))));
// assign data_dir_pos[1] = in_data_width && data_dir_pos[0];
// assign data_dir_pos[2] = data_dir_pos[1];
// assign data_dir_pos[3] = data_dir_pos[1];always @(negedge in_sd_clk or negedge hrst_n) beginif (!hrst_n) begindata_dir_nes <= 4'b0endelse begindata_dir_nes <= {data_dir_pos[3],data_dir_pos[2],data_dir_pos[1],data_dir_pos[0]};end
end
// out_data_dir 端口方向的控制??
assign out_data_dir = in_high_speed_clk ? data_dir_pos :data_dir_nes;//---------------------------------------------------------------------------------
// Generate output data to sd card 1ibt and 4bit mode and receive crc status bits
// -------------------------------------------------------------------------------
always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n) beginshift_reg0 <= 32'b0;out_serial_data <= 4'b1111;crc_status_reg <= 4'b0;crc_shift_reg0 <= 16'b0;crc_shift_reg1 <= 16'b0;crc_shift_reg2 <= 16'b0;crc_shift_reg3 <= 16'b0;endelse if (!in_soft_reset) beginshift_reg0 <= 32'b0;out_serial_data <= 4'b1111;crc_status_reg <= 4'b0;crc_shift_reg0 <= 16'b0;crc_shift_reg1 <= 16'b0;crc_shift_reg2 <= 16'b0;crc_shift_reg3 <= 16'b0;endelse beginif(!in_data_width)beginif (in_current_state == `DATA_STATE_SEND_START_BIT)//send start bitout_serial_data[0] <= 1'b0;else if (in_current_state == `DATA_STATE_SEND)begin//每32个bit,重新赋一个值(从fifo中读出得到)if (in_has_send_bit[4:0] == 5'b0){out_serial_data[0],shift_reg0} <= {sd_fifo_rdata_tp,1'b0};else {out_serial_data[0],shift_reg0} <= {shift_reg0,1'b0};//向左移位输出,并行转串行endelse if (in_current_state == `DATA_STATE_SEND_CRC)beginif (in_send_crc_counter == 0){out_serial_data[0],crc_shift_reg0} <= {crc_reg0,1'b0};else {out_serial_data[0],crc_shift_reg0} <= {crc_shift_reg0,1'b0};endelse if (in_current_state == `DATA_STATE_SEND_END_BIT)beginout_serial_data[0] <= 1'b1;end//DATA_STATE_RECEIVE_CRC_STATUS 这里sd 数据线的方向变化,变为接收crc_statuselse if (in_current_state == `DATA_STATE_RECEIVE_CRC_STATUS)begincrc_status_reg <= {crc_status_reg[2:0], in_sd_data[0]};endelse if (in_current_state == `DATA_STATE_WAIT_SEND)begincrc_status_reg <= 4'b0;endendelsebeginif (in_current_state == `DATA_STATE_SEND_START_BIT)out_serial_data <= 4'b0;else if (in_current_state == `DATA_STATE_SEND)beginif (in_has_send_bit[2:0] == 3'b0){out_serial_data,shift_reg0} <= {sd_fifo_rdata_tp,4'b0};else{out_serial_data,shift_reg0} <= {shift_reg0,4'b0};endelse if (in_current_state == `DATA_STATE_SEND_CRC)beginif(in_send_crc_counter == 0)begin{out_serial_data[3],crc_shift_reg3} <= {crc_reg3,1'b0};{out_serial_data[2],crc_shift_reg2} <= {crc_reg2,1'b0};{out_serial_data[1],crc_shift_reg1} <= {crc_reg1,1'b0};{out_serial_data[0],crc_shift_reg0} <= {crc_reg0,1'b0};endelsebegin{out_serial_data[3],crc_shift_reg3} <= {crc_shift_reg3,1'b0};{out_serial_data[2],crc_shift_reg2} <= {crc_shift_reg2,1'b0};{out_serial_data[1],crc_shift_reg1} <= {crc_shift_reg1,1'b0};{out_serial_data[0],crc_shift_reg0} <= {crc_shift_reg0,1'b0};endendelse if (in_current_state == `DATA_STATE_RECEIVE_CRC_STATUS)begincrc_status_reg <= {crc_status_reg[2:0],in_sd_data[0]};endelse if (in_current_state ==`DATA_STATE_WAIT_SEND)crc_status_reg <= 4'b0endendend//----------------------------------------------------
// Generate output data crc
//----------------------------------------------------always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n) begincrc_reg3 <= 16'b0;crc_reg2 <= 16'b0;crc_reg1 <= 16'b0;crc_reg0 <= 16'b0;endelse if (!in_soft_reset) begincrc_reg3 <= 16'b0;crc_reg2 <= 16'b0;crc_reg1 <= 16'b0;crc_reg0 <= 16'b0;endelse if (in_current_state == `DATA_STATE_WAIT_SEND)begincrc_reg3 <= 16'b0;crc_reg2 <= 16'b0;crc_reg1 <= 16'b0;crc_reg0 <= 16'b0;endelse if (in_current_state == `DATA_STATE_SEND)beginif (!in_data_width)begincrc_reg0[0] <= data_for_send[in_has_send_bit[4:0]] ^ crc_reg0[15];crc_reg0[1] <= crc_reg0[0];crc_reg0[2] <= crc_reg0[1];crc_reg0[3] <= crc_reg0[2];crc_reg0[4] <= crc_reg0[3];crc_reg0[5] <= crc_reg0[4] ^ data_for_send[in_has_send_bit[4:0]] ^ crc_reg0[15];crc_reg0[6] <= crc_reg0[5];crc_reg0[7] <= crc_reg0[6];crc_reg0[8] <= crc_reg0[7];crc_reg0[9] <= crc_reg0[8];crc_reg0[10] <= crc_reg0[9];crc_reg0[11] <= crc_reg0[10];crc_reg0[12] <= crc_reg0[11] ^ data_for_send[in_has_send_bit[4:0] ^ crc_reg0[15]];crc_reg0[13] <= crc_reg0[12];crc_reg0[14] <= crc_reg0[13];crc_reg0[15] <= crc_reg0[14];endelsebegincrc_reg3[0] <= data_for_send[{in_has_send_bit[2:0],2'b0}] ^ crc_reg3[15];crc_reg3[1] <= crc_reg3[0];crc_reg3[2] <= crc_reg3[1];crc_reg3[3] <= crc_reg3[2];crc_reg3[4] <= crc_reg3[3];crc_reg3[5] <= crc_reg3[4] ^ data_for_send[{in_has_send_bit[2:0],2'b0}] ^ crc_reg3[15];crc_reg3[6] <= crc_reg3[5];crc_reg3[7] <= crc_reg3[6];crc_reg3[8] <= crc_reg3[7];crc_reg3[9] <= crc_reg3[8];crc_reg3[10] <= crc_reg3[9];crc_reg3[11] <= crc_reg3[10];crc_reg3[12] <= crc_reg3[11] ^ data_for_send[{in_has_send_bit[2:0],2'b0}] ^ crc_reg3[15];crc_reg3[13] <= crc_reg3[12];crc_reg3[14] <= crc_reg3[13];crc_reg3[15] <= crc_reg3[14];crc_reg2[0] <= data_for_send[{in_has_send_bit[2:0],2'b0}+1] ^ crc_reg2[15];crc_reg2[1] <= crc_reg2[0];crc_reg2[2] <= crc_reg2[1];crc_reg2[3] <= crc_reg2[2];crc_reg2[4] <= crc_reg2[3];crc_reg2[5] <= crc_reg2[4] ^ data_for_send[{in_has_send_bit[2:0],2'b0}+1] ^ crc_reg2[15];crc_reg2[6] <= crc_reg2[5];crc_reg2[7] <= crc_reg2[6];crc_reg2[8] <= crc_reg2[7];crc_reg2[9] <= crc_reg2[8];crc_reg2[10] <= crc_reg2[9];crc_reg2[11] <= crc_reg2[10];crc_reg2[12] <= crc_reg2[11] ^ data_for_send[{in_has_send_bit[2:0],2'b0}+1] ^ crc_reg2[15];crc_reg2[13] <= crc_reg2[12];crc_reg2[14] <= crc_reg2[13];crc_reg2[15] <= crc_reg2[14];crc_reg1[0] <= data_for_send[{in_has_send_bit[2:0],2'b0}+2] ^ crc_reg1[15];crc_reg1[1] <= crc_reg1[0];crc_reg1[2] <= crc_reg1[1];crc_reg1[3] <= crc_reg1[2];crc_reg1[4] <= crc_reg1[3];crc_reg1[5] <= crc_reg1[4] ^ data_for_send[{in_has_send_bit[2:0],2'b0}+2] ^ crc_reg1[15];crc_reg1[6] <= crc_reg1[5];crc_reg1[7] <= crc_reg1[6];crc_reg1[8] <= crc_reg1[7];crc_reg1[9] <= crc_reg1[8];crc_reg1[10] <= crc_reg1[9];crc_reg1[11] <= crc_reg1[10];crc_reg1[12] <= crc_reg1[11] ^ data_for_send[{in_has_send_bit[2:0],2'b0}+2] ^ crc_reg1[15];crc_reg1[13] <= crc_reg1[12];crc_reg1[14] <= crc_reg1[13];crc_reg1[15] <= crc_reg1[14];crc_reg0[0] <= data_for_send[{in_has_send_bit[2:0],2'b0}+3] ^ crc_reg0[15];crc_reg0[1] <= crc_reg0[0];crc_reg0[2] <= crc_reg0[1];crc_reg0[3] <= crc_reg0[2];crc_reg0[4] <= crc_reg0[3];crc_reg0[5] <= crc_reg0[4] ^ data_for_send[{in_has_send_bit[2:0],2'b0}+3] ^ crc_reg0[15];crc_reg0[6] <= crc_reg0[5];crc_reg0[7] <= crc_reg0[6];crc_reg0[8] <= crc_reg0[7];crc_reg0[9] <= crc_reg0[8];crc_reg0[10] <= crc_reg0[9];crc_reg0[11] <= crc_reg0[10];crc_reg0[12] <= crc_reg0[11] ^ data_for_send[{in_has_send_bit[2:0],2'b0}+3] ^ crc_reg0[15];crc_reg0[13] <= crc_reg0[12];crc_reg0[14] <= crc_reg0[13];crc_reg0[15] <= crc_reg0[14];endend
end//------------------------------------------------------
// Generate data for send
//------------------------------------------------------
assign sd_fifo_rdata_tp = {sd_fifo_rdata[7:0],sd_fifo_rdata[15:8],sd_fifo_rdata[23:16],sd_fifo_rdata[31:24]};
//data_for_send是[0:31] 把sd_fifo_rdata_tp 的高位放在地位,用在crc的生成
always @(*) begindata_for_send = 32'b0;if (in_current_state == `DATA_STATE_SEND)data_for_send = sd_fifo_rdata_tp;
end//-------------------------------------------------------
// GEnerate tx fifo read enable signal
//-------------------------------------------------------always @(*) beginsd_fifo_re = 1'b0;if (!in_data_width)beginif(((in_current_state == `DATA_STATE_SEND_START_BIT) && (in_has_send_bit[4:0] == 5'b0)) ||((in_current_state == `DATA_STATE_SEND) && (in_next_state == `DATA_STATE_SEND) && (in_has_send_bit[4:0] == 5'b11111)))sd_fifo_re = 1'b1;endelse beginif(((in_current_state == `DATA_STATE_SEND_START_BIT) && (in_has_send_bit[2:0] == 3'b0)) ||((in_current_state == `DATA_STATE_SEND) && (in_next_state == `DATA_STATE_SEND) && (in_has_send_bit[2:0] == 3'b111)))sd_fifo_re = 1'b1;end
end//---------------------------------------------------------------
// Generate crc status wrong flag after sending data to sd card
//---------------------------------------------------------------
//crc的状态用3bit表示(010是OK),当状态为错误时产生数据错误信号
//应该是用高3位010判断(课上提出)?后面看波形确认
always @(*) beginout_crc_status_wrong =1'b0;// there crc_status_reg maybe sould be 4'b0100 ,see the waveif((in_current_state == `DATA_STATE_SEND_BUSY) && !(crc_status_reg == 4'b0010))out_crc_status_wrong =1'b1;
endendmodule
sd_data_receive_shift_register
功能描述:
1、数据读入并成一个word,swap,写入fifo
2、CRC数据读取,并和内部产生的CRC数据进行对比,以判定读入的数据是否出错,以out_receive_data_crc_error信号作标志位。
信号描述
signals | I/O | Width | from | to | declaration |
---|---|---|---|---|---|
in_sd_clk | input | 1 | sd_clk | 时钟信号 | |
in_soft_reset | input | 1 | 软件复位 | ||
in_current_state | input | [3:0] | sd_data_fsm | 数据当前状态标志位 | |
in_serial_data | input | [3:0] | sd_card | 数据输入端口 | |
in_data_width | input | 1 | sd_if | host使用数据线判定信号:1/4 data line | |
in_has_receive_bit | input | [13:0] | sd_data_fsm | Host已接收的数据bit大小 | |
sd_fifo_we | output | 1 | fifo | fifo写请求信号 | |
sd_fifo_wdata | output | [31:0] | fifo | fifo数据写入端口 | |
out_receive_data_crc_err | output | 1 | sd_if | 读入数据crc检验错误 |
verilog实现
module sd_data_receive_shift_register(in_sd_clk, //clock for sd cardhrst_n, in_soft_reset, //software resetin_current_state, //surrent state of data fsmin_serial_data, //data input from sd cardin_data_width, //data width 1:4bit 0:1bitin_has_receive_bit, //has received data bitssd_fifo_wdata, //output parallel data to rx fifosd_fifo_we, //host writes rx_fifoout_receive_data_crc_error //receive data crc error flag
);
input in_sd_clk; //clock for sd card
input hrst_n;
input in_soft_reset; //software reset
input [3:0] in_current_state; //surrent state of data fsm
input [3:0] in_serial_data; //data input from sd card
input in_data_width; //data width 1:4bit 0:1bit
input [13:0] in_has_receive_bit; //has received data bitsoutput [31:0] sd_fifo_wdata; //output parallel data to rx fifo
output sd_fifo_we; //host writes rx_fifo
output out_receive_data_crc_error; //receive data crc error flagreg out_receive_data_crc_error;
reg sd_fifo_we;
reg [15:0] crc_reg0;
reg [15:0] crc_reg1;
reg [15:0] crc_reg2;
reg [15:0] crc_reg3;
reg [15:0] generate_crc_reg0;
reg [15:0] generate_crc_reg1;
reg [15:0] generate_crc_reg2;
reg [15:0] generate_crc_reg3;
reg [31:0] shift_reg;
reg out_write_receive_fifo;//------------------------------------------------------------
// Beginning of main code
//------------------------------------------------------------
// Overview of the data receive shift register operation
// the following key signals are used in the data receive shift register
// in_serial_data is the data input from sd card
// out_write_receive_fifo is the rx fifo write enable signal
// crc_regx is the received data crc
// generate_crc_regx is the generated data crc
// out_receive_data_crc_error is the data receiveing crc error flag//assign sd_fifo_wdata =shift_reg;
assign sd_fifo_wdata = {shift_reg[7:0],shift_reg[15:8],shift_reg[23:16],shift_reg[31:24]};//------------------------------------------------------
// Register rx fifo write enable signal
//------------------------------------------------------always @(posedge in sd_clk or negedhe hrst_n) beginif (!hrst_n)sd_fifo_we <= 1'b0;else if (!in_soft_reset)sd_fifo_we <= 1'b0;else sd_fifo_we <= out_write_receive_fifo;
end//-------------------------------------------------------------
// Serial to Parallel conversion
// ------------------------------------------------------------always @(posedge in_sd_clk or negedge hrst_n) beginif(!hrst_n)shift_reg <= 32'b0;else if (!in_soft_reset)shift_reg <= 32'b0;else beginif (in_current_state == `DATA_STATE_RECEIVE)beginif(!in_data_width)shift_reg <= {shift_reg[30:0],in_serial_data[0]};elseshift_reg <= {shift_reg[27:0],in_serial_data};endend
end//-------------------------------------------------------------------
//Generate rx fifo write enable signal
//-------------------------------------------------------------------
always @(*) beginout_write_receive_fifo = 1'b0;if (!in_data_width) beginif ((in_current_state == `DATA_STATE_RECEIVE) && (in_has_receive_bit[4:0] == 5'b11111))out_write_receive_fifo = 1'b1;endelse beginif((in_current_state == `DATA_STATE_RECEIVE) && (in_has_receive_bit[2:0] == 3'b111))out_write_receive_fifo = 1'b1;end
end//--------------------------------------------------------------------
// Receive data crc 1bit and 4bit mode
//--------------------------------------------------------------------always @(posedge in_sd_clk or negedge hrst_n)if (!hrst_n)begincrc_reg0 <= 16'b0;crc_reg1 <= 16'b0;crc_reg2 <= 16'b0;crc_reg3 <= 16'b0;endelse if (in_soft_reset)begincrc_reg0 <= 16'b0;crc_reg1 <= 16'b0;crc_reg2 <= 16'b0;crc_reg3 <= 16'b0;endelse if ((in_current_state == `DATA_STATE_RECEIVE_END_BIT))begincrc_reg0 <= 16'b0;crc_reg1 <= 16'b0;crc_reg2 <= 16'b0;crc_reg3 <= 16'b0;endelse if (in_current_state == `DATA_STATE_RECEIVE_CRC)beginif(in_data_width == 1'b0)crc_reg0 <= {crc_reg0[14:0],in_serial_data[0]};else begincrc_reg0 <= {crc_reg0[14:0],in_serial_data[0]};crc_reg1 <= {crc_reg1[14:0],in_serial_data[1]};crc_reg2 <= {crc_reg2[14:0],in_serial_data[2]};crc_reg3 <= {crc_reg3[14:0],in_serial_data[3]};endend
end//-----------------------------------------------------
// Generate data crc for 1bit and 4bit mode
//-----------------------------------------------------always @(posedge in_sd_clk or negedge hrst_n) beginif (!hrst_n)begingenerate_crc_reg0 <= 16'b0;generate_crc_reg1 <= 16'b0;generate_crc_reg2 <= 16'b0;generate_crc_reg3 <= 16'b0;endelse if (!in_soft_reset)begingenerate_crc_reg0 <= 16'b0;generate_crc_reg1 <= 16'b0;generate_crc_reg2 <= 16'b0;generate_crc_reg3 <= 16'b0;endelse if ((in_current_state == `DATA_STATE_RECEIVE_END_BIT))begingenerate_crc_reg0 <= 16'b0;generate_crc_reg1 <= 16'b0;generate_crc_reg2 <= 16'b0;generate_crc_reg3 <= 16'b0;endelse if (in_current_state == `DATA_STATE_RECEIVE)beginif (in_data_width == 1'b0)begingenerate_crc_reg0[0] <= in_serial_data[0] ^ generate_crc_reg0[15];generate_crc_reg0[1] <= generate_crc_reg0[0];generate_crc_reg0[2] <= generate_crc_reg0[1];generate_crc_reg0[3] <= generate_crc_reg0[2];generate_crc_reg0[4] <= generate_crc_reg0[3];generate_crc_reg0[5] <= generate_crc_reg0[4] ^ in_serial_data[0] ^ generate_crc_reg0[15];generate_crc_reg0[6] <= generate_crc_reg0[5];generate_crc_reg0[7] <= generate_crc_reg0[6];generate_crc_reg0[8] <= generate_crc_reg0[7];generate_crc_reg0[9] <= generate_crc_reg0[8];generate_crc_reg0[10] <= generate_crc_reg0[9];generate_crc_reg0[11] <= generate_crc_reg0[10];generate_crc_reg0[12] <= generate_crc_reg0[11] ^ in_serial_data[0] ^ generate_crc_reg0[15];generate_crc_reg0[13] <= generate_crc_reg0[12];generate_crc_reg0[14] <= generate_crc_reg0[13];generate_crc_reg0[15] <= generate_crc_reg0[14];endelse begingenerate_crc_reg0[0] <= in_serial_data[0] ^ generate_crc_reg0[15];generate_crc_reg0[1] <= generate_crc_reg0[0];generate_crc_reg0[2] <= generate_crc_reg0[1];generate_crc_reg0[3] <= generate_crc_reg0[2];generate_crc_reg0[4] <= generate_crc_reg0[3];generate_crc_reg0[5] <= generate_crc_reg0[4] ^ in_serial_data[0] ^ generate_crc_reg0[15];generate_crc_reg0[6] <= generate_crc_reg0[5];generate_crc_reg0[7] <= generate_crc_reg0[6];generate_crc_reg0[8] <= generate_crc_reg0[7];generate_crc_reg0[9] <= generate_crc_reg0[8];generate_crc_reg0[10] <= generate_crc_reg0[9];generate_crc_reg0[11] <= generate_crc_reg0[10];generate_crc_reg0[12] <= generate_crc_reg0[11] ^ in_serial_data[0] ^ generate_crc_reg0[15];generate_crc_reg0[13] <= generate_crc_reg0[12];generate_crc_reg0[14] <= generate_crc_reg0[13];generate_crc_reg0[15] <= generate_crc_reg0[14];generate_crc_reg1[0] <= in_serial_data[1] ^ generate_crc_reg1[15];generate_crc_reg1[1] <= generate_crc_reg1[0];generate_crc_reg1[2] <= generate_crc_reg1[1];generate_crc_reg1[3] <= generate_crc_reg1[2];generate_crc_reg1[4] <= generate_crc_reg1[3];generate_crc_reg1[5] <= generate_crc_reg1[4] ^ in_serial_data[1] ^ generate_crc_reg1[15];generate_crc_reg1[6] <= generate_crc_reg1[5];generate_crc_reg1[7] <= generate_crc_reg1[6];generate_crc_reg1[8] <= generate_crc_reg1[7];generate_crc_reg1[9] <= generate_crc_reg1[8];generate_crc_reg1[10] <= generate_crc_reg1[9];generate_crc_reg1[11] <= generate_crc_reg1[10];generate_crc_reg1[12] <= generate_crc_reg1[11] ^ in_serial_data[1] ^ generate_crc_reg1[15];generate_crc_reg1[13] <= generate_crc_reg1[12];generate_crc_reg1[14] <= generate_crc_reg1[13];generate_crc_reg1[15] <= generate_crc_reg1[14];generate_crc_reg2[0] <= in_serial_data[2] ^ generate_crc_reg2[15];generate_crc_reg2[1] <= generate_crc_reg2[0];generate_crc_reg2[2] <= generate_crc_reg2[1];generate_crc_reg2[3] <= generate_crc_reg2[2];generate_crc_reg2[4] <= generate_crc_reg2[3];generate_crc_reg2[5] <= generate_crc_reg2[4] ^ in_serial_data[2] ^ generate_crc_reg2[15];generate_crc_reg2[6] <= generate_crc_reg2[5];generate_crc_reg2[7] <= generate_crc_reg2[6];generate_crc_reg2[8] <= generate_crc_reg2[7];generate_crc_reg2[9] <= generate_crc_reg2[8];generate_crc_reg2[10] <= generate_crc_reg2[9];generate_crc_reg2[11] <= generate_crc_reg2[10];generate_crc_reg2[12] <= generate_crc_reg2[11] ^ in_serial_data[2] ^ generate_crc_reg2[15];generate_crc_reg2[13] <= generate_crc_reg2[12];generate_crc_reg2[14] <= generate_crc_reg2[13];generate_crc_reg2[15] <= generate_crc_reg2[14];generate_crc_reg3[0] <= in_serial_data[3] ^ generate_crc_reg3[15];generate_crc_reg3[1] <= generate_crc_reg3[0];generate_crc_reg3[2] <= generate_crc_reg3[1];generate_crc_reg3[3] <= generate_crc_reg3[2];generate_crc_reg3[4] <= generate_crc_reg3[3];generate_crc_reg3[5] <= generate_crc_reg3[4] ^ in_serial_data[3] ^ generate_crc_reg3[15];generate_crc_reg3[6] <= generate_crc_reg3[5];generate_crc_reg3[7] <= generate_crc_reg3[6];generate_crc_reg3[8] <= generate_crc_reg3[7];generate_crc_reg3[9] <= generate_crc_reg3[8];generate_crc_reg3[10] <= generate_crc_reg3[9];generate_crc_reg3[11] <= generate_crc_reg3[10];generate_crc_reg3[12] <= generate_crc_reg3[11] ^ in_serial_data[3] ^ generate_crc_reg3[15];generate_crc_reg3[13] <= generate_crc_reg3[12];generate_crc_reg3[14] <= generate_crc_reg3[13];generate_crc_reg3[15] <= generate_crc_reg3[14];endendend//----------------------------------------------------------// Compare generated data crc with received data crc//----------------------------------------------------------always @(*) beginout_receive_data_crc_error = 1'b0;if(!in_data_width)beginif ((in_current_state == `DATA_STATE_RECEIVE_END_BIT) && !(crc_reg0 == generate_crc_reg0))out_receive_data_crc_error = 1'b1;endelse beginif((in_current_state == `DATA_STATE_RECEIVE_END_BIT) && (!(crc_reg0 == generate_crc_reg0) ||!(crc_reg1 == generate_crc_reg1) ||!(crc_reg2 == generate_crc_reg2) ||!(crc_reg3 == generate_crc_reg3) )out_receive_data_crc_error = 1'b1;end
end
SD-Host 数据控制模块相关推荐
- sdio接口_单片机基础 —— 使用SDMMC接口读写SD卡数据
本篇详细的记录了如何使用STM32CubeMX配置STM32L431RCT6的硬件SDMMC外设读取SD卡数据. 1. 准备工作 硬件准备 开发板 首先需要准备一个开发板,这里我准备的是STM32L4 ...
- STM32单片机基础19——使用SDMMC接口读写SD卡数据
本篇详细的记录了如何使用STM32CubeMX配置STM32L431RCT6的硬件SDMMC外设读取SD卡数据. 1. 准备工作 硬件准备 开发板 首先需要准备一个开发板,这里我准备的是STM32L4 ...
- SD卡数据读取Altium Designer下载
目录 一.SD卡数据读取 1.SD卡简介 2.代码实现 1.所用软件及硬件 2.SD卡实物连线 3.运行 二.Altium Designer下载及原理图绘制 1.Altium Designer软件安装 ...
- sd卡测速工具_怎样恢复SD卡数据?教你两招轻松恢复
怎样恢复SD卡数据?教你两招轻松恢复 SD卡数据恢复软件里真正免费的而且具备比较高的恢复能力的软件其实不多,而嗨格式数据恢复大师就是其中之一,SD 内存卡是一种性价比相对较高的存储设备,在目前的生活中 ...
- 怎样恢复sd卡数据?靠这几个方法
SD卡是一种便携式存储介质,一般安装在行车记录仪.相机等设备上,可以为我们存储照片.视频.音频等各种数据.但由于很多存储设备在长时间使用后,就很容易出现数据丢失等情况,遇到这种情况我们要怎样恢复sd卡 ...
- 如何恢复sd卡数据呢?
常见的平板电脑.数码相机等电子设备在使用中都会用到sd卡.以便于存储文件.图片.视频等.这让我们经常需要添加或者删除一些不必要的文件,当然重要的文件也可能因为一些误操作或者机械故障而从SD卡中删除.碰 ...
- 恢复原厂设置,清除SD卡数据
恢复原厂设置,清除sd卡数据. 设置--备份与重置--恢复出厂设置.清除平板电脑上的所有数据--重置平板电脑--清除全部内容--正常重启并恢复出厂设置. 设置--备份与重置--恢复出厂设置.清除平板电 ...
- sd卡数据误删怎么恢复?内存卡里的照片删了怎么恢复
sd卡数据误删怎么恢复?内存卡,一般并用在手机.相机里面,主要是用来储存照片等数据的,内存卡的容量通常来讲是有限的,一些不需要的数据我们会选择删除,这样来腾出更多的空间,方便后续保存新的数据.不过,偶 ...
- sd卡数据恢复,怎么恢复sd卡数据?
sd卡数据恢复一直是大家关注的问题,sd卡可以满足用户扩展内存,存储数据的需求,但是很多人在使用SD卡数据的时候,出现误删或者格式化等操作,就很麻烦,将会导致sd卡上的数据丢失.那么要怎么样恢复sd卡 ...
最新文章
- 一个简单IOC与DI示例
- C++primer 10.6节练习
- linux 代码统计工具,Shell脚本实现的基于SVN的代码提交量统计工具
- 美国第一大移动运营商的5G战略:已进入预商用测试
- koa2入门(3)mongoose 增删改查
- 计算机技术分,计算机技术专业那么多,你分得清吗?
- 贫血的Domain Model之说
- Java工作笔记-Map的基本用法
- 微服务开发的 10 个最佳实践
- jvm常用监控命令总结
- 腾讯百度等22家股东退出 链家注册资本缩水34%
- 15.3D效果,盒阴影和滤镜
- C#把Xml转换为DataSet的两种方法
- 百度普通收录正式下线,大量草根站长收录难
- Visio画正态分布曲线
- 深度学习理论——ssd从之前的网络断点接着训练
- 带你认识世界最值钱的十种货币
- 屏幕和摄像头中的视频分辨率P,I,K,MP表示的含义,720p,1080p,2k,5MP
- 怎么压缩gif图片大小?如何压缩gif又不影响画质
- 问题记录:键盘win键无法使用,组合键无反应,win+L不能锁屏