FPGA驱动eMMC系列(三)-----命令的发送与接收

一. 简介

本篇文章,将介绍如何编写命令的发送,与响应的接收,这部分代码,这部分代码。

对应所以模式而言,发送与接收的时序都是一样的,所以这部分代码对应所以的eMMC而言,都是通用的。

先来看一下整体的框图,命令模块下包括发送与接收,还是比较容易的。

关注微信公众号 FPGA之旅 回复 eMMC代码V1 获取完整工程,目前支持高速和HS200.HS400有点问题,可能是我PCB的问题。
FPGA驱动eMMC系列(二)-------上电初始化
FPGA驱动eMMC系列(一)-------简介
FPGA驱动eMMC系列(三)-----命令的发送与接收_第1张图片

FPGA驱动eMMC系列(三)-----命令的发送与接收_第2张图片

二. 命令发送

在命令发送模块里面,我们就不关心,命令长什么样,每一位代表什么意思,只需要知道每一条命令的长度,以及如何将其发送出去即可。

模块的接口信号如下,非常简单。当req请求来的时候,模块就会将eMMC_Command发送出去,然后返回一个ack信号,模块接口和UART的比较类似。所有的命令数据,都是在高电平的时候进行采样。

eMMC_CMD_TX(
    input           eMMC_CLK,
    input           rst_n,

    input           eMMC_tx_req,            //eMMC 发送请求
    output          eMMC_tx_ack,            //eMMC 发送完成响应


    input[47:0]     eMMC_Command,           //eMMC 发送命令
    output          eMMC_CMD              //eMMC 命令数据
);

三. 响应接收

命令的接收,和串口的接收类型,空闲的时候,eMMC_CMD为高电平起始信号为一个周期的低电平,同样也是检测到低电平,也就是下降沿,标志响应的起始位。

其中由于响应的大小有两种,48bit和136bit。通过外部eMMC_Response_Size参数控制即可,也是在时钟的上升沿进行采样。

最后将接收到的eMMC_Response,输出出去。内部的写法和串口类型,想要了解的可以看完整代码。

eMMC_CMD_RX(
    input           eMMC_CLK,
    input           rst_n,

    input           eMMC_rx_req,                //eMMC 发送请求
    output          eMMC_rx_ack,                //eMMC 发送完成响应

    input            eMMC_Response_Size,        //eMMC 响应大小 0 : 48bit , 1 :136bit
    output[135:0]    eMMC_Response,             //eMMC 接收到的响应  先接收高位
    input            eMMC_CMD                //eMMC 命令数据
);

四. 命令整体模块

发送一个命令后,基本上都会有一个响应,有的命令没有响应(广播命令),例如CMD0。所以命令发送接收的过程为 先发送命令,然后再接收响应,为一个完整的过程。

这部分的状态机如下,如果命令的类型为`CMD_Type_BC,说明没有响应,则直接进入END。有些命令发送后,eMMC设备会产生busy信号,将DAT[0]拉低,这个时候需要等待,直到DAT[0]为高,结束本次的发送。

always@(*)
begin
    case (state)
        S_IDLE: 
            if(eMMC_Cmd_Req == 1'b1)
                next_state <= S_SEND;
            else
                next_state <= S_IDLE;
        S_SEND:
            if(eMMC_tx_ack == 1'b1 && eMMC_Cmd_Typei == `CMD_Type_BC)
                next_state <= S_DONE;
            else if(eMMC_tx_ack == 1'b1)
                next_state <= S_RECV;
            else
                next_state <= S_SEND;
        S_RECV:
            if(eMMC_rx_ack == 1'b1 || eMMC_Response_Timeout == 1'b1)
                next_state <= S_DONE;
            else
                next_state <= S_RECV;
        S_DONE:
            if( eMMC_data0 == 1'b1)
                next_state <= S_IDLE;
            else
                next_state <= S_DONE;
        default:    next_state <= S_IDLE;
    endcase
end

五. 完

这部分就到这里,还是比较轻松的,对完整代码有疑问的,或者对eMMC不清楚的,可以通过微信公众号私聊我。

你可能感兴趣的:(FPGA,fpga开发,eMMC)