AXI-Lite 协议总结
AXI-Lite 协议总结
1. AXI-Lite 背景介绍
1.1 什么是 AXI-Lite
AXI-Lite(Advanced eXtensible Interface Lite)是 ARM AMBA(Advanced Microcontroller Bus Architecture)协议族中的一种简化版 AXI 协议。它是 AXI4 协议的精简版本,专为简单的外设寄存器访问而设计。
1.2 适用场景
- 寄存器映射外设:控制寄存器、状态寄存器的读写
- 低速、小数据量通信:不适合大块数据传输
- 简单的 Master-Slave 通信:一次只能传输一个数据字(32 位或 64 位)
- PS-PL 交互:Zynq 中 PS 端通过 AXI-Lite 访问 PL 端的寄存器接口
1.3 与 AXI4 的主要区别
| 特性 | AXI-Lite | AXI4 |
|---|---|---|
| 数据宽度 | 32 位或 64 位 | 32/64/128/256/512/1024 位 |
| 突发传输 | ❌ 不支持(每次只传输 1 个数据) | ✅ 支持(最多 256 次) |
| 事务 ID | ❌ 不支持 | ✅ 支持(用于乱序传输) |
| 复杂度 | 简单 | 复杂 |
| 资源消耗 | 低 | 高 |
1.4 项目中的应用
在本项目中,我们使用 AXI-Lite 协议实现 Zynq PS 端(ARM 处理器)与 PL 端(FPGA 逻辑)之间的寄存器通信:
- PS 端通过
M_AXI_GP0接口作为 Master - PL 端实现 AXI-Lite Slave 接口
- 实现 1024-bit 数据寄存器和标志位握手机制
2. AXI-Lite 信号说明
AXI-Lite 协议包含 5 个独立的通道,每个通道都有独立的握手机制:
2.1 全局信号
| 信号名 | 方向 | 说明 |
|---|---|---|
ACLK |
输入 | 全局时钟信号 |
ARESETN |
输入 | 全局复位信号(低电平有效,异步复位,同步释放) |
2.2 写地址通道(AW Channel)
| 信号名 | 方向(相对于 Slave) | 位宽 | 说明 |
|---|---|---|---|
S_AXI_AWADDR |
输入 | 32/64 | 写地址,指向要写入的寄存器地址 |
S_AXI_AWPROT |
输入 | 3 | 保护类型(访问权限,通常为 0) |
S_AXI_AWVALID |
输入 | 1 | Master 发出的写地址有效信号 |
S_AXI_AWREADY |
输出 | 1 | Slave 发出的写地址就绪信号 |
2.3 写数据通道(W Channel)
| 信号名 | 方向(相对于 Slave) | 位宽 | 说明 |
|---|---|---|---|
S_AXI_WDATA |
输入 | 32/64 | 写数据,要写入寄存器的数据 |
S_AXI_WSTRB |
输入 | 4/8 | 写数据选通信号(字节使能),指示哪些字节有效 |
S_AXI_WVALID |
输入 | 1 | Master 发出的写数据有效信号 |
S_AXI_WREADY |
输出 | 1 | Slave 发出的写数据就绪信号 |
2.4 写响应通道(B Channel)
| 信号名 | 方向(相对于 Slave) | 位宽 | 说明 |
|---|---|---|---|
S_AXI_BRESP |
输出 | 2 | 写响应状态: 00 = OKAY(正常) 01 = EXOKAY(独占访问) 10 = SLVERR(从设备错误) 11 = DECERR(解码错误) |
S_AXI_BVALID |
输出 | 1 | Slave 发出的写响应有效信号 |
S_AXI_BREADY |
输入 | 1 | Master 发出的写响应就绪信号 |
2.5 读地址通道(AR Channel)
| 信号名 | 方向(相对于 Slave) | 位宽 | 说明 |
|---|---|---|---|
S_AXI_ARADDR |
输入 | 32/64 | 读地址,指向要读取的寄存器地址 |
S_AXI_ARPROT |
输入 | 3 | 保护类型(访问权限,通常为 0) |
S_AXI_ARVALID |
输入 | 1 | Master 发出的读地址有效信号 |
S_AXI_ARREADY |
输出 | 1 | Slave 发出的读地址就绪信号 |
2.6 读数据通道(R Channel)
| 信号名 | 方向(相对于 Slave) | 位宽 | 说明 |
|---|---|---|---|
S_AXI_RDATA |
输出 | 32/64 | 读数据,从寄存器读取的数据 |
S_AXI_RRESP |
输出 | 2 | 读响应状态(与 BRESP 编码相同) |
S_AXI_RVALID |
输出 | 1 | Slave 发出的读数据有效信号 |
S_AXI_RREADY |
输入 | 1 | Master 发出的读数据就绪信号 |
3. AXI-Lite 握手规则
AXI-Lite 采用双向握手机制(VALID/READY 握手),每个通道都是独立的。
3.1 基本握手规则
对于每个通道,传输发生需要满足:
VALID && READY == 1 (在时钟上升沿采样)
重要规则:
- VALID 信号:由发送方(Master 或 Slave)控制,一旦置高,必须保持高直到握手完成
- READY 信号:由接收方控制,可以随时置高或置低(但建议保持稳定)
- 握手完成:当
VALID == 1且READY == 1时,在时钟上升沿完成传输 - 独立性:各通道之间可以独立握手,但写操作需要 AW、W、B 三个通道都完成
3.2 重要约束和规则
关于这一点,可以参考 Arm 的 AMBA 总线协议手册:AMBA AXI Protocol Specification ,里面提供了一个经典的依赖关系图(Dependencies between channel handshake signals):
信号都是高位有效,单头箭头指向的信号可以在箭头开头的信号之前或之后置位,双头箭头指向的信号必须在箭头开头的信号断言之后才置位。

- VALID 不能依赖 READY:发送方不能等待 READY 才置高 VALID,但可以等待 READY 才撤销 VALID
- READY 可以先于 VALID 置高:接收方可以提前置高 READY,等待 VALID
- 死锁避免:Slave 必须能够响应任意有效的地址和数据,即使返回错误响应。
- 地址对齐:32 位数据必须 4 字节对齐(地址低 2 位为 0),64 位数据必须 8 字节对齐(地址低 3 位为 0)
3.3 本项目中遇到的问题
错误现象:
- 写地址通道和写数据通道独立握手,导致可能只有其中一个通道完成握手
bvalid只检查了wready && wvalid,没有检查写地址通道是否完成- 如果 AW 通道未完成但 W 通道完成,
bvalid会错误地置高 - 导致 AXI 协议违反,Master 端卡死
正确做法:
awready和wready都应该等待对方通道也有效时才置高(或者都独立响应,但 B 通道必须等两者都完成)bvalid必须同时检查awready && awvalid和wready && wvalid都完成
4. 问题分析和解决
4.1 波形分析
抓取的波形都放在文件夹 doc/ila波形/20251221波形 里面。
错误波形如下,握手不正确,很明显 bvalid 只针对 wready 和 wvalid 做了回应,但是没有对 awready 和 awvalid 做回应。

正确的波形(经过修改)

read 读取波形正常(因为read相对简单,没有回复,所以后续说了,只放出波形)

之前的代码:
// write AXI Addr
always @(posedge ps_axi_clk or negedge ps_axi_rst_n ) begin
if (!ps_axi_rst_n) begin
ps_axi_awready <= 1'b0;
end else begin
if (~ps_axi_awready && ps_axi_awvalid) begin
ps_axi_awready <= 1'b1;
end else begin
ps_axi_awready <= 1'b0;
end
end
end
// write AXI data
always @(posedge ps_axi_clk or negedge ps_axi_rst_n) begin
if (!ps_axi_rst_n) begin
ps_axi_wready <= 1'b0;
end else begin
if (~ps_axi_wready && ps_axi_wvalid ) begin
ps_axi_wready <= 1'b1;
end
else begin
ps_axi_wready <= 1'b0;
end
end
end
// AXI write respone
always @(posedge ps_axi_clk or negedge ps_axi_rst_n) begin
if (!ps_axi_rst_n) begin
ps_axi_bvalid <= 1'b0;
ps_axi_bresp <= 2'b0;
end else begin
if ( ps_axi_wready && ps_axi_wvalid && ~ps_axi_bvalid ) begin// 写地址,写数据都正确传输
ps_axi_bvalid <= 1'b1;
ps_axi_bresp <= 2'b0; // OKAY
end
if (ps_axi_bready && ps_axi_bvalid ) begin
ps_axi_bvalid <= 1'b0;
end
end
end
更新的代码:
// write AXI Addr
always @(posedge ps_axi_clk or negedge ps_axi_rst_n ) begin
if (!ps_axi_rst_n) begin
ps_axi_awready <= 1'b0;
end else begin
if (~ps_axi_awready && ps_axi_awvalid && ps_axi_wvalid) begin // modify!!!
ps_axi_awready <= 1'b1;
end else begin
ps_axi_awready <= 1'b0;
end
end
end
// write AXI data
always @(posedge ps_axi_clk or negedge ps_axi_rst_n) begin
if (!ps_axi_rst_n) begin
ps_axi_wready <= 1'b0;
end else begin
if (~ps_axi_wready && ps_axi_wvalid && ps_axi_awvalid ) begin // modify!!!
ps_axi_wready <= 1'b1;
end
else begin
ps_axi_wready <= 1'b0;
end
end
end
always @(posedge ps_axi_clk or negedge ps_axi_rst_n) begin
if (!ps_axi_rst_n) begin
ps_axi_bvalid <= 1'b0;
ps_axi_bresp <= 2'b0;
end else begin
if ( ps_axi_awready && ps_axi_awvalid && ps_axi_wready && ps_axi_wvalid && ~ps_axi_bvalid ) begin// 写地址,写数据都正确传输
ps_axi_bvalid <= 1'b1;
ps_axi_bresp <= 2'b00; // OKAY
end
else if( ps_axi_wready && ps_axi_wvalid && ~ps_axi_bvalid ) begin
ps_axi_bvalid <= 1'b1;
ps_axi_bresp <= 2'b10; // SLVERR, in case of deadlock
end
else if( ps_axi_awready && ps_axi_awvalid && ~ps_axi_bvalid ) begin
ps_axi_bvalid <= 1'b1;
ps_axi_bresp <= 2'b10; // SLVERR, in case of deadlock
end
if (ps_axi_bready && ps_axi_bvalid ) begin
ps_axi_bvalid <= 1'b0;
ps_axi_bresp <= 2'b00;
end
end
end
4.2 代码对比
错误代码的关键问题
-
写地址通道(AW)和写数据通道(W)独立握手
// AW 通道只检查 awvalid if (~ps_axi_awready && ps_axi_awvalid) begin ps_axi_awready <= 1'b1; end // W 通道只检查 wvalid if (~ps_axi_wready && ps_axi_wvalid) begin ps_axi_wready <= 1'b1; end问题:两个通道可能不同时完成握手,导致后续逻辑错误
-
写响应通道(B)只检查写数据通道
// 只检查 wready && wvalid,没有检查 awready && awvalid if (ps_axi_wready && ps_axi_wvalid && ~ps_axi_bvalid) begin ps_axi_bvalid <= 1'b1; end问题:如果 AW 通道未完成但 W 通道完成,会错误地发送写响应
正确代码的关键修改
-
AW 和 W 通道等待对方也有效
// AW 通道等待 W 通道也有效 if (~ps_axi_awready && ps_axi_awvalid && ps_axi_wvalid) begin ps_axi_awready <= 1'b1; end // W 通道等待 AW 通道也有效 if (~ps_axi_wready && ps_axi_wvalid && ps_axi_awvalid) begin ps_axi_wready <= 1'b1; end效果:确保两个通道基本同时完成握手
-
B 通道检查两个通道都完成
// 必须两个通道都完成才发送响应 if (ps_axi_awready && ps_axi_awvalid && ps_axi_wready && ps_axi_wvalid && ~ps_axi_bvalid) begin ps_axi_bvalid <= 1'b1; ps_axi_bresp <= 2'b00; // OKAY end效果:确保写事务完整完成后才响应
-
添加错误处理(防止死锁)
// 如果只有一个通道完成,返回错误响应(防止死锁) else if(ps_axi_wready && ps_axi_wvalid && ~ps_axi_bvalid) begin ps_axi_bvalid <= 1'b1; ps_axi_bresp <= 2'b10; // SLVERR end效果:即使出现异常情况也能响应,避免 Master 永久等待
5. 总结
5.1 实现成果
今天实现了 PS 端和 PL 端基于寄存器的交互,基于 PS-PL 使用了 AXI-Lite 协议。
5.2 遇到的问题及解决过程
-
问题发现:
- 程序在
Xil_Out函数调用时崩溃 - 经过调试发现不是立即崩溃,而是循环几次之后才崩溃
- 怀疑是握手交互不对导致程序卡死
- 程序在
-
问题分析:
- 通过查看 AXI AMBA 总线协议手册,了解握手规则
- 初步检查代码逻辑,看似没有问题
- 使用 ILA 抓包,发现了错误的波形
- 发现对 AXI-Lite 握手规则理解不够深入
-
问题根源:
- 写地址通道(AW)和写数据通道(W)独立握手,没有同步
- 写响应通道(B)只检查了写数据通道,没有检查写地址通道
- 导致协议违反,Master 端等待超时
-
解决方案:
- 修改 AW 和 W 通道的握手逻辑,要求对方通道也有效
- 修改 B 通道响应逻辑,确保两个通道都完成
- 添加错误处理机制,防止死锁
5.3 关键经验教训
- 理解协议细节很重要:AXI-Lite 的握手规则看似简单,但实现时容易忽略细节
- 调试工具很重要:ILA 抓包是发现时序问题的关键工具
- 错误处理很重要:即使出现异常情况,也应该能够响应,避免死锁
- 代码审查很重要:看似合理的代码可能违反协议规范
5.4 参考资料
- ARM AMBA AXI Protocol Specification (ARM IHI 0022)
- Xilinx AXI Reference Guide (UG761)
- Vivado Design Suite User Guide (UG910)