AXI4 总线协议全面详解
一、概述
1.1 什么是 AXI4
AXI4 (Advanced eXtensible Interface 4) 是 ARM 公司推出的 AMBA (Advanced Microcontroller Bus Architecture) 总线协议家族的第四代版本,是高性能、高频率系统设计的片上互联总线标准。
1.2 AXI4 的三种子协议
| 协议 | 说明 | 典型场景 |
|---|---|---|
| AXI4(Full) | 完整版,支持 burst、outstanding、乱序完成等所有特性 | 高性能互联,如 CPU ↔ DDR、DMA ↔ memory |
| AXI4-Lite | 轻量版,不支持 burst,每次传输 1 个数据 | 控制寄存器访问,如配置外设的 control/status reg |
| AXI4-Stream | 流式协议,不含地址通道,源源不断的连续数据流 | 音视频数据流、网络数据包、DMA 引擎 |
1.3 架构特点——独立的地址/数据通道
AXI4 的核心设计理念是通道分离。一次完整的读写操作分为 5 个独立的通道:
关键特点:
- 读和写是完全独立的通道,可以同时进行
- 每个通道都有独立的VALID/READY 握手机制
- 地址通道和数据通道分离,允许地址提前发送,后续数据乱序返回
二、信号列表
2.1 全局信号
| 信号 | 位宽 | 方向 | 说明 |
|---|---|---|---|
| ACLK | 1 | Master→Slave | 全局时钟,所有信号在时钟上升沿采样 |
| ARESETn | 1 | Master→Slave | 异步复位,低电平有效 |
2.2 写地址通道 (AW — Write Address Channel)
| 信号 | 位宽 | 说明 |
|---|---|---|
| AWID | ID_WIDTH | 写地址通道的 ID 标签 |
| AWADDR | ADDR_WIDTH | 写地址 |
| AWLEN | 8 | Burst 长度= AWLEN + 1 (0~255) |
| AWSIZE | 3 | Burst 大小:每拍字节数 (0=1B, 1=2B, …, 7=128B) |
| AWBURST | 2 | Burst 类型:00=FIXED, 01=INCR, 10=WRAP |
| AWLOCK | 2 | 锁类型:00=Normal, 01=Exclusive, 10=Locked |
| AWCACHE | 4 | 缓存/内存类型:定义传输的可缓存性、缓冲策略 |
| AWPROT | 3 | 保护类型:特权/安全/数据访问级别 |
| AWQOS | 4 | 服务质量 (QoS):优先级级别 0~15 |
| AWREGION | 4 | 区域标识:将物理地址空间划分为最多 16 个区域 |
| AWUSER | USER_WIDTH | 用户自定义信号(可选) |
| AWVALID | 1 | Master 驱动,表示 AW 通道地址有效 |
| AWREADY | 1 | Slave 驱动,表示可以接收地址 |
2.3 写数据通道 (W — Write Data Channel)
| 信号 | 位宽 | 说明 |
|---|---|---|
| WID | ID_WIDTH | 写数据 ID(仅在 AXI3 中使用,AXI4取消了 WID) |
| WDATA | DATA_WIDTH | 写数据(8/16/32/64/128/256/512/1024 位) |
| WSTRB | DATA_WIDTH/8 | 写选通:每个字节对应 1 位,为 1 时才写入 |
| WLAST | 1 | 该 burst 的最后一拍数据 |
| WUSER | USER_WIDTH | 用户自定义信号(可选) |
| WVALID | 1 | Master 驱动,表示 W 数据有效 |
| WREADY | 1 | Slave 驱动,表示可以接收数据 |
2.4 写响应通道 (B — Write Response Channel)
| 信号 | 位宽 | 说明 |
|---|---|---|
| BID | ID_WIDTH | 写响应 ID |
| BRESP | 2 | 写响应:00=OKAY, 01=EXOKAY, 10=SLVERR, 11=DECERR |
| BUSER | USER_WIDTH | 用户自定义信号(可选) |
| BVALID | 1 | Slave 驱动,表示写响应有效 |
| BREADY | 1 | Master 驱动,表示可接收响应 |
2.5 读地址通道 (AR — Read Address Channel)
| 信号 | 位宽 | 说明 |
|---|---|---|
| ARID | ID_WIDTH | 读地址通道 ID 标签 |
| ARADDR | ADDR_WIDTH | 读地址 |
| ARLEN | 8 | Burst 长度 = ARLEN + 1 |
| ARSIZE | 3 | Burst 大小 (同 AWSIZE) |
| ARBURST | 2 | Burst 类型 (同 AWBURST) |
| ARLOCK | 2 | 锁类型 (同 AWLOCK) |
| ARCACHE | 4 | 缓存类型 (同 AWCACHE) |
| ARPROT | 3 | 保护类型 (同 AWPROT) |
| ARQOS | 4 | QoS (同 AWQOS) |
| ARREGION | 4 | 区域标识 |
| ARUSER | USER_WIDTH | 用户自定义信号 |
| ARVALID | 1 | Master 驱动 |
| ARREADY | 1 | Slave 驱动 |
2.6 读数据通道 (R — Read Data Channel)
| 信号 | 位宽 | 说明 |
|---|---|---|
| RID | ID_WIDTH | 读数据 ID |
| RDATA | DATA_WIDTH | 读数据 |
| RRESP | 2 | 读响应:00=OKAY, 01=EXOKAY, 10=SLVERR, 11=DECERR |
| RLAST | 1 | 该 burst 的最后一拍 |
| RUSER | USER_WIDTH | 用户自定义信号 |
| RVALID | 1 | Slave 驱动 |
| RREADY | 1 | Master 驱动 |
2.7 各通道握手依赖关系
写事务握手顺序(无严格顺序,但通常这样): AWVALID/AWREADY ───► WVALID/WREADY ───► BVALID/BREADY 读事务握手顺序: ARVALID/ARREADY ───► RVALID/RREADYVALID/READY 握手规则:
- VALID 不能等待 READY(Master 必须主动发,不能等)
- READY 可以等待 VALID,也可以提前拉高
- 只有当 VALID 和 READY 同时为高时,传输发生
三、Burst 传输机制
3.1 Burst 三要素
每个 AXI4 传输由地址通道上的三个信号共同决定:
AWADDR — 起始地址 AWLEN[7:0] — 传输次数 = AWLEN + 1 AWSIZE[2:0] — 每拍字节数 = 2^AWSIZE3.2 三种 Burst 类型 (AWBURST / ARBURST)
FIXED (00) — 固定地址
每次传输使用同一个地址,不递增。
地址序列: addr, addr, addr, addr... 典型用途: 反复写入同一个外设寄存器(如 FIFO)INCR (01) — 递增地址(最常用)
每次传输后地址递增SIZE字节。
地址序列: addr, addr+SIZE, addr+2*SIZE, addr+3*SIZE... 典型用途: 连续内存读写,如 cache line fill、DMAWRAP (10) — 回环地址(仅 AXI4 Full)
递增到边界后自动回绕到起始地址,整个地址范围是对齐的。
突发示例: 起始地址=0x38, SIZE=16字节(4拍), LEN=3(共4拍) 地址序列: 0x38, 0x3C, 0x30, 0x34 ↑ 到达边界 0x40(4x16=64) 后回绕到 0x30 典型用途: cache line fill(CPU 一次性取一整行 cache)3.3 Burst 地址计算
INCR/NORMAL: Address_N = Start_Addr + N * (2^SIZE) WRAP: 低位递增,到达 2^SIZE * (LEN+1) 边界后低位回绕 FIXED: 地址不变四、Narrow 传输(窄传输)
4.1 什么是 Narrow 传输
当数据总线宽度 > 实际传输的数据宽度时,称为窄传输。例如:
数据总线 = 64 位 (8字节) AWSIZE = 3 -> 每拍 8 字节 (64位,对齐正常) AWSIZE = 2 -> 每拍 4 字节 ← 窄传输 (只用了总线的一半) AWSIZE = 1 -> 每拍 2 字节 ← 窄传输 AWSIZE = 0 -> 每拍 1 字节 ← 窄传输4.2 Narrow 传输中 WSTRB 的作用
窄传输需要WSTRB(写选通)来指明哪些字节通道被实际写入:
// 数据总线 64 位,写 2 字节到地址 0x4 // WSTRB[7:0] 每位对应一个字节通道 // 0x4 对应字节通道 4-5 WSTRB = 8'b0011_0000; // bit4 和 bit5 为 14.3 地址映射关系
| 地址偏移 | 64位总线的字节通道 |
|---|---|
| 0x00 | byte[0] |
| 0x08 | byte[8] |
当AWSIZE=2(4B)且地址0x4时:用 WSTRB[4:7] 标记第 4~7 字节有效。
4.4 为什么需要 Narrow 传输
- 混合数据类型:在 64 位总线上可以高效地写入 8/16/32 位数据
- 非对齐访问:允许访问非自然对齐的地址
- 减少总线浪费:不必为了写 1 字节而读取整个 64 位(对比 AHB,窄传输效率更高)
五、Outstanding 传输
5.1 概念
Outstanding 传输指的是 Master 在未收到前一个事务的响应之前就发出下一个事务的地址。
非 Outstanding(串行): AWADDR: [addr1]______[addr2]______[addr3]______ WDATA: [data1]______[data2]______[data3]______ BRESP: [resp1] [resp2] [resp3] Outstanding(并行/流水线): AWADDR: [addr1][addr2][addr3]____________________ WDATA: [data1]__[data2]__[data3]________________ BRESP: [resp1] [resp2] [resp3]______5.2 Outstanding 能力的衡量
Outstanding 深度 = Master 已发出但未收到响应的最大事务数 示例:深度为 3 表示 Master 最多可以同时发出 3 个事务5.3 AXI4 如何支持 Outstanding
- 每个通道独立握手(VALID/READY),地址通道不阻塞数据通道
- ID 标签机制— 每个 transaction 有独立的 ID,Slave 按 ID 返回数据
- Slave 需要内部深度足够(FIFO / buffer)来缓存多个请求
5.4 Outstanding 的优势
| 优势 | 说明 |
|---|---|
| 更高带宽利用率 | 隐藏了 Slave 的访问延迟(如 DDR 的列选延迟) |
| 流水线并行 | 地址发送和数据处理互相不阻塞 |
| 提高吞吐量 | 从 DDR 读取数据的延迟可以被后续请求覆盖 |
5.5 Outstanding 深度设置的权衡
深度太小 → 总线利用率低,延迟无法掩盖 深度太大 → Slave 端 buffer 巨大,硬件开销高 → 可能导致死锁(Slave 满,无法返回 response)六、乱序传输(Out-of-Order / Transaction ID 机制)
6.1 为什么需要乱序
不同的 Slave 或同一个 Slave 的不同访问区域,响应时间不同:
例子: Master 先后发出两个请求: ARID=0 → 读 SLOW_SLAVE(响应需要 100 拍) ARID=1 → 读 FAST_SLAVE(响应只需 10 拍) 如果没有乱序(AXI3 的严格顺序要求): R 通道顺序: [slow_data] [fast_data] ← fast 等 slow,延迟浪费 使用 ID 乱序(AXI4): R 通道顺序: [fast_data(ARID=1)] [slow_data(ARID=0)] ← fast 先回!6.2 ID 标签的规则
每个事务的 ID 由 Master 分配。 同一 ID 的事务必须保持顺序返回(写 + 读通道分别保持顺序)。 不同 ID 的事务可以乱序返回。ID=0 的 3 个读请求: [req_a] [req_b] [req_c] ──→ R 返回: [req_a] [req_b] [req_c] (保持顺序) ID=1 的 1 个读请求: [req_x] ──→ R 返回: [req_x] ID=0 和 ID=1 之间: 可以任意穿插 R 通道可能的顺序: [req_a(ID=0)] [req_x(ID=1)] [req_b(ID=0)] [req_c(ID=0)] [req_x(ID=1)]6.3 AXI4 取消了 WID
AXI3: 写数据通道有 WID,支持写数据乱序 AXI4: 取消 WID,写数据必须按发出顺序发送(W 通道保序) 写响应 B 通道仍可乱序(通过 BID 区分)原因:在实际设计中,写数据的乱序极少使用,反而增加了 Master 的设计复杂度。AXI4 简化了写端,要求 WDATA 与 AWADDR 一一对应顺序发送。
6.4 验证 ID 的正确行为
关键检查项: ✓ 同一 ID 的读请求在 R 通道必须保序返回 ✓ 同一 ID 的写请求在 B 通道必须保序返回 ✓ 写数据必须按 AW 发出的顺序发送(AXI4 无 WID) ✓ 不同 ID 的请求允许任意穿插乱序 ✓ 同一个 ID 不能覆盖(必须先完成前一个,再发后一个同一 ID 的)七、Exclusive 访问(独占访问 / 原子操作)
7.1 为什么需要 Exclusive 访问
在多核系统中,多个 Master(CPU core)可能同时访问同一块内存。传统的"读-改-写"流程需要加锁,但锁的开销太大。Exclusive 访问提供了更高效的单边原子操作机制。
7.2 Exclusive 访问流程 (Load-Linked / Store-Conditional)
Step 1: Master 发送 Exclusive 读 (ARLOCK=01) Slave 标记该地址为"被监控" Step 2: Master 执行本地操作(修改数据) Step 3: Master 发送 Exclusive 写 (AWLOCK=01) Slave 检查该地址是否被其他 Master 修改过 情况A:未被修改 → 写入成功,返回 EXOKAY 情况B:已被修改 → 写入失败,返回 OKAY7.3 AXI4 中的 LOCK 信号
| AWLOCK/ARLOCK | 模式 | 说明 |
|---|---|---|
| 00 | Normal | 普通访问 |
| 01 | Exclusive | 独占访问(读/写配对使用) |
| 10 | Locked | 锁定访问(AXI3 保留,AXI4 中已废弃) |
| 11 | 保留 | — |
7.4 Exclusive 响应的区分
BRESP / RRESP: 00 = OKAY — 普通访问成功 / Exclusive 写失败(被其他 Master 修改) 01 = EXOKAY — Exclusive 读/写成功 10 = SLVERR — Slave 错误 11 = DECERR — 译码错误7.5 Exclusive Monitor
独占操作的核心是Exclusive Monitor(监视器),通常位于互联(interconnect)或 memory slave 中:
┌─────────┐ ┌─────────────┐ ┌─────────┐ │ CPU0 │ │ Exclusive │ │ DDR │ │ ──────┼─────────►│ Monitor ├─────────►│ │ │ │ │ │ │ │ │ CPU1 │ │ - 记录地址 │ │ │ │ ──────┼─────────►│ - 检测冲突 │ │ │ └─────────┘ └─────────────┘ └─────────┘- 当 Master A 发送 Exclusive 读 → Monitor 记录该地址 → 关联到 Master A
- 当其他 Master 向该地址写入 → Monitor 取消 Master A 的独占权
- 当 Master A 发送 Exclusive 写 → Monitor 检查占用权 → EXOKAY 或 OKAY
八、QoS(Quality of Service,服务质量)
8.1 为什么需要 QoS
在复杂 SoC 中,多个 Master 共享总线资源:
DDR 控制器前的 Master 列表: ├── CPU (延迟敏感,不满足就卡顿) ├── GPU (带宽需求大,可稍等) ├── Video Decoder (实时需求) ├── Display Controller (需要保证帧率) └── DMA (后台搬运,不着急)QoS 让 Master 标记其请求的优先级,互联(interconnect)据此进行仲裁。
8.2 QOS 信号
AWQOS[3:0] — 写操作的 QoS 级别 (0~15,越大优先级越高) ARQOS[3:0] — 读操作的 QoS 级别 (0~15)8.3 QoS 的典型配置
| 优先级 | QoS 值 | 典型设备 |
|---|---|---|
| 最高 | 15 | Display Controller (避免画面撕裂) |
| 高 | 12~14 | Real-time Audio / Video |
| 中 | 8~11 | CPU (cache miss 时) |
| 低 | 4~7 | GPU / Accelerator |
| 最低 | 0~3 | Background DMA / Debug |
8.4 QoS 的实现方式
方式1:静态 QoS — 每个 Master 固定设置一个 QoS 值 方式2:动态 QoS — Master 根据当前任务动态调整 QoS 方式3:QoS 编程接口 — 软件可以动态配置 Master 的 QoS8.5 QoS 在验证中需要关注的点
1. 高优先级请求是否被低优先级请求阻塞? 2. 是否会发生优先级反转(低 QoS 持有资源,高 QoS 等待)? 3. QoS 仲裁是否公平(防止高 QoS 完全饿死低 QoS)? 4. 动态 QoS 切换时是否有毛刺或延迟?九、4KB 边界问题
9.1 什么是 4KB 边界
AXI4 协议规定:一个 burst 传输不能跨越 4KB 地址边界。
内存空间: ┌──────────────┐ 0x0000 │ Page 0 │ │ [0x0000 │ │ ~0x0FFF] │ ├──────────────┤ ← 4KB 边界 (0x1000) │ Page 1 │ │ [0x1000 │ │ ~0x1FFF] │ ├──────────────┤ ← 8KB 边界 (0x2000) │ Page 2 │ └──────────────┘9.2 为什么不能跨越 4KB 边界
这是 AXI4 协议的硬性规定,原因:
| 原因 | 说明 |
|---|---|
| 页边界保护 | 内存管理单元(MMU)的页大小通常是 4KB,不同页可能有不同的权限/属性 |
| Slave 地址译码 | 互联(interconnect)通常基于 4KB 对齐进行地址映射,跨越后可能到达不同的 Slave |
| 简化 Slave 设计 | Slave 不需要处理跨边界的大块传输 |
| 避免内存保护违例 | 跨页访问可能从可访问区域跳到不可访问区域 |
9.3 跨 4KB 边界会怎样
// ❌ 违反规则: // 起始地址 = 0x0FFC, SIZE=4B (32位), LEN=3 (共4拍) // 地址序列: 0x0FFC, 0x1000, 0x1004, 0x1008 // ↑ 跨越了 0x1000 的 4KB 边界!违反协议! // ✅ 合法: // 起始地址 = 0x0FFC, SIZE=4B, LEN=0 (仅1拍) // 地址序列: 0x0FFC ← 没有跨边界 // ✅ 合法: // 起始地址 = 0x1000, SIZE=4B, LEN=7 (共8拍) // 地址序列: 0x1000, 0x1004, ..., 0x101C ← 都在 Page 1 内部Mater 的责任:发起传输前检查是否会跨 4KB 边界,如果会则必须拆分为多个 burst。
9.4 跨 4KB 边界的检测
defcheck_4k_boundary(start_addr,burst_len,burst_size):""" 判断一个 burst 是否跨越 4KB 边界 burst_len: 拍数 (AWLEN + 1) burst_size: 每拍字节数 (2^AWSIZE) """transfer_bytes=burst_len*burst_size# burst 总字节数start_page=start_addr//4096end_addr=start_addr+transfer_bytes-1end_page=end_addr//4096returnstart_page!=end_page# True = 跨边界9.5 Wrap Burst 的 4KB 边界
WRAP burst 本身已有对齐边界(burst 大小对齐),这个边界不会超过 4KB,所以 WRAP 天然不会跨 4KB 边界:
// WRAP burst 尺寸 = N * SIZE // 这个尺寸必须 ≤ 4KB,否则也算非法 // 实际上 AXI4 限制最大 SIZE=128B,最大 LEN=15(16拍) // 最大一个 burst = 128*16 = 2048B = 2KB < 4KB ✅ // 所以 WRAP 天然安全十、其他重要机制
10.1 CACHE 信号与内存属性
| ARCACHE[3:0] / AWCACHE[3:0] | 含义 |
|---|---|
| bit0 | Bufferable— 数据可以缓冲(不必须立即到达终点) |
| bit1 | Cacheable— 数据可以缓存(可以有 cache copy) |
| bit2 | Read Allocate— 读缺失时分配 cache line |
| bit3 | Write Allocate— 写缺失时分配 cache line |
常用组合:
0000 = Non-bufferable, Non-cacheable — Device memory 0001 = Bufferable, Non-cacheable — 写缓冲 0010 = Non-bufferable, Cacheable — 读缓存 0111 = Write-back, Write-allocate — 标准 cache policy 1111 = Write-through, Read+Write allocate — cache with write-through10.2 PROT 信号与安全属性
| APROT[2:0] | 含义 |
|---|---|
| bit0 = 0 | Privilegedaccess |
| bit0 = 1 | Unprivilegedaccess |
| bit1 = 0 | Secureaccess |
| bit1 = 1 | Non-Secureaccess |
| bit2 = 0 | Dataaccess |
| bit2 = 1 | Instructionaccess |
用途:TrustZone 安全扩展、MMU 权限检查、指令/数据区分。
10.3 REGION 信号
ARREGION[3:0] / AWREGION[3:0] 将物理地址空间划分为最多 16 个区域(region)。 不同 region 可能有不同的访问属性、延迟、Slave 映射。 典型用途:在包含多个 DDR 控制器/内存片的 SoC 中, 用 region 选择具体的控制器。10.4 AXI4-Stream 的简要对比
AXI4-Full AXI4-Lite AXI4-Stream ───────────────────────────────────────────────────────────── 5 个通道 5 个通道(简化) 1 个通道(数据流向) 有地址 有地址 无地址 支持 burst 仅 1 拍 连续数据流 支持 ID/乱序 无 ID 无 ID 支持 Exclusive 不支持 不支持 适合任意访问 适合寄存器 适合数据流(视频/DMA/网络)十一、AXI4 性能指标与优化
11.1 关键性能指标
| 指标 | 公式/说明 |
|---|---|
| 带宽(Bandwidth) | 数据宽度 × 时钟频率 × 有效数据比例 |
| 延迟(Latency) | 从发出地址到收到第一拍数据的时间 |
| 吞吐量(Throughput) | 单位时间内完成的有效数据传输量 |
| 总线利用率 | 实际数据传输周期 / 总周期 |
11.2 性能优化策略
1. 增加 Outstanding 深度 → 掩盖延迟 2. 增大数据总线宽度 → 提高单拍带宽(代价:布线面积↑) 3. 使用 INCR burst → 减少地址通道的开销 4. 对齐地址访问 → 避免 WSTRB 导致的带宽浪费 5. 合理设置 QoS → 确保实时性要求高的 Master 不被饿死 6. 避免频繁跨 4KB 边界 → 减少额外地址开销十二、AXI4 功能验证方法
12.1 验证要覆盖的关键功能点
基础功能验证
✓ 所有 5 个通道的正确握手(VALID/READY 时序) ✓ 三种 Burst 类型(FIXED/INCR/WRAP)的地址正确性 ✓ 各种 SIZE(1B/2B/4B/8B/.../128B)的组合 ✓ WSTRB 在各种 Narrow 传输下的正确性 ✓ 写响应 (B通道) 的 OKAY/SLVERR/DECERR ✓ 读响应 (R通道) 的 OKAY/SLVERR/DECERR高级功能验证
✓ 4KB 边界限制 — 确保证 Master 不发出跨 4KB 边界的 burst ✓ Outstanding 传输 — 多个未完成请求的正确顺序和处理 ✓ ID 乱序 — 不同 ID 的返回可以穿插,同一 ID 必须保序 ✓ Exclusive 访问 — Load-Linked/Store-Conditional 流程 ✓ Exclusive Monitor — 检测其他 Master 写入,返回 OKAY ✓ QoS 优先级仲裁 — 高优先级是否优先服务 ✓ CACHE/PROT 信号传递 — 是否正确到达最终 Slave ✓ Locked 传输(AXI3 兼容)边界与压力验证
✓ 最大 burst 长度(LEN=255,即 256 拍) ✓ 最大数据宽度(1024 位,如果支持) ✓ Outstanding 深度打到 Slave 的最大能力 ✓ 多个 Master 同时访问同一个 Slave ✓ 所有 Master 都发送最高 QoS 的极端情况 ✓ 地址空间的非法访问(未映射地址 → DECERR) ✓ 随机握手延迟(VALID/READY 任意延迟组合)12.2 UVM 验证环境中的检查
Protocol Checker(协议检查器)
AXI4 协议有大量时序和逻辑规则,必须用 protocol checker 自动检查:
需要检查的规则示例: 1. VALID 不能依赖 READY(Master 必须主动拉 VALID) 2. 一旦 VALID 拉高,必须保持到 READY 到来(不能撤销) 3. WLAST 必须在最后一拍数据上拉高 4. Narrow 传输的 WSTRB 必须正确 5. Burst 地址计算必须符合类型(FIXED/INCR/WRAP) 6. 写响应 BVALID 必须在 WLAST 和 WREADY 之后 7. 同一 ID 在 R 通道必须保序 8. 4KB 边界检查 9. Exclusive 访问必须是成对的读→写UVM Sequence 激励生成
// 基础随机激励 class axi_random_seq extends uvm_sequence #(axi_transaction); task body(); axi_transaction tx; repeat(100) begin `uvm_do_with(tx, { burst_type inside {FIXED, INCR, WRAP}; burst_len inside {[0:15]}; // 短 burst burst_size inside {[0:5]}; // 1B~32B addr inside {[0:32'h1_FFFF]}; // 确保 4KB 边界 solve addr before burst_len; solve addr before burst_size; }) end endtask endclass // Outstanding 测试 class axi_outstanding_seq extends uvm_sequence #(axi_transaction); task body(); axi_transaction tx_q[10]; // 一次性发出 10 个读请求,不等待响应 foreach (tx_q[i]) begin `uvm_do_with(tx_q[i], {read_write == READ; id == i;}) end // 然后依次接收 response for (int i = 0; i < 10; i++) begin get_response(rsp); // 验证返回顺序 end endtask endclass // Exclusive 测试 class axi_exclusive_seq extends uvm_sequence #(axi_transaction); task body(); axi_transaction tx, rsp; // 独占读 `uvm_do_with(tx, {read_write == READ; exclusive == 1;}) get_response(rsp); assert (rsp.resp == EXOKAY); // 独占写(同一地址) `uvm_do_with(tx, { read_write == WRITE; exclusive == 1; addr == rsp.addr; // 同一个地址 }) get_response(rsp); // rsp.resp 可能是 EXOKAY 或 OKAY endtask endclass // 跨 4KB 边界测试(预期失败场景) class axi_cross_4k_seq extends uvm_sequence #(axi_transaction); task body(); axi_transaction tx; // 这个 transaction 必然跨 4KB 边界 —— 协议检查器应该报错 `uvm_do_with(tx, { addr == 32'hFFF8; burst_len == 3; // 4 拍 burst_size == 3; // 8B/拍 = 32B 总长 → 跨越到 0x10018 }) // 如果是 Master 验证,这里应该检查 Master 是否正确拆分 // 如果是 Slave 验证,这里应该检查 Slave 如何正确响应跨边界请求 endtask endclassScoreboard / 数据完整性检查
class axi_scoreboard extends uvm_scoreboard; // 写数据记录 bit [31:0] mem_model[bit [31:0]]; // 简单内存模型 // 写事务到达时更新内存模型 function void write_transaction(axi_transaction tx); foreach (tx.data[i]) begin if (tx.wstrb[i]) begin mem_model[tx.addr + i] = tx.data[i]; end end endfunction // 读事务到达时比较(读取的数据和内存模型中的数据) function void check_read_data(axi_transaction tx); foreach (tx.data[i]) begin if (mem_model.exists(tx.addr + i)) begin assert(tx.data[i] == mem_model[tx.addr + i]) else `uvm_error("DATA_MISMATCH", $sformatf("Addr=%0h expect=%0h got=%0h", tx.addr + i, mem_model[tx.addr + i], tx.data[i])) end end endfunction endclass12.3 常用的 AXI4 VIP / Protocol Checker
商业 VIP: Synopsys VC Verification IP (AXI4 VIP) Cadence AXI4 VIP ARM AXI4 Protocol Checker 开源/内建: VHDL: AXI4-Stream VIP by AMD/Xilinx SystemVerilog: AXI4 Protocol Checker (bus_axim_monitor) 来自 OpenCores UVM: 自建 Protocol Checker(推荐使用 UVM scoreboard+monitor 模式)十三、常见问题总结
| 问题 | 原因 | 解决方法 |
|---|---|---|
| 跨 4KB 边界 | Master 发出 burst 跨越 4KB 边界 | Master 必须检查并拆分;验证中必须检查此规则 |
| ID 乱序错误 | 同一 ID 的读数据在 R 通道未保序 | 验证中严格检查 ID + 顺序规则 |
| 延迟隐藏不足 | Outstanding 深度太小 | 增加 Master 的 outstanding 深度(性能)或检查 Slave 的接受能力 |
| 优先级反转 | 低 QoS Master 持有锁,高 QoS Master 等待 | 使用抢占机制或限制锁定时间 |
| 写响应丢失 | Master 没等 BVALID/BREADY 就发下一个写 | 严格检查写事务的完成状态 |
| 数据损坏 | WSTRB 错误(写入了不应该写的字节) | 使用内存模型进行数据完整性检查 |
| 死锁 | Slave 和 Master 互相等待 | 确保每个通道的 VALID 不依赖对方 READY |
| Slave 响应错误 | SLVERR 表示 Slave 内部错误;DECERR 表示地址未映射 | 检查地址映射表或 Slave 功能 |
十四、总结
| AXI4 特性 | 解决的问题 | 设计目的 |
|---|---|---|
| 5 个独立通道 | 地址和数据分离 | 允许地址提前发送、数据乱序返回、读写并行 |
| VALID/READY 握手 | 不同频率/延迟的组件可以互连 | 与时钟周期无关,任意延迟都兼容 |
| Burst 传输 | 减少地址发送频率 | 提高总线利用率,支持高速缓存行填充 |
| Narrow 传输 + WSTRB | 在宽总线上处理小数据 | 节省总线宽度,提供字节级写入精度 |
| Outstanding | 掩盖 Slave 访问延迟 | 通过流水线提高有效吞吐量 |
| ID + 乱序 | 处理不同延迟的 Slave 响应 | 防止一个慢 Slave 阻塞其他快速访问 |
| Exclusive | 多核原子操作 | 比传统锁机制更高效的同步原语 |
| QoS | 区分不同 Master 的优先级 | 保证实时性要求高的 Master 获得服务 |
| 4KB 边界限制 | 防止跨页访问和地址映射错误 | 简化 MMU 设计和内存保护 |
| CACHE/PROT | 定义内存属性和安全级别 | 支持 cache 一致性和 TrustZone |
| REGION | 物理地址空间分区 | 支持超大 SoC 中多个内存控制器的管理 |
验证 AXI4 的核心思路:
1. 协议时序:VALID/READY 握手规则、通道间依赖 → Protocol Checker 2. 功能正确:地址计算、burst 类型、WSTRB → Directed test + Constrained random 3. 数据完整性:写入数据 vs 读出数据一致 → Scoreboard + Memory model 4. 高级功能:Outstanding、乱序、Exclusive → 专用 Sequence 5. 边界条件:4KB 边界、最大值、全随机延迟 → Stress test 6. 性能验证:带宽、延迟、吞吐量 → Performance monitor