• SD_DATA_RECEIVE_SHIFT_REGISTER


    1.接口

    • 时钟复位软复位
    • 状态信号in_current_state
    • sd卡过来的数据信号in_serial_data
    • 数据位宽in_data_width,决定1线还是4线传输
    • 已经接受的bit数in_has_receive_bit
    • sd发过来的数据信号sd_fifo_wdata,
    • fifo使能信号sd_fifo_we,在收完32bit的参数后给出
    • crc上报错误out_receive_data_crc_error
    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 bits
    
    output  [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 flag
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.内部信号

    后面都会讲到

    reg                 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;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.数据位的转换

    以为高位低位的手法存在差异,这里需要将bit数的顺序换一下

    assign sd_fifo_wdata = {shift_reg[7:0],shift_reg[15:8],shift_reg[23:16],shift_reg[31:24]};
    
    • 1

    4.fifo使能sd_fifo_we

    • 由out_write_receive_fifo打一拍输出
    • 当接收完参数(32位)后给出,相当于这里做了串转并的操作
    always @(posedge in sd_clk or negedhe hrst_n) begin
        if (!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
    /----------------------------------------------------------
    always @(*) begin
        out_write_receive_fifo = 1'b0;
        if (!in_data_width) 
        begin
            if ((in_current_state == `DATA_STATE_RECEIVE) && (in_has_receive_bit[4:0] == 5'b11111))
                out_write_receive_fifo = 1'b1;
        end
        else begin
            if((in_current_state == `DATA_STATE_RECEIVE) && (in_has_receive_bit[2:0] == 3'b111))
                out_write_receive_fifo = 1'b1;
        end
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    5.并转串

    • 两种情况,一线和四线传输的时候移位不同
    always @(posedge in_sd_clk or negedge hrst_n) begin
        if(!hrst_n)
            shift_reg <= 32'b0;
        else if (!in_soft_reset)
            shift_reg <= 32'b0;
        else begin
            if (in_current_state == `DATA_STATE_RECEIVE)
            begin
                if(!in_data_width)
                    shift_reg <= {shift_reg[30:0],in_serial_data[0]};
                else
                    shift_reg <= {shift_reg[27:0],in_serial_data};
            end
        end
    end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    6.接收crc16

    • 在接收完参数后接收crc16,也是串转并的操作
    always @(posedge in_sd_clk or negedge hrst_n)
        if (!hrst_n)
        begin
            crc_reg0 <= 16'b0;
            crc_reg1 <= 16'b0;
            crc_reg2 <= 16'b0;
            crc_reg3 <= 16'b0;
        end
        else if (in_soft_reset)
        begin
            crc_reg0 <= 16'b0;
            crc_reg1 <= 16'b0;
            crc_reg2 <= 16'b0;
            crc_reg3 <= 16'b0;
        end
        else if ((in_current_state == `DATA_STATE_RECEIVE_END_BIT))
        begin
            crc_reg0 <= 16'b0;
            crc_reg1 <= 16'b0;
            crc_reg2 <= 16'b0;
            crc_reg3 <= 16'b0;
        end
        else if (in_current_state == `DATA_STATE_RECEIVE_CRC)
        begin
            if(in_data_width == 1'b0)
                crc_reg0 <= {crc_reg0[14:0],in_serial_data[0]};
            else begin
                crc_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]};
            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

    7.自己计算crc16

    • 方法和前面说cmd模块时的crc7类似
    • 主要是做异或的运算
    • 记住是在接收的同时一起算crc16

    在这里插入图片描述

     always @(posedge in_sd_clk or negedge hrst_n) begin
         if (!hrst_n)
         begin
             generate_crc_reg0 <= 16'b0;
             generate_crc_reg1 <= 16'b0;
             generate_crc_reg2 <= 16'b0;
             generate_crc_reg3 <= 16'b0;
        end
        else if (!in_soft_reset)
        begin
             generate_crc_reg0 <= 16'b0;
             generate_crc_reg1 <= 16'b0;
             generate_crc_reg2 <= 16'b0;
             generate_crc_reg3 <= 16'b0;
         end
         else if ((in_current_state == `DATA_STATE_RECEIVE_END_BIT))
         begin
             generate_crc_reg0 <= 16'b0;
             generate_crc_reg1 <= 16'b0;
             generate_crc_reg2 <= 16'b0;
             generate_crc_reg3 <= 16'b0;
         end
         else if (in_current_state == `DATA_STATE_RECEIVE)
         begin
             if (in_data_width == 1'b0)
             begin
                 generate_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];
             end
             else begin
                 generate_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];
             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

    8.比较crc16

    • 在DATA_STATE_RECEIVE_END_BIT状态,对接收的crc16和自己算出来的crc16进行对比
    • 不同则报错
    always @(*) begin
         out_receive_data_crc_error = 1'b0;
         if(!in_data_width)
         begin
             if ((in_current_state == `DATA_STATE_RECEIVE_END_BIT) && !(crc_reg0 == generate_crc_reg0))
                 out_receive_data_crc_error = 1'b1;
         end
         else begin
             if((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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
  • 相关阅读:
    bjpowernode_MyBatis
    一个22届被裁前端思想上得转变
    第二十二章 面向对象
    SpringBoot RabbitMQ 注解版 基本概念与基本案例
    音视频专题--opengl (3)
    redis缓存穿透问题
    到了30岁,我才有了深刻的感悟:千万不要一辈子靠技术生存
    Dubbo命令行详解
    达梦数据库DM8之逻辑导入导出
    代码随想录 - Day33 - 回溯:切割问题,子集问题
  • 原文地址:https://blog.csdn.net/qq_38502780/article/details/125630745