4. AXI写事务

写事务在AXI协议里,说白了就是三拨人干一件事。AW通道负责告诉从设备“我要往哪写”,W通道负责把数据送过去,B通道则回来告诉你“写完了,结果如何”。

我刚开始接触AXI时,总觉得这三个通道各干各的,时序上好像很复杂。后来调了几个模块才明白——它们其实是流水线作业,配合好了效率极高。

4.1 AW通道:写地址与控制信息

AW通道传输的是写事务的“头”。它包括目标地址、突发类型、数据长度等信息。我习惯把AW通道看作“快递单”——你得先告诉对方包裹要送到哪。

信号 含义 我踩过的坑
AWADDR 写地址 地址对齐问题,后面细说
AWLEN 突发长度(实际为AWLEN+1) 很多人忘了加1
AWSIZE 每拍数据字节数 别超过数据总线宽度
AWBURST 突发类型(FIXED/INCR/WRAP) WRAP的地址边界要算清楚

这里有个关键点:AWVALID和AWREADY的握手。我曾经在项目中遇到一个从设备,它的AWREADY只在特定条件下拉高,结果主设备一直等,整个总线卡死。嗯,握手协议一定要仔细检查。

4.2 W通道:写数据与字节使能

W通道负责把数据一拍拍地送过去。每拍数据都带着WSTRB信号,用来指示哪些字节是有效的。

核心要点:WLAST信号必须在最后一拍数据时拉高。少了它,从设备不知道什么时候结束。

我记得有一次调试,从设备一直不返回BVALID。查了半天,发现是WLAST没拉高。从设备傻傻地等着下一拍数据,结果就死锁了。

W通道还有一个容易忽略的地方——数据对齐。举个例子:

// 假设数据总线64位,每次传输8字节
// 地址0x1004,WSTRB应该为0xF0(高4字节有效)
// 地址0x1008,WSTRB应该为0xFF(全部有效)

// 错误写法(我见过有人这么干):
assign wstrb = 8'hFF;  // 不管地址,全部使能
// 正确做法:
assign wstrb = (addr[2:0] == 3'h0) ? 8'hFF :
               (addr[2:0] == 3'h4) ? 8'hF0 : ...

4.3 B通道:写响应机制

B通道是写事务的“回执”。从设备处理完所有写数据后,通过B通道返回响应状态。

BRESP只有两种常用值:

  • OKAY(00):正常完成
  • SLVERR(10):从设备错误(比如地址越界)
  • DECERR(11):译码错误(地址没人管)

注意:BRESP必须在BVALID和BREADY同时有效时才能变化。我曾经见过一个设计,BVALID拉低后BRESP还保持SLVERR,结果下一个事务误判为错误。

4.4 写数据交织

AXI允许不同事务的W数据交织发送。什么意思呢?就是你可以先发事务A的地址,再发事务B的地址,然后先送事务B的数据,再送事务A的数据。

为什么会这样?说白了就是为了提高总线利用率。比如事务A需要从内存读数据才能继续写,而事务B的数据已经准备好了,那就先让B走。

但交织也带来了麻烦:

  • 从设备必须能区分数据属于哪个事务
  • WID信号(在AXI3中)用于标识事务ID
  • AXI4去掉了WID,要求W数据必须按顺序发送

我个人建议:除非你非常清楚自己在做什么,否则别用交织。我在一个项目中尝试过交织,结果从设备的缓存管理变得极其复杂,最后不得不改回顺序发送。

4.5 完整写事务时序示例

下面是一个典型的4拍突发写事务时序:

// 时钟周期1:AW通道握手
AWVALID = 1, AWADDR = 0x1000, AWLEN = 3
// 时钟周期2:AWREADY拉高,地址被接收
// 同时W通道开始发送第一拍数据
WVALID = 1, WDATA = d0, WSTRB = 0xFF
// 时钟周期3:WREADY拉高,数据被接收
WVALID = 1, WDATA = d1, WSTRB = 0xFF
// 时钟周期4:继续发送
WVALID = 1, WDATA = d2, WSTRB = 0xFF
// 时钟周期5:最后一拍,WLAST拉高
WVALID = 1, WDATA = d3, WSTRB = 0xFF, WLAST = 1
// 时钟周期6:B通道返回响应
BVALID = 1, BRESP = OKAY

小技巧:调试时可以用波形查看WLAST和BVALID的关系。如果WLAST之后很久BVALID才来,说明从设备处理速度慢。如果BVALID一直不来,大概率是握手卡住了。

4.6 知识体系结构图

AXI写事务知识体系 AW通道 写地址与控制 W通道 写数据与字节使能 B通道 写响应 地址决定数据顺序 WLAST触发B响应 AW通道关键点 • 地址对齐 • 突发长度计算 • 握手协议 W通道关键点 • WSTRB字节使能 • WLAST标记 • 数据交织 B通道关键点 • 响应码含义 • 响应时序 • 错误处理 核心原则:AW先发 → W数据流 → B响应 三个通道独立握手,但逻辑上严格依赖

4.7 避坑指南

我总结几个写事务中容易出问题的地方:

  1. 地址未对齐:比如64位总线,地址却是0x1002。这时候WSTRB要正确配置,否则数据会错位。
  2. WLAST丢失:从设备收不到WLAST,会一直等数据,B通道永远不会响应。
  3. BRESP误判:有些从设备在正常操作时也会返回SLVERR,比如写到了只读区域。一定要检查地址映射。
  4. 交织混乱:AXI4不支持WID,如果多个事务交织,数据会混在一起。我建议用AXI4时保持W数据顺序发送。

一句话总结:写事务就是“先告诉地址,再送数据,最后等回执”。三个通道各司其职,但时序上要配合好。调试时盯着WLAST和BVALID,这两个信号最容易出问题。

嗯,写事务的内容就这些。实际项目中,你可能会遇到各种奇怪的时序问题,但万变不离其宗——把AW、W、B三个通道的握手逻辑理清楚,大部分问题都能解决。