当前位置:网站首页>SD_DATA_RECEIVE_SHIFT_REGISTER

SD_DATA_RECEIVE_SHIFT_REGISTER

2022-07-07 15:46:00 捌肆幺幺

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

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;

3.数据位的转换

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

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

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

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

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

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

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
原网站

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