• SD_DATA_SEND_SHIFT_REGISTER


    1.接口

    • 时钟复位软复位
    • sd卡数据线过来的数据in_sd_data
    • 数据传输宽度in_data_width
    • 从fifo中读出的数据sd_fifo_rdata、使能sd_fifo_re
    • 状态in_current_state、in_next_state
    • 发送的crc,需要in_send_crc_counter、out_crc_status_wrong
    • 发送的数据信号in_has_send_bit、in_interval_counter、out_serial_data
    • 输出数据out_data_half_delay、out_data_dir
    • 高速时钟模式in_high_speed_clk
    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 数对面crc
    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 card
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2.内部信号

    reg [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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.高速时钟模式

    • 由in_high_speed_clk的输入决定out口用哪个数据
    assign out_data_half_delay = in_high_speed_clk ? out_serial_data : out_data_half_delay_tp;
    
    assign out_data_dir = in_high_speed_clk ? data_dir_pos :data_dir_nes;
     
     //-------------------------------------------------------
    always @(negedge in_sd_clk or negedge hrst_n) begin
        if (!hrst_n) begin
            out_data_half_delay_tp <= 4'b1111;
        end
        else begin
            out_data_half_delay_tp <= out_serial_data;
    		//用clk下降沿打拍,延迟半个周期
        end
    end
    //-------------------------------------------------
    always @(negedge in_sd_clk or negedge hrst_n) begin
        if (!hrst_n) begin
            data_dir_nes <= 4'b0
        end
        else begin
                data_dir_nes <= {data_dir_pos[3],data_dir_pos[2],data_dir_pos[1],data_dir_pos[0]};
        end
    end
    
    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 && data_dir_pos[0];
     assign data_dir_pos[2] = data_dir_pos[1];
     assign data_dir_pos[3] = data_dir_pos[1];
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    4.移位进行数据的并转串

    • 需要移位的数据有out_serial_data、crc_status_reg、crc_shift_reg
    • 在每个不同状态,移位不一样的数据
    always @(posedge in_sd_clk or negedge hrst_n) begin
        if (!hrst_n) begin
            shift_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;
        end
        else if (!in_soft_reset) 
        begin
            shift_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;
        end
        else 
        begin
            if(!in_data_width)
            begin
                if (in_current_state == `DATA_STATE_SEND_START_BIT)
    			//send start bit
                    out_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};
    					//向左移位输出,并行转串行
                end
                else if (in_current_state == `DATA_STATE_SEND_CRC)
                begin
                    if (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};
                end
                else if (in_current_state == `DATA_STATE_SEND_END_BIT)
                begin
                    out_serial_data[0] <= 1'b1;
                end
    			//DATA_STATE_RECEIVE_CRC_STATUS 这里sd 数据线的方向变化,变为接收crc_status
                else if (in_current_state == `DATA_STATE_RECEIVE_CRC_STATUS)
                begin
                    crc_status_reg <= {crc_status_reg[2:0], in_sd_data[0]};
                end
                else if (in_current_state == `DATA_STATE_WAIT_SEND)
                begin
                    crc_status_reg <= 4'b0;
                end
            end
            else
            begin
                if (in_current_state == `DATA_STATE_SEND_START_BIT)
                    out_serial_data <= 4'b0;
                else if (in_current_state == `DATA_STATE_SEND)
                begin
                    if (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};
                end
                else if (in_current_state == `DATA_STATE_SEND_CRC)
                begin
                    if(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};
                    end
                    else
                    begin
                        {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};
                    end
                end
                else if (in_current_state == `DATA_STATE_RECEIVE_CRC_STATUS)
                begin
                    crc_status_reg <= {crc_status_reg[2:0],in_sd_data[0]};
                end
                else if (in_current_state ==`DATA_STATE_WAIT_SEND)
                    crc_status_reg <= 4'b0
            end
        end
    
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    5.data_for_send的产生,后面用于计算crc

    • 同样的对于从fifo读到的数据进行高位低位变换,记作sd_fifo_rdata_tp
    • 当状态为DATA_STATE_SEND时,将sd_fifo_rdata_tp给到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]};
    
    always @(*) begin
        data_for_send = 32'b0;
        if (in_current_state == `DATA_STATE_SEND)
            data_for_send = sd_fifo_rdata_tp;
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    6.计算crc16

    • 在发送状态的时候,一遍发一边在算
    always @(posedge in_sd_clk or negedge hrst_n) begin
        if (!hrst_n) begin
            crc_reg3 <= 16'b0;
            crc_reg2 <= 16'b0;
            crc_reg1 <= 16'b0;
            crc_reg0 <= 16'b0;
        end
        else if (!in_soft_reset) begin
            crc_reg3 <= 16'b0;
            crc_reg2 <= 16'b0;
            crc_reg1 <= 16'b0;
            crc_reg0 <= 16'b0;
        end
        else if (in_current_state == `DATA_STATE_WAIT_SEND)
        begin
            crc_reg3 <= 16'b0;
            crc_reg2 <= 16'b0;
            crc_reg1 <= 16'b0;
            crc_reg0 <= 16'b0;
        end
        else if (in_current_state == `DATA_STATE_SEND)
        begin
            if (!in_data_width)
            begin
                crc_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];
            end
            else
            begin
                crc_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];
            end
        end
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114

    7.fifo读使能

    • 分为1线和4线的情况
    • 数据发完的时候给出fifo的读使能,表明这一次发完了,需要读下一次的数据
    always @(*) begin
        sd_fifo_re = 1'b0;
        if (!in_data_width)
        begin
            if(((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;
        end
        else begin
            if(((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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    8.crc16的状态

    • crc16的状态为3bit数,由crc_status_reg 决定,010表示正常
    always @(*) begin
        out_crc_status_wrong =1'b0;
        if((in_current_state == `DATA_STATE_SEND_BUSY) && !(crc_status_reg == 4'b0010))
            out_crc_status_wrong =1'b1;
    end
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    怎么把gif动图尺寸改小?一招教你轻松修改gif大小
    细说RTSP、RTMP和GB28181区别
    Nacos源码 (6) Grpc概述与Nacos集成
    Redis桌面管理工具:Redis Desktop Manager for Mac
    Vue封装Axios实现全局的loading自动显示效果
    使用rosserial实现ROS与Windows的service服务通信
    wpf中的Border和Background
    开源数据库 SQLite 发布 3.37.0 版本
    0067 练习
    计算机专业的就业情况如何?
  • 原文地址:https://blog.csdn.net/qq_38502780/article/details/125631063