3. AXI4-Lite握手协议:VALID/READY握手机制、握手时序图分析、依赖关系与死锁避免
大家好,我是你们的FPGA讲师。今天我们来聊聊AXI4-Lite最核心的东西——握手协议。
说实话,我刚开始学AXI总线时,最头疼的就是这个握手。一堆信号,什么VALID、READY,还有各种依赖关系。但后来我发现,只要搞懂了握手,AXI总线你就掌握了八成。
3.1 VALID/READY握手机制
AXI4-Lite的握手,说白了就是两个信号在跳舞:
- VALID:发送方说“我准备好了,数据有效”
- READY:接收方说“我准备好了,可以接收”
只有当两个信号同时为高时,数据才真正传输成功。这个机制,我称之为“双向确认”。
核心原则:VALID和READY同时为高,数据在时钟上升沿被采样。
我个人习惯把握手分成三种情况来看:
- VALID先有效,READY后有效——发送方先准备好,等接收方
- READY先有效,VALID后有效——接收方先准备好,等发送方
- 两者同时有效——一拍搞定,最理想的情况
3.2 握手时序图分析
咱们来看一个典型的握手过程。我用SVG画了一张时序图,方便大家理解。
嗯,这张图很关键。你看T3时刻,VALID和READY同时为高,数据就在这个时钟上升沿被成功传输了。
我在项目中遇到过一种情况:设计人员只考虑了VALID,没考虑READY,结果数据一直发不出去。你想想看,接收方还没准备好,你发数据有什么用?
3.3 依赖关系分析
AXI4-Lite有五个独立通道,每个通道都有自己的握手。但通道之间是有依赖关系的。我总结了一张表:
| 依赖关系 | 说明 | 我的经验 |
|---|---|---|
| 写地址 → 写数据 | 写地址通道必须先于写数据通道完成握手 | 曾经有个项目,地址和数据同时发,结果地址没到数据先到了,总线直接挂死 |
| 写数据 → 写响应 | 写响应必须在写数据完成后才能发出 | 这个顺序搞反了,从设备会报错 |
| 读地址 → 读数据 | 读地址必须先完成,从设备才知道读哪个地址 | 这个比较好理解,你总得先告诉别人你要什么 |
⚠️ 重要提醒:依赖关系不是的时序要求,而是协议层面的逻辑依赖。硬件上可以同时发起,但数据必须按顺序到达。
3.4 死锁避免
死锁,说白了就是双方都在等对方,结果谁都不动。这在AXI总线里是个大坑。
我曾经在一个项目中,主设备把VALID拉高后,就一直等READY。而从设备呢,它要先等某个内部信号才拉READY。结果那个内部信号又依赖于主设备的另一个操作...死锁了。
避免死锁,我有几个建议:
- 不要让VALID依赖READY——发送方应该独立拉高VALID,不要等接收方
- READY可以依赖VALID——接收方看到VALID再拉READY,这是允许的
- 超时机制——如果长时间没握手成功,强制复位
- 避免循环依赖——通道之间的依赖关系不能形成环
💡 小技巧:我习惯在设计中加一个看门狗定时器。如果某个通道超过1024个时钟周期还没完成握手,就触发中断。这样即使有死锁,也能及时发现。
3.5 代码示例:握手实现
来看一个简单的写地址通道握手实现:
// AXI4-Lite 写地址通道握手
// 主设备侧实现
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
awvalid <= 1'b0;
awaddr <= 32'b0;
end else begin
// 如果握手成功,准备下一笔传输
if (awvalid && awready) begin
awvalid <= 1'b0; // 握手成功,拉低VALID
// 可以在这里更新地址
end
// 如果有新的传输请求,拉高VALID
else if (new_transfer_req) begin
awvalid <= 1'b1;
awaddr <= new_addr;
end
end
end
这段代码的核心逻辑是:VALID一旦拉高,就保持到握手成功。不要自己偷偷拉低,否则从设备会懵的。
3.6 握手时序的三种情况
最后,我用一个流程图来总结握手的三种情况:
你看,不管哪种情况,最终结果都一样——数据在VALID和READY同时为高的那个时钟上升沿传输成功。
好了,关于AXI4-Lite的握手协议,今天就讲到这里。记住:VALID和READY是双向确认,依赖关系要理清,死锁要提前预防。这些都是我踩过的坑,希望你们能避开。
课后思考:如果你设计一个从设备,READY信号应该怎么产生?是组合逻辑直接输出,还是寄存器打一拍?这两种方式各有什么优缺点?
可可精品资料库