当前位置:网站首页>SD_CMD_SEND_SHIFT_REGISTER

SD_CMD_SEND_SHIFT_REGISTER

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

1.接口

  • 正常的时钟复位软复位
  • 大哥cmd_fsm发过来的当前状态信号in_current_state
  • 已经发送的bit数in_has_send_bit
  • 从sd卡过来的命令号信号in_command_index、参数信号in_command_argument
  • 还有高速时钟信号in_high_speed_clk,会和普通不一样
  • 给到sd卡的命令信号out_sd_cmd
  • 类似pad的oen信号的out_cmd_dir方向信号,1代表发给sd卡
input           in_sd_clk;
input           hrst_n;
input           in_soft_reset;

//from fsm
input [2:0]     in_current_state;
input [5:0]     in_has_send_bit;

//from sd if
input [5:0]     in_command_index;
input [31:0]    in_command_argument;
input           in_high_speed_clk;


output          out_sd_cmd;
output          out_cmd_dir;

2.传输方向out_cmd_dir

  • 根据是否使用高速时钟来选择上升沿cmd_dir_pos或下降沿cmd_dir_neg传输
  • cmd_dir_neg 比 cmd_dir_pos 延迟半个周期
always @(posedge in_sd_clk or negedge hrst_n) begin
    if(!hrst_n)
        cmd_dir_pos <= 1'b0;
	else if (in_current_state == `CMD_STATE_SEND)
		cmd_dir_pos <= 1'b1;
	else if (in_current_state == `CMD_STATE_STOP)
		cmd_dir_pos <= 1'b0;
	else if (in_current_state == `CMD_STATE_WAIT_RECEIVE)
		cmd_dir_pos <= 1'b0;
end

always @(negedge in_sd_clk or negedge hrst_n) begin
    if(!hrst_n)
        cmd_dir_neg <= 1'b0;
    else
        cmd_dir_neg <= cmd_dir_pos;
end

assign out_cmd_dir = in_high_speed_clk ? cmd_dir_pos : cmd_dir_neg;

3.命令产生cmd_for_send

  • 在SEND状态下根据已经发送的bit数in_has_send_bit给出相应的命令
  • 命令的格式如下:共48位 需要6bit
  • 使用case分别给每个bit时的cmd_for_send赋值
  • 只给到argument(参数),之后的crc、结束位没有给出
  • 组合逻辑要是没写完所有情况会生成锁存器latch,所以一开始就让cmd_for_send为0
    在这里插入图片描述
always @(*) begin
    cmd_for_send = 8'b0;
    if (in_current_state == `CMD_STATE_SEND)
        begin
            case(in_has_send_bit)
                6'b0,6'b1,6'b10,6'b11,6'b100,6'b101,6'b110,6'b111:
                    cmd_for_send = {
    1'b0,1'b1,in_command_index};
                6'b001000,6'b001001,6'b001010,6'b001011,6'b001100,6'b001101,6'b001110,6'b001111:
                    cmd_for_send = {
    in_command_argument[31:24]};
                6'b010000,6'b010001,6'b010010,6'b010011,6'b010100,6'b010101,6'b010110,6'b010111:
                    cmd_for_send = {
    in_command_argument[23:16]};
                6'b011000,6'b011001,6'b011010,6'b011011,6'b011100,6'b011101,6'b011110,6'b011111:
                    cmd_for_send = {
    in_command_argument[15:8]};
                6'b100000,6'b100001,6'b100010,6'b100011,6'b100100,6'b100101,6'b100110,6'b100111:
                    cmd_for_send = {
    in_command_argument[7:0]};
            endcase
        end
end

4.命令输出out_sd_cmd

  • 根据是否使用高速时钟来选择上升沿输出sd_cmd_pos或者时下降沿输出sd_cmd_neg
  • sd_cmd_neg比sd_cmd_pos还是慢了半拍
  • 由于板级路径长,要是全是组合逻辑pos建立时间可能会不满足,那么移动半个周期可能就满足了
  • 用移位寄存器进行并转串,in_has_send_bit[2:0] == 3’b0表示没8bit进到case里拿数据
always @(posedge in_sd_clk or negedge hrst_n) begin
    if(!hrst_n)
        begin
            sd_cmd_pos <= 1'b1;
            shift_r <= 8'b0;
        end
    else if(!in_soft_reset)
        begin
            sd_cmd_pos <= 1'b1;
            shift_r <= 8'b0;
        end
    else
        begin
            if(in_current_state == `CMD_STATE_SEND)
                begin
                    if(in_has_send_bit[2:0] == 3'b0)
                        begin
                            case(in_has_send_bit)
                                6'b000000:
                                    {
    sd_cmd_pos,shift_r} <= {
    1'b0,1'b1,in_command_index,1'b0};
                                6'b001000:
                                    {
    sd_cmd_pos,shift_r} <= {
    in_command_argument[31:24],1'b0};
                                6'b010000:
                                    {
    sd_cmd_pos,shift_r} <= {
    in_command_argument[23:16],1'b0};
                                6'b011000:
                                    {
    sd_cmd_pos,shift_r} <= {
    in_command_argument[15:8],1'b0};
                                6'b100000:
                                    {
    sd_cmd_pos,shift_r} <= {
    in_command_argument[7:0],1'b0};
								6'b101000:
                                    {
    sd_cmd_pos,shift_r} <= {
    crc_reg,1'b1,1'b0};
                            endcase
                        end
                    else
                        {
    sd_cmd_pos,shift_r} <= {
    shift_r,1'b0};
                end
        end
end

always @(negedge in_sd_clk or negedge hrst_n) begin
    if (!hrst_n)
        sd_cmd_neg <= 1'b0;
    else
        sd_cmd_neg <= sd_cmd_pos;
end

assign out_sd_cmd = in_high_speed_clk ? sd_cmd_pos : sd_cmd_neg;

5.计算crc7

  • 计算crc7,并通过out_sd_cmd 发送给sd卡
  • 计算crc7的方法:[0]和[3]这两个比特要做异或运算,其他的移位就行,见下图
    在这里插入图片描述
always @(posedge in_sd_clk or negedge hrst_n) begin
    if(!hrst_n)
        crc_reg <= 7'b0;
    else if (!in_soft_reset)
        crc_reg <= 7'b0;
    else
        if((in_current_state == `CMD_STATE_SEND) &&
            (in_has_send_bit >= 6'b0)            &&
            (in_has_send_bit < 6'd40))
        begin
            crc_reg[0] <= cmd_for_send[in_has_send_bit[2:0]]^crc_reg[6];
            crc_reg[1] <= crc_reg[0];
            crc_reg[2] <= crc_reg[1];
            crc_reg[3] <= cmd_for_send[in_has_send_bit[2:0]]^crc_reg[6]^crc_reg[2];
            crc_reg[4] <= crc_reg[3];
            crc_reg[5] <= crc_reg[4];
            crc_reg[6] <= crc_reg[5];
        end
        else
            crc_reg <= 7'b0;
end
原网站

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