AXI 常见问题详解
AXI协议核心问题深度解析
AXI 常见问题详解
问题 1:AXI 和 AHB 的区别在哪里,为什么 AXI 相比 AHB 有明显的性能优势?
架构差异
AHB 架构(共享总线):
Master 0 ──┐
Master 1 ──┼──→ 仲裁器 ──→ 共享总线 ──→ Slave
Master 2 ──┘
问题:同时只能有一个 Master 访问一个 Slave
AXI 架构(独立通道):
Master ──→ ┌─────────────────────────────────────────┐
│ AW (写地址) ←→ Slave 0 │
│ W (写数据) ←→ Slave 1 │
│ B (写响应) ←→ Slave 2 │
│ AR (读地址) ←→ Slave 3 │
│ R (读数据) ←→ Slave 4 │
└─────────────────────────────────────────┘
优势:5 个通道完全独立,可同时工作
关键差异详解
| 特性 | AHB | AXI | 性能影响 |
|---|---|---|---|
| 通道数量 | 1条共享总线 | 5个独立通道 | AXI可并行读写 |
| 流水线 | 无(地址/数据串行) | 有(地址/数据重叠) | AXI提高利用率 |
| Outstanding | 不支持 | 支持 | AXI隐藏延迟 |
| 乱序完成 | 不支持 | 通过ID支持 | AXI提高吞吐 |
| 突发长度 | 最大16拍 | 最大256拍(INCR) | AXI减少地址开销 |
Outstanding 机制详解
AHB(无 Outstanding):
时钟: T0 T1 T2 T3 T4 T5 T6 T7 T8
│ │ │ │ │ │ │ │ │
Master: A0 ─ ─ A1 ─ ─ A2 ─ ─
│ │ │
▼ ▼ ▼
Slave: ─ ─ D0 ─ ─ D1 ─ ─ D2
总延迟 = 3笔 × 3周期 = 9 周期
AXI(有 Outstanding,深度=4):
时钟: T0 T1 T2 T3 T4 T5 T6 T7 T8
│ │ │ │ │ │ │ │ │
Master: A0 A1 A2 A3 ─ ─ ─ ─ ─
│ │ │ │
▼ ▼ ▼ ▼
Slave: ─ ─ ─ ─ D0 D1 D2 D3 ─
总延迟 = 4 + 4 = 8 周期(节省 50%)
核心原理:主设备发送地址后,不必等待数据响应即可发送下一个地址,这种”流水线”方式可以隐藏从设备的访问延迟。
问题 2:AXI3 和 AXI4 的区别在哪里?
主要差异总结
| 特性 | AXI3 | AXI4 | 影响 |
|---|---|---|---|
| 写交织 | 允许 | 禁止 | AXI4简化互联设计 |
| INCR突发长度 | 最大16拍 | 最大256拍 | AXI4提高DDR效率 |
| 写数据先于写地址 | 允许 | 禁止 | AXI4去掉Buffer,节省面积 |
| LOCK信号 | 2bit | 1bit | AXI4简化锁机制 |
| QoS/Region | 无 | 有 | AXI4增加流量控制 |
写交织(Write Interleaving)详解
AXI3 允许写交织:
Transaction A: W_A0 → W_A1 → W_A2
Transaction B: W_B0 → W_B1
正确(交织):
W_A0 → W_B0 → W_A1 → W_B1 → W_A2
(A 和 B 的数据拍可以交错)
AXI4 禁止写交织:
Transaction A: W_A0 → W_A1 → W_A2
Transaction B: W_B0 → W_B1
正确:
W_A0 → W_A1 → W_A2 → W_B0 → W_B1
(A 的所有拍先发完,再发 B)
错误:
W_A0 → W_B0 → W_A1 → W_B1 → W_A2
(交织违反协议)
为什么 AXI4 禁止写交织?
- 互联需要为每个事务的写数据开辟 Buffer
- 禁止后可以去掉这些 Buffer,节省面积
- 简化互联设计复杂度
突发长度扩展
AXI3 INCR 突发:awlen[3:0] = 0-15,最多 16 拍
AXI4 INCR 突发:awlen[7:0] = 0-255,最多 256 拍
应用场景:
- DDR 控制器:需要长突发提高效率
- AXI3:需要多次发送地址才能传输 256 拍数据
- AXI4:一次地址即可传输 256 拍数据
问题 3:Exclusive 访问是什么?它的实现机制是什么?相比于 Lock Access 的优势是什么?
Lock Access 的问题
Lock Access 流程:
1. 主设备发送 LOCK=1,锁定总线
2. 主设备进行读-修改-写操作
3. 操作完成后,主设备发送 LOCK=0,释放总线
问题:
- 锁定期间,其他主设备无法访问任何从设备
- 可能导致优先级反转(低优先级主设备锁定总线,高优先级主设备被阻塞)
- 系统整体吞吐量下降
Exclusive 访问机制
Exclusive 访问流程:
1. 主设备发送 Exclusive 读请求
AW/AR: LOCK=1, 打算进行原子操作
2. 互联记录该地址被主设备 M0 独占
互联内部:M0 拥有 addr=0x100 的独占权
3. 主设备进行修改(在本地缓存中修改)
4. 主设备发送 Exclusive 写请求
AW: LOCK=1, 写 addr=0x100
5. 互联检查该地址是否被其他主设备修改:
- 未修改:写成功,返回 OKAY
- 已修改:写失败,返回 EXOKAY(Exclusive OKAY)
互联监控逻辑
// Exclusive 访问监控简化逻辑
module exclusive_monitor (
input logic clk,
input logic rst_n,
input logic arvalid,
input logic [31:0] araddr,
input logic [3:0] arid,
input logic awvalid,
input logic [31:0] awaddr,
input logic [3:0] awid,
output logic exclusive_ok // Exclusive 写是否成功
);
// 记录每个地址的独占主设备
typedef struct {
logic [31:0] addr;
logic [3:0] owner_id;
logic valid;
} exclusive_entry_t;
exclusive_entry_t entries[16];
// Exclusive 读:记录独占权
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
for (int i = 0; i < 16; i++)
entries[i].valid <= 1'b0;
end else if (arvalid && arid == 4'h0) begin // 假设 M0 发起
// 找到空闲表项,记录独占权
for (int i = 0; i < 16; i++) begin
if (!entries[i].valid) begin
entries[i].addr <= araddr;
entries[i].owner_id <= arid;
entries[i].valid <= 1'b1;
break;
end
end
end
end
// Exclusive 写:检查是否被其他主设备修改
always_comb begin
exclusive_ok = 1'b0;
if (awvalid) begin
for (int i = 0; i < 16; i++) begin
if (entries[i].valid &&
entries[i].addr == awaddr &&
entries[i].owner_id == awid) begin
exclusive_ok = 1'b1; // 未被修改,写成功
end
end
end
end
endmodule
Lock vs Exclusive 对比
| 特性 | Lock Access | Exclusive Access |
|---|---|---|
| 总线锁定 | 是 | 否 |
| 其他主设备访问 | 完全阻塞 | 可访问其他地址 |
| 优先级反转 | 可能 | 不会 |
| 系统吞吐 | 降低 | 保持 |
| 实现复杂度 | 简单 | 较高 |
问题 4:AXI 的 Outstanding 数量如何计算?
影响因素
Outstanding 数量 = min(
主设备缓冲深度, // 主设备能缓存多少未完成事务
互联支持的最大深度, // 互联能路由多少并发事务
从设备可处理的队列长度 // 从设备能接受多少并发请求
)
典型配置
| 从设备类型 | 典型 Outstanding | 原因 |
|---|---|---|
| DDR 控制器 | 4-8 | DDR 流水线较深,需要较深队列 |
| SRAM | 2-4 | SRAM 响应快,队列可较浅 |
| APB 外设 | 1 | APB 每次只处理一个事务 |
| 高速缓存 | 8-16 | 缓存命中率高,需要深队列 |
Outstanding 深度与性能关系
性能 vs Outstanding 深度:
性能
↑
│ ┌───────────────── 深度=16
│ /
│ /
│ / ┌─────────────── 深度=8
│ / /
│ / /
│ / / ┌───────────── 深度=4
│ / / /
│/ / /
└───┴───┴──────────────→ 从设备延迟
从设备延迟越大,需要越深的 Outstanding 才能隐藏延迟
面积与性能权衡
深度=1:无流水,每笔事务独立完成
优点:无乱序风险,面积最小
缺点:延迟大
深度=2-4:可流水 2-4 笔事务
优点:适合中速外设,面积适中
缺点:性能提升有限
深度=8+:深度流水
优点:最大化带宽利用率
缺点:面积和功耗代价大
问题 5:Burst 中的 WRAP 类型,如何计算上下界地址?
WRAP 地址计算公式
突发总字节数 = burst_size × (burst_len + 1)
下界 = (起始地址 / 突发总字节数) × 突发总字节数
上界 = 下界 + 突发总字节数
地址行为:
从起始地址开始,每次递增 burst_size
当地址达到上界时,回绕到下界
详细示例
参数:awaddr=0x04, awsize=2(4字节), awlen=3(4拍), awburst=WRAP
步骤 1:计算突发总字节数
burst_bytes = 4 × (3+1) = 16 字节
步骤 2:计算下界
下界 = (0x04 / 16) × 16 = 0x00
步骤 3:计算上界
上界 = 0x00 + 16 = 0x10
步骤 4:计算地址序列
拍 0:0x04 (起始地址)
拍 1:0x04 + 4 = 0x08
拍 2:0x08 + 4 = 0x0C
拍 3:0x0C + 4 = 0x10 (达到上界,回绕)
→ 回绕到下界 0x00
拍 4:0x00 + 4 = 0x04 (回到起始)
地址序列:0x04 → 0x08 → 0x0C → 0x00
WRAP 的应用场景
缓存行填充(Cache Line Fill):
场景:CPU 请求地址 0x04,但缓存行大小为 16 字节
目标:填充整个 0x00-0x0F 范围
如果用 INCR:
0x04 → 0x08 → 0x0C → 0x10 (超出缓存行)
用 WRAP:
0x04 → 0x08 → 0x0C → 0x00 (正确填充)
问题 6:AXI 哪些情况可能出现死锁,如何避免此问题?
死锁场景 1:valid/ready 违反
场景:valid 提前撤销
Master: AWVALID ────1────────0──────────
(valid 在 ready 之前撤销)
Slave: AWREADY ───────────────1────────
问题:Slave 在 T2 采样到 AWVALID=0,认为事务未开始
但 Master 认为事务已完成
→ 状态不一致,可能死锁
避免:严格遵守 valid/ready 协议
valid=1 后必须保持到 ready=1
死锁场景 2:循环依赖
场景:读写通道循环等待
Master 等待:AR 通道响应
Slave 等待:W 通道数据
但 Master 因为缓冲满,无法发送 W
形成死锁:Master ↔ Slave 互相等待
避免:
- 合理分配 ID,避免资源耗尽
- 设置合理的超时机制
死锁场景 3:从设备长时间阻塞
场景:从设备不响应
Master: AR_VALID=1, 等待 R_VALID
Slave: 因为内部状态机卡住,不发送 R_VALID
如果没有超时,Master 会永远等待
避免:
- 实现看门狗定时器
- 检测超时并重置事务
死锁预防策略
| 策略 | 说明 | 实现方式 |
|---|---|---|
| 协议遵守 | 严格遵守 valid/ready | 协议检查断言 |
| 超时机制 | 检测长时间阻塞 | 看门狗定时器 |
| 资源管理 | 避免资源耗尽 | ID 分配策略 |
| 死锁检测 | 主动检测死锁 | 状态机监控 |
问题 7:AXI Stream 中如何进行反压?
反压机制
AXI Stream 通过 TREADY/TVALID 握手实现反压:
发送端:
- 当 TREADY=0 时,必须保持 TVALID=1 和所有数据信号
- 不能撤销 TVALID 或改变数据
接收端:
- 通过 TREADY 控制流量
- 当无法处理数据时,拉低 TREADY
反压时序示例
正常传输(无反压):
CLK ──┐ ┌──┐ ┌──┐ ┌──┐ ┌──
└──┘ └──┘ └──┘ └──┘
TVALID ──────1─────1─────1─────0────
TREADY ──────1─────1─────1─────1────
TDATA ──── D0 ──── D1 ──── D2 ────
每个周期都传输数据
反压场景(接收端忙):
CLK ──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌──
└──┘ └──┘ └──┘ └──┘ └──┘ └──┘
TVALID ──────1─────1─────1─────1─────1─────0────
TREADY ──────1─────0─────0─────1─────1─────1────
TDATA ──── D0 ──── D1 ──── D1 ──── D2 ──── D2 ────
│ │ │
│ └──────┴────── 反压期间数据保持不变
└────── 第一个传输完成
反压期间的信号要求
规则:
1. TVALID=1 且 TREADY=0 时,TDATA/TSTRB/TKEEP 必须保持稳定
2. 不能撤销 TVALID(除非复位)
3. 接收端可以在任意时刻拉低 TREADY
违规示例:
TVALID ────1────0────1──── ← 违规!TVALID 被撤销
TREADY ──────0────0────1────
TDATA ──── D0 ──── D1 ────
问题 8:AXI 中各个 Channel 之间的依赖关系是什么?
通道依赖图
读通道依赖关系:
AR (读地址) ─────→ R (读数据)
│ │
└────────────────┘
(无其他依赖)
读操作:Master 发送 AR → Slave 返回 R
AR 和 R 之间是简单的请求-响应关系
写通道依赖关系:
AW (写地址) ──┐
│
W (写数据) ─┼──→ B (写响应)
│
└─────
写操作:Master 发送 AW 和 W → Slave 返回 B
AW 和 W 可以并行(AXI4 中 W 必须在 AW 之后)
B 必须在 AW 和 W 都完成后才能返回
关键依赖规则
| 依赖 | 说明 | 原因 |
|---|---|---|
| AR → R | R 依赖 AR | 必须先知道读地址,才能返回数据 |
| AW + W → B | B 依赖 AW 和 W | 必须完成写地址和写数据,才能返回响应 |
| AR ∥ AW | 读写地址可并行 | 读写通道完全独立 |
| AR ∥ W | 读地址和写数据可并行 | 读写通道完全独立 |
并行性优势
AXI 可以同时进行读写:
时钟: T0 T1 T2 T3 T4 T5
│ │ │ │ │ │
AW: A0 ─ ─ ─ ─ ─
W: ─ D0 ─ ─ ─ ─
B: ─ ─ ─ R0 ─ ─
AR: ─ A1 ─ ─ ─ ─
R: ─ ─ ─ ─ D1 ─
写操作和读操作同时进行,提高带宽利用率
问题 9:如何计算 AXI 最大传输带宽?
理论带宽计算
理论带宽 = 数据位宽 × 时钟频率
示例:
- 32位 AXI4, 200MHz: 32 × 200MHz = 6.4 Gbps
- 64位 AXI4, 500MHz: 64 × 500MHz = 32 Gbps
- 128位 AXI4, 400MHz: 128 × 400MHz = 51.2 Gbps
实际带宽计算
实际带宽 = 理论带宽 × 效率因子
效率因子考虑:
1. 握手开销(valid/ready 延迟)
2. Outstanding 深度
3. 突发长度
4. 地址阶段开销
效率因子估算
效率因子 = (数据传输周期) / (总周期)
示例:64位 AXI4, 500MHz, Outstanding=4, Burst=16
数据传输周期 = 16 拍(每笔事务)
地址阶段开销 = 1 拍(每笔事务)
总周期 = 16 + 1 = 17 拍
效率因子 = 16 / 17 ≈ 94%
实际带宽 = 32 Gbps × 94% ≈ 30 Gbps
不同配置的带宽对比
| 配置 | 理论带宽 | 实际带宽(估算) | 效率 |
|---|---|---|---|
| 32位, 200MHz | 6.4 Gbps | ~4.8 Gbps | 75% |
| 64位, 500MHz | 32 Gbps | ~24 Gbps | 75% |
| 128位, 400MHz | 51.2 Gbps | ~38 Gbps | 75% |
问题 10:Interleave 和乱序的区别是什么?
定义对比
| 特性 | Interleave | 乱序(Out of Order) |
|---|---|---|
| 定义 | 不同事务的数据拍交错传输 | 不同ID的事务不按顺序完成 |
| 作用层面 | W通道数据级别 | 事务级别 |
| AXI4支持 | 禁止 | 支持 |
Interleave 详解
AXI3 允许写交织:
Transaction A: W_A0 → W_A1 → W_A2
Transaction B: W_B0 → W_B1
交织方式:
W_A0 → W_B0 → W_A1 → W_B1 → W_A2
特点:
- A 和 B 的数据拍交错
- 每个事务的拍必须按顺序(A0→A1→A2)
- 但不同事务的拍可以交错
AXI4 禁止写交织:
正确:
W_A0 → W_A1 → W_A2 → W_B0 → W_B1
错误:
W_A0 → W_B0 → W_A1 → W_B1 → W_A2
乱序详解
乱序完成:
AR_A (ID=0) → AR_B (ID=1) → AR_C (ID=2)
可以:
R_B → R_C → R_A(基于从设备响应速度)
特点:
- 不同 ID 的事务可以乱序返回
- 同一 ID 的事务必须按顺序返回
- 提高带宽利用率
核心区别
Interleave:数据拍级别的交错
- 作用于 W 通道的单个数据拍
- AXI4 已禁止
乱序:事务级别的重排
- 作用于完整的读/写事务
- AXI4 仍然支持
- 通过 ID 机制实现
问题 11:AXI 的 Out of Order 应该怎么去实现?
首先要区分“允许乱序返回”和“必须重新排成发出顺序”。AXI 的基本规则是:具有相同 ID、相同方向并且属于相同排序范围的事务必须保持顺序;不同 ID 的事务之间没有统一的完成顺序要求。
ID 由谁产生
ARID 和 AWID 通常由 Master 发出,并不是由 Interconnect 为每笔事务统一分配一个连续且全局唯一的编号。Master 可以使用多个 ID 表示多个独立的有序流,也可以重复使用同一个 ID;重复使用时必须满足该 ID 对应的顺序要求。
Master 发出:
事务 A:ARID=0,访问慢速区域
事务 B:ARID=1,访问快速区域
允许的返回顺序:
先返回 RID=1 的事务 B
再返回 RID=0 的事务 A
Master 根据 RID/BID 找到对应的未完成事务,因此 B 不需要等待 A。不同 ID 之间的乱序正是 AXI 隐藏访问延迟、提高并行度的方式。
如果连续两笔请求使用相同 ID:
请求:A0(ID=3) → A1(ID=3)
响应:A0(ID=3) → A1(ID=3) 正确
响应:A1(ID=3) → A0(ID=3) 违反同 ID 顺序要求
Interconnect 如何路由响应
多个 Master 可能使用相同的 ID。例如 M0 和 M1 都可能发出 ARID=3。Interconnect 必须同时保存“来自哪个 Master”和“原始 ID”,常见实现方式是扩展或重映射内部 ID:
M0: ARID=3 ──→ internal_id={source=M0, id=3} ──┐
├──→ Slave
M1: ARID=3 ──→ internal_id={source=M1, id=3} ──┘
Slave 返回 internal_id
↓
Interconnect 恢复路由信息
├──→ 返回 M0,并恢复 RID=3
└──→ 返回 M1,并恢复 RID=3
具体设计可以直接扩展 ID,也可以使用映射表保存内部 tag。关键目标是:
- 把响应送回正确的 Master;
- 向 Master 返回正确的原始
RID/BID; - 保证协议要求的同 ID 顺序;
- 对不同 ID 保留架构允许的并行和乱序能力。
什么时候才需要重排序缓冲
正常 AXI 接口允许不同 ID 的事务乱序完成,因此 Interconnect 不必把所有响应重新排成请求发出顺序。以下场景才可能需要额外的重排序、等待或限制发出:
| 场景 | 处理方式 |
|---|---|
| Master 能按 ID 接收乱序响应 | 直接按 ID 返回,不做跨 ID 重排 |
| 上游接口只接受严格顺序响应 | 使用重排序缓冲,或限制为单笔/单 ID Outstanding |
| ID 宽度转换或协议桥接 | 使用映射表跟踪原始 ID、来源和顺序关系 |
| CPU 需要按程序顺序提交结果 | 通常由 CPU 内部的 Load/Store Queue、ROB 或内存顺序逻辑处理 |
| 相同 ID 存在多笔 Outstanding | 按该 ID 的请求队列顺序返回,不能用“ID 数值递增”判断先后 |
因此,不能假设下一个响应 ID 必须等于 当前 ID + 1。ID 是事务所属有序流的标签,不是天然连续递增的序号。
验证环境如何检查乱序响应
Scoreboard 可以为每个 ID 保存一个期望事务队列。不同 ID 的队列可以按任意先后被取出,但同一 ID 始终从队头匹配:
axi_transaction expected_by_id[int unsigned][$];
function void save_request(axi_transaction req);
expected_by_id[req.id].push_back(req);
endfunction
function void check_response(axi_transaction rsp);
axi_transaction exp;
if (!expected_by_id.exists(rsp.id) ||
expected_by_id[rsp.id].size() == 0) begin
`uvm_error("AXI_OOO",
$sformatf("收到没有对应请求的响应,id=%0d", rsp.id))
return;
end
// 同一 ID 内必须按照请求顺序匹配
exp = expected_by_id[rsp.id].pop_front();
if (!rsp.compare(exp))
`uvm_error("AXI_OOO",
$sformatf("响应内容不匹配,id=%0d", rsp.id))
endfunction
对于读突发,还要以 RID 识别所属事务,并检查拍数、RLAST 和同一事务内部的数据顺序;对于写事务,则使用 BID 匹配写响应。复位时应按照项目定义清理或终止所有未完成事务。
实现与验证要点总结
| 要点 | 正确理解 |
|---|---|
| ID 来源 | ARID/AWID 通常由 Master 提供,Interconnect 可以扩展或重映射 |
| ID 唯一性 | 不要求每笔 Outstanding 都使用全局唯一且连续递增的 ID |
| 不同 ID | 可以乱序完成,接收方按 RID/BID 匹配 |
| 相同 ID | 必须遵守协议规定的请求/响应顺序 |
| Interconnect | 负责响应路由、ID 恢复和必要的排序约束 |
| 重排序缓冲 | 仅在上游要求严格顺序或协议转换等场景中按需使用 |
| Scoreboard | 按 ID 建队列,不按全局请求顺序强行比较 |
以上规则应结合 Arm AMBA AXI/ACE Protocol Specification 的 Transaction Identifiers 与 Ordering Model 使用。实际项目还可能根据内存类型、目的地址、barrier 和系统一致性要求增加更严格的排序约束。
问题 12:WSTRB 是什么?总线写字节和实际写字节为什么要分开统计?
WSTRB(Write Strobe)是 AXI 写数据通道的字节有效掩码。WDATA 每 8 bit 对应一个字节,WSTRB 每一位对应一个字节 lane:
WSTRB[i] = 1:WDATA 对应字节有效,应写入目标
WSTRB[i] = 0:对应字节无效,目标中的该字节保持不变
因此,若 DATA_WIDTH=32,则 WSTRB_WIDTH=4:
WDATA = 32'hAA_BB_CC_DD
字节 3 2 1 0
WSTRB = 4'b1111 → 4 个字节都有效
WSTRB = 4'b0011 → 只有字节 1、0 有效
WSTRB = 4'b0101 → 只有字节 2、0 有效
一次 W 握手产生两个不同指标
写数据只有在 WVALID && WREADY 时真正传输:
wire w_hs = wvalid && wready;
一种常见的性能监控口径是:同一次 W 握手同时更新两个指标:
wire wr_bus_inc = active && w_hs;
wire wr_act_inc = active && w_hs;
wr_bus_delta = STRB_WIDTH;
wr_act_delta = popcount(wstrb);
两个 enable 相同,是因为它们观察的是同一个 W 传输事件;两个结果不同,是因为增量含义不同:
| 指标 | 每次 W 握手增加量 | 含义 |
|---|---|---|
写总线字节 wr_bus_bytes | STRB_WIDTH | 本拍占用的数据总线字节容量 |
实际写字节 wr_act_bytes | popcount(WSTRB) | 本拍真正有效的写字节数 |
例如 STRB_WIDTH=128,某拍只有 100 个 WSTRB 位为 1:
wr_bus_bytes += 128
wr_act_bytes += 100
这里的“总线字节”表示物理数据拍容量,是一种可选的性能监控口径,不是 AXI 协议强制规定的唯一 payload 算法。若规格要求按照窄传输的 AWSIZE 统计 payload,则应明确采用 2^AWSIZE 或其他规格公式,不能把两个定义混用。
读通道和事务数如何统计
AXI 读数据通道没有与 WSTRB 对称的 RSTRB。采用“按物理数据拍容量计数”的监控口径时,可以按实际握手拍统计读总线容量,并以响应完成事件统计事务数:
wire r_hs = rvalid && rready;
wire rlast_hs = r_hs && rlast;
wire b_hs = bvalid && bready;
// 当前活动窗口内
if (w_hs) wr_bus_bytes += STRB_WIDTH;
if (w_hs) wr_act_bytes += popcount(wstrb);
if (r_hs) rd_bus_bytes += STRB_WIDTH;
if (b_hs) wr_trans_num += 1;
if (rlast_hs) rd_trans_num += 1;
这五个事件的含义必须区分:
- W 握手表示完成一个写数据 beat;
- R 握手表示完成一个读数据 beat;
- B 握手表示一笔写事务收到完成响应;
- 带
RLAST的 R 握手表示一笔读事务的最后一个 beat 完成; - 只有 VALID、READY 同时为 1 才能计数,单独 VALID 或 READY 都不算传输。
知识点总结
| 问题 | 核心要点 |
|---|---|
| AXI vs AHB | 5通道独立、Outstanding、乱序 |
| AXI3 vs AXI4 | 禁止写交织、突发长度扩展 |
| Exclusive 访问 | 原子操作、不锁定总线、提高并发 |
| Outstanding 计算 | min(主设备、互联、从设备) |
| WRAP 地址 | 下界对齐、上界回绕 |
| 死锁避免 | 协议遵守、超时机制、资源管理 |
| AXI Stream 反压 | TREADY/TVALID 握手 |
| Channel 依赖 | AR→R, AW+W→B, 读写独立 |
| 带宽计算 | 位宽×频率×效率因子 |
| Interleave vs 乱序 | 数据拍交错 vs 事务重排 |
| Out of Order 实现 | Master 提供 ID、同 ID 保序、不同 ID 可乱序、接收方按 ID 匹配 |
| WSTRB 与字节统计 | WSTRB 每位对应一个字节;总线容量按 W/R beat 统计,实际写字节按 popcount(WSTRB) 统计 |