当前位置:网站首页>SOC_SD_DATA_FSM

SOC_SD_DATA_FSM

2022-07-05 06:37:00 捌肆幺幺

1.接口

  • 正常的时钟复位软复位
  • 从sd卡过来的in_data_ready、in_sd_data、in_data_direction
  • 从fifo模块过来的sd_fifo_full
  • 需要接收发送的byte以及块的数量,need_to_receive_byte、need_to_receive_block等
  • 数据传输位宽in_data_width,有1线和4线传输
  • 读数据超时in_read_to
  • 给小弟模块的状态信号current_state、next_state
  • 发送接收的bit数以及计数器
  • crc状态计数receive_crc_status_counter
  • 格式中间信号EZZS计数,interval_counter
  • 传输结束信号out_transfer_complete、one_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;          //从sd if 的data_fsm_ready传来
input           sd_fifo_full;

input [3:0]     in_sd_data;             //data input from sd card 一般只用到[0]
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 out of read data fsm

output [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 给到sd if
output          one_bk_re_end;

2.状态机

①描述状态的转移

always @ (posedge in_sd_clk or negedge hrst_n) begin
    if(!hrst_n)
        current_state <= `CMD_STATE_STOP;
    else if(!in_soft_reset)
        current_state <= `CMD_STATE_STOP;
    else 
        current_state <= next_state;
end

②组合逻辑状态跳转,并赋值相应使能

状态介绍,此模块的状态比较多,我直接简写了,反正也能看懂
在这里插入图片描述

  • STOP :停止状态,in_data_ready高有效时进入IDLE状态
  • IDLE: 读写判断状态,in_data_direction高有效时,表示host准备发送数据,WAIT_SEND状态,反之,则表示host准备接收数据,进入WAIT_RECEIVE状态
  • WAIT_RECEIVE : 读操作准备状态,首先判断数据块是否满足要求,满足则跳入STATE_STOP,并给出状态信号read_to_error;最后,检测数据线data[0]是否低有效,有效则跳入RECEIVE状态,否则保持;
  • RECEIVE :数据读操作处理过程,并需要判断每块byte数据是否读完,满足则跳入RECEIVE_CRC状态,否则保持;
  • RECEIVE_CRC :判断每块crc数据是否读完,满足则跳入RECEIVE_END_BIT状态,否则保持;
  • RECEIVE_END_BIT :首先判断数据块是否满足要求,满足则跳入STOP,不满足则跳入WAIT_RECEIVE状态;
  • WAIT_SEND :数据输出等待状态,在条件fifo已被写满情况下,判断所有数据块是否发送完成,满足则跳入STOP状态,否则进行data[0]数据判断,高有效,跳入SNED_Z状态,否则保持;
  • SNED_Z:不做任何数据处理,进入DATA_STATE_SNED_P状态;
  • SNED_P:总线方向改变方向,进入SNED_START_BIT状态;
  • SNED_START_BIT:开始数据发送状态,跳入STATE_SEND状态;
  • SEND:数据发送状态,单块数据所有bit发送完成后,进入STATE_SEND_CRC状态,否则保持;
  • SEND_CRC:CRC数据发送状态,完成后,跳入STATE_SEND_END_BIT;
  • SEND_END_BIT:结束位发送状态,并用于数据线的方向切换(状态中间点),进入RECEIVE_CRC_STATUS状态;
  • RECEIVE_CRC_STATUS:收到crc3个bit以及一个‘E’后,进入SEND_BUSY状态;
  • SEND_BUSY:数据块传输结束判断状态,所有block发送结束,跳入STATE_STOP状态,停止操作。否则,进入DATA_STATE_WAIT_SEND状态,等待下一次块数据传输的开始;

在状态的跳转中还伴随着相应的使能如:

  • 接收bit计数使能has_receive_bit_counter_en
  • 发送bit计数使能has_send_bit_counter_en
  • 接收block计数使能has_receive_block_counter_en
  • 发送block计数使能has_send_block_counter_en
  • 接收crc计数使能receive_crc_counter_en
  • 发送crc计数使能send_crc_counter_en
  • 读超时计数使能read_resp_time_counter_en
  • 中间EZZS数据计数使能interval_counter_en
  • 接收crc状态计数receive_crc_status_counter_en
  • 一次传输完成信号out_transfer_complete
always @(*) begin
    out_read_to_error = 1'b0;
    case (current_state)
        `DATA_STATE_STOP: //0
        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_ready)
                next_state = `DATA_STATE_IDLE;
            else
                next_state = `DATA_STATE_STOP;
        end

        `DATA_STATE_IDLE: //1
		//IDLE状态判断读/写sd,进入读写等待状态
        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_direction)
                next_state = `DATA_STATE_WAIT_RECEIVE;
            else
                next_state = `DATA_STATE_WAIT_SEND;
        end

        `DATA_STATE_WAIT_RECEIVE: //2
		//数据等待接收状态:所有blcok收完STOP;读超时STOP;
		//接收到数据的开始位data[0]==0,进入数据接收模式
        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;

            if (has_receive_block == need_to_receive_block)
            begin
                next_state = `DATA_STATE_STOP;
                out_transfer_complete = 1'b1;
            end
            else if (read_resp_time_counter == in_read_to)
            begin
                next_state = `DATA_STATE_STOP;
                out_read_to_error = 1'b1;
            end
            else begin
                if(!in_sd_data[0])
                    next_state = `DATA_STATE_RECEIVE;
                else begin
                    next_state = `DATA_STATE_WAIT_RECEIVE;
                    read_resp_time_counter_en = 1'b1;
                end
            end
        end
        
        `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) begin
                if (has_receive_bit == need_to_receive_bit - 1)
                begin
                    next_state = `DATA_STATE_RECEIVE_CRC;
                    has_receive_bit_counter_en = 1'b0;
                end
                else begin
                    next_state = `DATA_STATE_RECEIVE;
                    has_receive_bit_counter_en = 1'b1;
                end
            end
            else begin
                if (has_receive_bit_4 == (need_to_receive_bit_4 - 1))
                begin
                    next_state = `DATA_STATE_RECEIVE_CRC;
                    has_receive_bit_counter_en = 1'b0;
                end
                else begin
                    next_state = `DATA_STATE_RECEIVE;
                    has_receive_bit_counter_en = 1'b1;
                end
            end
        end

        `DATA_STATE_RECEIVE_CRC: //4
		//接收crc状态,启用接收crc计数器,接收完成进入,接收end_bit状态
        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(receive_crc_counter == 15) begin
                next_state =`DATA_STATE_RECEIVE_END_BIT;
                receive_crc_counter_en = 1'b0;
            end
            else begin
                next_state = `DATA_STATE_REVEIVE_CRC;
                receive_crc_counter_en = 1'b1;
            end
        end
        
        `DATA_STATE_RECEIVE_END_BIT: //5
		//接收end_bit,全部block接收完则回到STOP
		//否则blcok计数器启用,调到等待接收,启用被释放,相当于block计数只加了1
        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(has_receive_block == (need_to_receive_block - 1)) begin
                next_state = `DATA_STATE_STOP;
                has_receive_block_counter_en = 1'b0;
                out_transfer_complete = 1'b1;
            end
            else begin
                next_state = `DATA_STATE_WAIT_RECEIVE;
                has_receive_block_counter_en = 1'b1;
            end
        end

        `DATA_STATE_WAIT_SEND: //6
        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(sd_fifo_full) begin
                if(has_send_block == need_to_send_block)
                begin
                    next_state = `DATA_STATE_STOP;
                    out_transfer_complete = 1'b1;
                end
                else begin
                   // if (!in_sd_data[0])
				    if (in_sd_data[0])
                        next_state = `DATA_STATE_WAIT_SEND;
                    else
                        next_state = `DATA_STAET_SEND_Z;
                end
            end
            else
                next_state = `DATA_STATE_WAIT_SEND;
        end
        
        `DATA_STATE_SEND: //7
		//启用发送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)
            begin
                if (has_send_bit == (need_send_bit - 1))
                begin
                    next_state = `DAYA_STATE_SEND_CRC;
                    has_send_bit_counter_en = 1'b0;
                end
                else begin
                    next_state = `DATA_STATE_SEND;
                    has_send_bit_counter_en = 1'b1;
                end
            end
            else begin
                if (has_send_bit == (need_to_seed_bit_4 - 1))
                begin
                    next_state = `DAYA_STATE_SEND_CRC;
                    has_send_bit_counter_en = 1'b0;
                end
                else begin
                    next_state = `DATA_STATE_SEND;
                    has_send_bit_counter_en = 1'b1;
                end
            end
        end
        
        `DATA_STATE_SEND_CRC: //8
		//启用发送crc bit计数,发送完crc准备发end bit
        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 (send_crc_counter == 15)
            begin
                next_state = `DATA_STATE_SEND_END_BIT;
                send_crc_counter_en = 1'b0;
            end
            else begin
                next_state = `DATA_STATE_SEND_CRC;
                send_crc_counter_en = 1'b1;
            end
        end

        `DATA_STATE_SEND_END_BIT: //9
		//发送完endbit ,准备接收数据是否正确的信号,
		//这里应该增加一个状态更好,而不是用计数的方式
        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;
			//这里4个周期接收EZZS
            if (interval_counter == 3)
            begin
                next_state = `DATA_STATE_RECEIVE_CRC_STATUS;
                interval_counter_en = 1'b0;
            end
            else begin
                next_state = `DATA_STATE_SNED_END_BIT;
                interval_counter_en = 1'b1;
            end
        end

        `DATA_STATE_RECEIVE_CRC_STATUS ://10
		
        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;
			//这里4个周期接收status(3bit)+E
            if (receive_crc_status_counter == 3)
            begin
                next_state = `DATA_STATE_SEND_BUSY;
                receive_crc_status_counter_en = 1'b0;
            end
            else begin
                next_state = `DATA_STATE_RECEIVE_CRC_STATUS;
                receive_crc_status_counter_en = 1'b1;
            end
        end

        `DATA_STATE_SEND_BUSY: //11
		//数据块传输结束判断状态,所有block发送结束,
		//跳入STATE_STOP状态,停止操作。
		//否则,进入DATA_STATE_WAIT_SEND状态,等待下一次块数据传输的开始。
        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 (has_send_block == (need_to_send_block - 1))
            begin
                next_state = `DATA_STATE_STOP;
                has_send_block_counter_en = 1'b0;
                out_transfer_complete = 1'b1;
            end
            else begin
                next_state = `DATA_STATE_WAIT_SEND;
                has_send_block_counter_en = 1'b1;
            end
        end

        `DATA_STATE_SEND_START_BIT: //12
        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;
            next_state = `DATA_STATE_SEND;
        end

        `DATA_STATE_SEND_Z:
        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;
            next_state = `DATA_STATE_SEND_P;
        end

        `DATA_STATE_SEND_P:
        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;
            next_state = `DATA_STATE_SEND_START_BIT;
        end

        default:
        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;
            next_state = `DATA_STATE_STOP;
        end
    endcase
end

3.one_bk_re_end的产生

  • 在DATA_STATE_RECEIVE_END_BIT状态给one_bk_re_end_tp 置1
  • 将one_bk_re_end_tp打一拍给到one_bk_re_end 输出,可以保证时序
assign  one_bk_re_end_tp = (current_state == `DATA_STATE_RECEIVE_END_BIT);

always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!hrst_n)
		one_bk_re_end <= 1'b0;
	else 
		one_bk_re_end <= one_bk_re_end_tp;

4.一些计数器

  • has_receive_bit计数
always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!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_resp_time_counter计数
always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!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_send_bit 计数
always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!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
  • receive_crc_counter
always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!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_receive_block
always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!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_send_block
always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!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
  • interval_counter
always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!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
  • receive_crc_status_counter
always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!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
  • send_crc_counter
always @(posedge in_sd_clk or negedge hrst_n) begin
    if (!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;
end
原网站

版权声明
本文为[捌肆幺幺]所创,转载请带上原文链接,感谢
https://blog.csdn.net/qq_38502780/article/details/125610119