第三章:AXI通道详解——五条通道的“分工协作”

各位同学,今天我们来聊聊AXI总线最核心的部分——那五条通道。说实话,我刚接触AXI时,看着这五条通道的名字就头大。读地址、读数据、写地址、写数据、写响应……感觉像五个兄弟各干各的。但等你真正在项目里调过几次时序,你就会发现,这五条通道的设计其实非常巧妙。

我个人习惯把AXI的通道比作一个“快递系统”。你想想看,发快递需要填地址单(地址通道),需要把包裹寄出去(数据通道),最后还要确认签收(响应通道)。AXI也是这个道理。只不过它把读和写分开了,这样就能同时进行读写操作,效率高了不少。

3.1 读地址通道(AR)——告诉从设备“我要什么”

读地址通道,说白了就是主设备告诉从设备:“嘿,我要读你某个地址的数据。”这个通道上传递的信号不多,但每个都很关键。

信号 宽度 说明
ARADDR 地址宽度 读操作的起始地址
ARLEN 8位 突发传输长度(实际传输次数 = ARLEN + 1)
ARSIZE 3位 每次传输的字节数(2^ARSIZE)
ARBURST 2位 突发类型:00=FIXED, 01=INCR, 10=WRAP
ARVALID 1位 主设备表示地址有效
ARREADY 1位 从设备表示可以接收地址

这里有个坑,我必须要提醒大家。ARLEN的值是“传输次数减1”。比如你想读4个数据,ARLEN要设成3。我在项目中遇到过一位同事,他直接把ARLEN设成了4,结果从设备多传了一个数据,整个系统就乱了。嗯,这种错误排查起来特别费劲。

注意:ARLEN = 传输次数 - 1。这是新手最容易犯的错误之一。

3.2 读数据通道(R)——从设备把数据送回来

读数据通道是从设备响应主设备的通道。主设备发完地址后,从设备就开始往回传数据。这个通道上除了数据本身,还有一个很重要的信号——RLAST。

RLAST信号会在最后一次数据传输时拉高。为什么需要这个信号?因为突发传输的长度是可变的,从设备需要告诉主设备:“这是最后一个数据了,别再等了。”我刚开始做AXI设计时,曾经忘记检查RLAST信号,结果主设备一直在等下一个数据,系统就卡死了。

核心要点:读数据通道的握手协议是RVALID和RREADY。主设备准备好接收数据时拉高RREADY,从设备有数据要发送时拉高RVALID。两者同时为高,数据就传输成功了。

3.3 写地址通道(AW)——告诉从设备“我要写哪里”

写地址通道和读地址通道非常相似,信号也差不多。AWADDR、AWLEN、AWSIZE、AWBURST……这些信号的含义和读地址通道完全一样。我建议你直接把读地址通道的信号名中的“AR”换成“AW”,就得到写地址通道的信号了。

不过有一点要注意:写地址通道和写数据通道是独立的。也就是说,主设备可以先发地址,再发数据;也可以先发数据,再发地址;甚至可以同时发。这种灵活性在实际设计中非常有用。

我的经验:在大多数设计中,我习惯先发地址再发数据。这样从设备可以提前准备好存储空间,减少等待时间。但如果你在做高性能设计,可以考虑让地址和数据同时发出,能节省一个时钟周期。

3.4 写数据通道(W)——把数据写进去

写数据通道是五条通道中唯一一个带“字节使能”的通道。WSTRB信号就是干这个用的。每个bit对应一个字节,1表示这个字节有效,0表示无效。

举个例子:你想写一个32位数据,但只想修改低16位。那么WSTRB就应该设为4'b0011。这样从设备就知道,只有低两个字节需要更新,高两个字节保持不变。

我曾经在一个项目中遇到过这样的问题:一个DMA控制器往内存写数据时,WSTRB信号一直设为全1。结果每次写操作都把整个32位覆盖了,导致其他数据被意外修改。排查了整整两天才发现是WSTRB的问题。从那以后,我每次设计都会特别检查WSTRB的生成逻辑。

// 写数据通道的典型时序
// 假设我们要写4个32位数据,地址从0x1000开始
// 时钟周期1: AWADDR = 0x1000, AWVALID = 1, AWREADY = 1
// 时钟周期2: WDATA = data0, WSTRB = 4'b1111, WVALID = 1, WREADY = 1
// 时钟周期3: WDATA = data1, WSTRB = 4'b1111, WVALID = 1, WREADY = 1
// 时钟周期4: WDATA = data2, WSTRB = 4'b1111, WVALID = 1, WREADY = 1
// 时钟周期5: WDATA = data3, WSTRB = 4'b1111, WVALID = 1, WLAST = 1, WREADY = 1

3.5 写响应通道(B)——确认写操作完成

写响应通道是五条通道中最简单的一条。它只有一个信号——BRESP,用来表示写操作的结果。BRESP只有两位,取值如下:

BRESP值 含义
00 OKAY:正常完成
01 EXOKAY:独占访问成功
10 SLVERR:从设备错误
11 DECERR:地址译码错误

你可能会问:“为什么读数据通道没有响应信号?”其实读数据通道的响应是通过RRESP信号来传递的,它和BRESP的编码方式完全一样。只不过读数据通道的响应是和数据一起传回来的,而写数据通道的响应是单独一个通道。

重要提醒:写响应通道的BVALID信号必须等到所有写数据都传输完成后才能拉高。也就是说,从设备必须收到WLAST信号后,才能发出写响应。这个顺序不能乱。

3.6 五条通道的“握手”机制

AXI的每条通道都使用独立的握手协议。VALID和READY信号就是用来握手的。VALID表示发送方有数据要发送,READY表示接收方可以接收数据。只有当VALID和READY同时为高时,数据才被传输。

这里有个小技巧:如果你想让接收方一直处于“准备好”状态,可以把READY信号固定拉高。但这样做有个风险——如果发送方还没准备好,VALID一直为低,那READY拉高也没用。我建议在大多数情况下,让READY信号在VALID为高后的下一个时钟周期再拉高,这样更稳妥。

好了,五条通道的基本内容就讲到这里。你想想看,AXI的设计其实很人性化——读和写分开,地址和数据分开,还有专门的响应通道。这种设计让总线可以同时处理多个事务,效率自然就高了。

我的建议:刚开始学习AXI时,不要急着看复杂的互联结构。先把这五条通道的握手时序搞明白。你可以用Vivado或者ModelSim写几个简单的测试用例,模拟一下读写操作。等你能熟练画出每条通道的时序图,AXI就算入门了。

AXI五条通道结构图 主设备 (Master) 从设备 (Slave) 读地址通道 (AR) ARADDR, ARLEN, ARSIZE, ARBURST 读数据通道 (R) RDATA, RRESP, RLAST 写地址通道 (AW) AWADDR, AWLEN, AWSIZE, AWBURST 写数据通道 (W) WDATA, WSTRB, WLAST 写响应通道 (B) BRESP 图例: 读通道(主→从或从→主) 写通道(主→从或从→主) 注:箭头方向表示数据传输方向,地址和写数据从主到从,读数据和写响应从从到主

这张图把五条通道的关系画得很清楚了。你看,读操作需要两条通道(AR和R),写操作需要三条通道(AW、W和B)。这就是为什么AXI能支持同时读写——因为读和写的通道是完全独立的。

最后再啰嗦一句:在实际项目中,你可能会遇到各种奇怪的时序问题。比如地址通道的握手超时、数据通道的乱序返回、写响应迟迟不来……这些问题的根源,往往就是对这五条通道的理解不够深入。把基础打牢,后面才能走得更远。

可可精品资料库