FPGA入门 —— AXI4 总线简介
=============
AXI4 总线协议
AXI4,全称第四代高级可扩展接口(Advanced eXtensible Interface 4),是一种高性能、高带宽、低延迟的片上总线协议,可用于处理器与内存之间传递数据。
动态随机存储器(Dynamic Random Access Memory,DRAM)是内存的主要组成部分。由于其访问速度较慢,它并不能随时随地接收访问请求,送出数据的时机也不可预知。因此,为了保障数据传输的可靠性,需要做到以下五点:
- 确保读地址被存储器正确接收;
- 确保读数据能被处理器正确接收;
- 确保写地址被存储器正确接收;
- 确保写数据被存储器正确接收;
- 确保处理器能够得知写操作完成。
AXI4 总线协议正是对以上五点进行了规定。在一次读写请求中,AXI4 总线通过处理器和存储器之间的多次握手,保障了上述信号的正确传输,从而保障了数据传输的可靠性。
在本文档中,我们只会针对实验中涉及的信号进行解读,其他信号的解读请参考 AXI4 总线协议规范。
AXI4 总线特性
AXI4 总线具有以下特点:
- 高性能:AXI4 总线支持乱序传输,可以同时进行多个读写操作,从而提高了总线的利用率;
- 高带宽:AXI4 总线支持突发传输,可以在一次请求中传输多个数据,从而提高了总线的带宽;
- 高并行:AXI4 总线提供多个通道,可以实现读写的并行传输,从而提高了总线的并行度;
- 非对齐:AXI4 总线可以支持地址非对齐的传输。
AXI4 总线时序
握手
在 AXI4 总线协议中,读写请求的握手使用了基本的 valid-ready 握手信号。
在一次握手事务中,存在一个主方和一个从方。主方会主动地发送 valid 信号,并期待从方发送一个 ready 信号。而从方的 ready 信号可能不依赖与主方的 valid 信号,也可能依赖。对于“握手成功”的概念,在主方和从方的视角下,有不同的定义:
- 主方:自己发送了 valid 且收到了从方发出的 ready,即为“握手成功”;
- 从方:自己发送了 ready 且收到了主方发出的 valid,即为“握手成功”。
总线的“握手成功”,是主方和从方同时握手成功,只有一方视角的“握手成功”现象是不合法的。
握手并不是仅仅为了“看到某个信号”,握手通常是为了可靠地传递其他信息的。例如,当主方发送 valid 的时候,可能会同时将一些数据通过另一个信号发送给从方;而从方收到 valid 信号时,可能会先保存住主方发送的这个数据,然后再发送 ready 信号。这样,主方就可以通过 ready 信号来判断从方是否已经接收了数据。
读事务时序
AXI4 总线的读事务时序如下图所示:
AXI4 协议规定的一次读事务,需要一次地址握手和若干次数据握手,具体解读如下:
-
读地址握手:这是一次读事务的开端。处理器会向存储器发送本次读请求的地址,同时发送一个 arvalid 信号。同时,处理器还会发送本次读请求的一些配置信号,一些重要配置如下:
- arsize:本次读请求单个返回数据的宽度的对数,宽度以字节为单位。如果 arsize 为 nnn,则单次返回数据宽度为 2n2^n2n 字节;
- arlen:本次读请求需要连续读取的数据个数。如果 arlen 为 nnn,则本次读请求需要连续读取 n+1n+1n+1 个数据;
- arburst:本次突发读请求的模式,包括固定、递增、回绕三种模式,具体模式的含义我们将在下文阐述。
当存储器看到了处理器发送的 arvalid 信号后,会发送一个 arready 信号,表示已经接收到了处理器发送的地址和配置信号。至此,读地址握手完成,从下个周期开始,存储器将不定期地用 arburst 指定的模式发送由 arsize 和 arlen 规定的数据。
-
读数据握手:这是一次读事务的主体。存储器将会不定期地发送读取的数据,并同时发送一个 rvalid 信号,告知处理器本次发送的读数据是有效的。处理器得到数据和 rvalid 信号后,应当锁存住这个数据,并发送一个 rready 信号作为回应。一旦存储器看到了 rready 信号,就可以继续发送下一个数据了。
当存储器发送最后一个数据时,将会同时发送一个 rlast 信号,表示这是本次读事务的最后一个数据。处理器完成最后这个数据的读握手后,就可以认为本次读事务已经完成了。
写事务时序
AXI4 总线的写事务时序如下图所示:
AXI4 协议规定的一次写事务,需要一次地址握手、若干次数据握手和一次写回确认握手,具体解读如下:
-
写地址握手:这是一次写事务的开端。处理器会向存储器发送本次写请求的地址,同时发送一个 awvalid 信号。同时,处理器还会发送本次写请求的一些配置信号,一些重要配置如下:
- awsize:本次写请求单个写入数据的宽度的对数,单位为字节。如果 awsize 为 nnn,则单次写入数据宽度为 2n2^n2n 字节。
- awlen:本次写请求需要连续写入的数据个数。如果 awlen 为 nnn,则本次写请求需要连续写入 n+1n+1n+1 个数据。
- awburst:本次突发写请求的模式,包括固定、递增、回绕三种模式,具体模式的含义我们将在下文阐述。
当存储器看到了处理器发送的 awvalid 信号后,会发送一个 awready 信号,表示已经接收到了处理器发送的地址和配置信号。此时,写地址握手完成,从下个周期开始,存储器将不定期地用 awburst 模式接收由 awsize 和 awlen 规定的数据。
-
写数据握手:这是一次写事务的主体。处理器将发送 wvalid 信号,以告知存储器当前周期发送的数据是有效的,需要被写入。当存储器接收到这个数据后,将会应答一个 wready 信号,表示已经接收到了这个数据。处理器看到了 wready 信号后,就可以继续发送下一个数据了。
在每次发送写数据的时候,处理器还需要发送一个 wstrb 信号作为写数据的掩码。信号掩码的定义我们将在下文进行讲述。
当处理器发送最后一个数据时,还需要额外发送一个 wlast 信号,表示这是本次写事务的最后一个数据。存储器接收到了 wlast 信号,且本次写入数据握手完成后,就认为本次写事务已经完成了,将进入写回确认阶段。
-
写回确认握手:这是一次写事务的结尾。存储器将会发送 bvalid 信号,表示本次写事务已经完成。处理器接收到 bvalid 信号后,应当发送 bready 信号,表示已经接收到了存储器的写回确认。当存储器收到 bready 信号后,就可以认为本次写事务已经完成了。
AXI4 总线信号解读
1)全局信号
信号名 | AXI4 | AXI4-Lit |
ACLK | 全局时钟 | |
ARESETN | 全局复位,低有效。 |
2)写地址通道信号
信号名 | 源 | AXI4 | AXI4-Lit |
AWID | 主 | 写地址ID。这个信号用于写地址信号组的标记。 | 不支持 |
AWADDR | 主 | 写地址。 写地址给出突发数据传输的第一个传输地址。 | |
AWLEN | 主 | 突发长度。给出突发传输中准确的传输个数。支持INCR和WRAP传输模式。 突发长度=awlen+1 | 不支持 |
AWSIZE | 主 | 突发大小。 这个信号用于确定突发传输中每个传输的大小。 总线位宽=2^size Betyes | 不支持 |
AWBURST | 主 | 突发类型。该信息与突发大小信息一起,表示在突发过程中,地址如何应用于每个传输。支持INCR和WRAP传输模式。 | 不支持 |
AWLOCK | 主 | 锁类型。该信号提供了关于传输原子特性的额外信息(普通或互斥访问)。 | 不支持 |
AWCACHE | 主 | 缓存类型,建议值为0011。 | |
AWPROT | 主 | 保护类型,访问权限,建议值为000。 | |
AWQOS | 主 | QoS标识符,xilinx AXI4不支持。 | 不支持 |
AWREGION | 主 | 用于每个写操作的地址通道上的域标识符。通过该标识实现一个物理端口对应多个逻辑端口 | 不支持 |
AWUSER | 主 | xilinx AXI4不支持。 | 不支持 |
AWVALID | 主 | 写地址有效信号。为高指示地址有效。 | |
AWREADY | 从 | 写地址准备信号。为高表示从设备空闲,准备接收地址;为低表示从设备忙。 |
3)写数据通道信号
信号名 | 源 | AXI4 | AXI-Lite |
WDATA | 主 | 写数据,32位到1024位宽 | 只支持32位宽 |
WSTRB | 主 | 写字节选通,用于表示更新存储器的字节通道,对于数据总线的每8位数据有一位写选通信号。 | 从设备端可选择忽略。 |
WLAST | 主 | 写最后一个数据指示信号。表示突发传输中的最后一个数据。 | 不支持 |
WUSER | 主 | xilinx AXI4不支持。 | 不支持 |
WVALID | 主 | 写有效。为高指示数据有效。 | |
WREADY | 从 | 写准备。为高表示从设备空闲,准备接收数据;为低表示从设备忙。 |
4)写响应通道
信号名 | 源 | AXI4 | AXI-Lite |
BID | 从 | 响应ID。写响应识别标记,BID值必须匹配AWID值。 | 不支持 |
BRESP | 从 | 写响应。该信号表示写状态,可允许相应的表示为OKAY\EXOKAY\SLVERR\DECERR。 | EXOKAY状态不支持 |
BUSER | 从 | xilinx AXI4不支持。 | 不支持 |
BVALID | 从 | 写响应有效。为高指示响应数据有效。 | |
BREADY | 主 | 写响应准备。为高表示主设备空闲,准备接收写响应;为低表示主设备忙。 |
5)读地址通道
信号名 | 源 | AXI4 | AXI-Lite |
ARID | 主 | 读地址ID。这个信号用于读地址信号组的标记。 | 不支持 |
ARADDR | 主 | 读地址。读地址给出突发数据传输的第一个传输地址。 | |
ARLEN | 主 | 突发长度。给出突发传输中准确的传输个数。支持INCR和WRAP传输模式。 | 不支持 |
ARSIZE | 主 | 突发大小。这个信号用于确定突发传输中每个传输的大小。 | 不支持 |
ARBURST | 主 | 突发类型。该信息与突发大小信息一起,表示在突发过程中,地址如何应用于每个传输。支持INCR和WRAP传输模式。 | 不支持 |
ARLOCK | 主 | 锁类型。该信号提供了关于传输原子特性的额外信息(普通或互斥访问)。 | 不支持 |
ARCACHE | 主 | 缓存类型,建议值为0011。 | |
ARPROT | 主 | 保护类型,建议值为000。 | |
ARQOS | 主 | QoS标识符,xilinx AXI4不支持。 | 不支持 |
ARREGION | 主 | 用于每个读操作的地址通道上的域标识符。 | 不支持 |
ARUSER | 主 | xilinx AXI4不支持。 | 不支持 |
ARVALID | 主 | 读地址有效信号。为高指示地址有效。 | |
ARREADY | 从 | 读地址准备信号。为高表示从设备空闲,准备接收地址;为低表示从设备忙。 |
6)读数据通道
信号名 | 源 | AXI4 | AXI-Lite |
RID | 从 | 读ID标记,该信号是读数据信号组标记,由从设备产生RID,RID必须和读交易中的ARID匹配。 | 不支持 |
RDATA | 从 | 读数据。32位到1024位宽 | 只支持32位宽 |
RRESP | 从 | 读响应。该信号表示读状态,可允许相应的表示为OKAY\EXOKAY\SLVERR\DECERR。 | EXOKAY状态不支持 |
RLAST | 从 | 读最后一个数据指示信号。表示突发传输中的最后一个数据。 | 不支持 |
RUSER | 从 | xilinx AXI4不支持。 | 不支持 |
RVALID | 从 | 读有效。为高指示数据有效。 | |
RREADY | 主 | 读准备。为高表示主设备空闲,准备接收数据;为低表示主设备忙。 |
7)AXI4-Stream信号
信号名 | 源 | 默认值 | 功能 |
TVALID | No | N/A | Stream读写数据有效。为高指示数据有效。 |
TREADY | Yes | 1 | Stream读写读准备。为高表示对端设备空闲,准备接收数据;为低表示对端设备忙。 |
TDATA | Yes | 0 | Stream读写数据,8到4096位宽。 |
TSTRB | Yes | 同TKEEP,否则为1 | 字节选通信号。用于表示更新存储器的字节通道,对于数据总线的每8位数据有一位选通信号。 |
TKEEP | Yes | 1 | 字节选通信号。TKEEP未被确认的那些相关的字节是空字节,可以从数据流中去除。 |
TLAST | Yes | 0 | 表明包的边界。 |
TID | Yes | 0 | 数据流标识符。 |
TDEST | Yes | 0 | 数据流路由信息。 |
TUSER | Yes | 0 | 用户定义的边带信息,这些信息能伴随数据流进行发送。 |
信号约定
- AXI4 总线能够支持的单次最大传输位宽可以为 32、64、128 位,而最常用的一般是 32 位。在我们的实验中,我们将地址和数据位宽约定为 32 位;
- 表格中的“信号方向”是针对存储器而言的,即存储器的输入信号和输出信号。因此,CPU 的输出信号对应的是输入信号,而输入信号对应的是输出信号。
读地址信号(以 ar 开头)
信号名 | 信号方向 | 信号位宽 | 信号描述 |
---|---|---|---|
araddr | 输入 | 32 | 读地址,表示本次读事务的起始地址 |
arvalid | 输入 | 1 | 读地址有效,表示本次读事务的读地址和配置信号已经发送完毕,存储器可以开始读取数据 |
arready | 输出 | 1 | 读地址就绪,表示存储器已经接收到了本次读事务的读地址和配置信号 |
arsize | 输入 | 3 | 读数据宽度,表示本次读事务单个返回数据的宽度的对数,单位为字节 |
arlen | 输入 | 8 | 读数据个数,表示本次读事务需要连续读取的数据个数 - 1 |
arburst | 输入 | 2 | 读数据模式,表示本次读事务的突发模式 |
以上的信号都是在读地址握手阶段使用的信号,用于传递读地址和配置信息。
其中,arburst
信号的三种突发模式的含义如下:
- 固定地址(0b00):存储器将会连续返回若干个请求地址的数据,每个数据的地址都是相同的。
- 递增地址(0b01):存储器将会连续返回若干个递增的地址的数据,每个数据的地址都是上一个数据地址加上数据宽度。例如:若 arsize 为 2、arlen 为 3,那么存储器将会连续返回 4 个地址的数据,地址分别为 araddr, araddr+4, araddr+8, araddr+12。
- 回绕地址(0b10):存储器将会连续返回若干个递增的地址的数据,每个数据的地址都是上一个数据地址加上数据宽度。当地址达到一定边界后,将会从初始地址的 (arlen+1)×2arsize\small (arlen + 1) \times \large 2^{arsize}(arlen+1)×2arsize 字节对齐位置继续递增。例如:如果 arsize 为 2、arlen 为 3,且 araddr 为 0x000C,则对齐地址为 0x0000,存储器将会连续返回 4 个地址的数据,地址分别为 0x000C, 0x0000, 0x0004, 0x0008。
本课程实验使用递增地址
在本课程实验框架中,我们都采用递增地址的模式进行读写操作。
事实上,回绕地址的访问方式是为了配合 Cache “关键字优先”的技术,但如此一来会增加 Cache 的设计复杂度,不利于大家理解代码。
读数据信号(以 r
开头)
信号名 | 信号方向 | 信号位宽 | 信号描述 |
---|---|---|---|
rdata | 输出 | 32 | 读数据,表示存储器返回的数据 |
rvalid | 输出 | 1 | 读数据有效,表示存储器返回的数据和配置信号已经发送完毕,处理器可以开始读取数据 |
rready | 输入 | 1 | 读数据就绪,表示处理器已经接收到了存储器发送的读数据和配置信号 |
rlast | 输出 | 1 | 读数据结束,表示存储器返回的数据是本次读事务的最后一个数据 |
rresp | 输出 | 2 | 读响应,表示存储器返回的数据的状态,包括正常(0b00)、错误(0b01)、保留(0b10)、未知(0b11) |
写地址信号(以 aw 开头)
信号名 | 信号方向 | 信号位宽 | 信号描述 |
---|---|---|---|
awaddr | 输入 | 32 | 写地址,表示本次写事务的起始地址 |
awvalid | 输入 | 1 | 写地址有效,表示本次写事务的写地址和配置信号已经发送完毕,存储器可以开始写入数据 |
awready | 输出 | 1 | 写地址就绪,表示存储器已经接收到了本次写事务的写地址和配置信号 |
awsize | 输入 | 3 | 写数据宽度,表示本次写事务单个写入数据的宽度的对数,单位为字节 |
awlen | 输入 | 8 | 写数据个数,表示本次写事务需要连续写入的数据个数 - 1 |
awburst | 输入 | 2 | 写数据模式,表示本次写事务的突发模式 |
其中,awburst 的三种突发模式的含义与 arburst 相同,不再赘述。
写数据信号(以 w 开头)
信号名 | 信号方向 | 信号位宽 | 信号描述 |
---|---|---|---|
wdata | 输入 | 32 | 写数据,表示本次写事务需要写入的数据 |
wvalid | 输入 | 1 | 写数据有效,表示本次写事务的写数据已经发送完毕,存储器可以写入该数据 |
wready | 输出 | 1 | 写数据就绪,表示存储器已经接收到了本次写事务的写数据 |
wstrb | 输入 | 4 | 写数据掩码,表示本次写事务需要写入的数据的哪些字节是有效的 |
wlast | 输入 | 1 | 写数据结束,标识了当前写数据是本次写事务的最后一个数据 |
其中,wstrb 信号的每一位表示了对应字节是否有效,例如,如果 wstrb 为 0b0011,则表示本次发送的写数据的低两个字节是有效的,高两个字节是无效的且不会被写入。
一般来说,wstrb 只有 0b1111(写全字)、0b0011(写低半字)、0b1100(写高半字)、0b0001(写低字节)、0b0010(写次低字节)、0b0100(写次高字节)、0b1000(写高字节)、0b0000(不写)这几种情况,其余情况视为非法。
写回确认信号(以 b 开头)
信号名 | 信号方向 | 信号位宽 | 信号描述 |
---|---|---|---|
bvalid | 输出 | 1 | 写回确认有效,表示存储器已经完成了本次写事务 |
bready | 输入 | 1 | 写回确认就绪,表示处理器已经接收到了存储器的写回确认 |
bresp | 输出 | 2 | 写回响应,表示存储器完成本次写事务的状态,包括正常(0b00)、错误(0b01)、保留(0b10)、未知(0b11) |