多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

AXI3协议中文详解:五通道握手、突发地址计算与Slave验证实战

AXI3协议中文详解:五通道握手、突发地址计算与Slave验证实战 简介AMBA AXI3中文协议详解是一份面向SoC设计、FPGA开发及嵌入式系统工程师的中文技术文档适合需要深入理解AXI总线握手、突发传输与通道机制的读者。资源包内含1个PDF文件大小约1.5MB内容围绕AXI协议的核心概念展开涵盖分离的地址/控制与数据相位、字节选通非对齐传输、基于突发的传输模式、读写数据通道分离、outstanding与乱序传输等关键特性并配有读地址、读数据、写地址、写数据及写响应通道的结构说明。文档还系统梳理了VALID与READY双向握手机制、通道定义、接口与互联拓扑以及长度可变突发、回环/增量/固定长度突发、原子操作、缓存控制与安全特权访问等机制。目前已有528人学习下载适合作为协议查阅手册与设计参考帮助读者快速建立AXI3知识框架提升总线设计与验证效率。1. 为什么每个 FPGA 工程师迟早都要啃一遍 AXI3 中文协议做 Zynq 或纯 FPGA 逻辑开发的人大概都有过这样的经历IP 核例化好了地址映射也配了仿真波形一跑数据死活出不来。抓波形一看AWVALID拉高了AWREADY却一直是低或者读数据通道上RLAST该来的没来突发传了 7 拍就断了。这类问题的根子十有八九不在你的逻辑而在对 AXI3 握手规则和突发地址计算的理解有偏差。AMBA AXI3 是 ARM 在 AXI 协议第一版中定义的接口规范它把地址/控制与数据相位彻底分离用五条独立通道加 VALID/READY 双向握手来跑传输。相比 AHB 那种地址数据绑在一起的老总线AXI3 允许 outstanding 和乱序完成主机发完地址不用等数据回来就能发下一个带宽利用率能拉高一大截。这份中文协议详解把 V1.0 规范里的架构、信号、握手、地址选项、Cache 与保护支持逐章翻译整理适合正在写 AXI Master/Slave 逻辑、调 Xilinx MIG 或 AXI Interconnect、或者要自己搭总线验证环境的工程师。下面按“信号怎么连、握手怎么走、地址怎么算、坑怎么排”的顺序拆开讲。2. AXI3 五通道信号定义与 VALID/READY 握手时序2.1 全局信号与五条独立通道的职责划分AXI3 的接口信号按通道分组全局只有两个ACLK和ARESETn。ACLK是所有信号的采样基准上升沿有效ARESETn低有效复位时所有 VALID 必须拉低。剩下的信号分属五条通道每条通道只在一个方向上传信息这是 AXI 能插寄存器片、能做时序收敛的前提。通道方向关键信号作用写地址 AW主机→从机AWID/AWADDR/AWLEN/AWSIZE/AWBURST/AWVALID/AWREADY传送写突发的起始地址与控制写数据 W主机→从机WID/WDATA/WSTRB/WLAST/WVALID/WREADY传送写数据与字节选通写响应 B从机→主机BID/BRESP/BVALID/BREADY从机回写完成状态读地址 AR主机→从机ARID/ARADDR/ARLEN/ARSIZE/ARBURST/ARVALID/ARREADY传送读突发的起始地址与控制读数据 R从机→主机RID/RDATA/RRESP/RLAST/RVALID/RREADY从机返回读数据与响应注意WID必须和对应写事务的AWID一致BID必须和AWID一致RID必须和ARID一致。ID 是乱序完成的唯一依据相同 ID 的事务必须按序完成不同 ID 可以乱序。很多初学者在自研 Slave 里随手给BID赋 0结果多主机场景下响应串了就是没吃透这条。2.2 VALID/READY 握手的三种时序形态所有五条通道都用同一套握手规则传输发生在VALID和READY同时为高的那个时钟上升沿。源端拉高VALID表示地址/数据/控制有效目的端拉高READY表示能接收。关键在于谁先谁后都合法于是有三种典型时序。第一种源端先拉VALID目的端过几个周期再拉READY。这是最常见的背压场景源端数据必须保持稳定直到握手完成。第二种目的端先拉READY源端后拉VALID表示从机随时能收主机一有数据就能一拍传完。第三种两者同拍拉高传输立即发生。// 写数据通道握手源端保持 WDATA/WSTRB 稳定直到 WREADY 拉高 always (posedge ACLK or negedge ARESETn) begin if (!ARESETn) begin WVALID 1b0; WLAST 1b0; end else if (WVALID WREADY) begin // 握手成功推进到下一拍数据 WVALID (beat_cnt burst_len - 1); WLAST (beat_cnt burst_len - 2); beat_cnt beat_cnt 1; end // WVALID 一旦拉高在 WREADY 到来前不得撤销 end这段逻辑的核心是WVALID拉高后只有等到WREADY才允许变化WDATA和WSTRB在WVALID有效期间必须保持不变。WLAST只在突发最后一拍拉高。参数burst_len来自AWLEN1beat_cnt是当前拍计数。如果仿真里看到WDATA在WREADY为低时跳变那就是源端逻辑写错了从机采到的数据不可信。2.3 握手依赖关系与死锁规避AXI3 规范里有一条铁律任何组件的VALID不能依赖其他组件的READY。换句话说你不能写成“等AWREADY拉高了我再拉AWVALID”这直接违反协议还可能死锁。READY可以等VALID但VALID绝不能等READY。写事务里还有一条容易踩的依赖主机必须先驱动AWVALID或WVALID再去等AWREADY/WREADY。如果从机设计成“等WVALID拉高才拉AWREADY”而主机又设计成“等AWREADY拉高才拉WVALID”两边互等波形上就是两个信号永远不动。我一般会在自研 Slave 里让AWREADY默认拉高只要地址通道有空就收避免这类互锁。提示AWREADY和ARREADY推荐默认值为高前提是从机能随时接收任何有效地址。默认拉低会让每个传输至少多花一个周期带宽直接砍半。3. 突发地址计算LEN、SIZE、BURST 三参数如何决定每一拍地址3.1 突发长度、大小与类型的编码规则AXI3 的传输是基于突发的主机只给起始地址后续每拍地址由从机按规则算出来。三个控制信号决定算法AWLEN/ARLEN定长度AWSIZE/ARSIZE定每拍字节数AWBURST/ARBURST定地址变化方式。LEN是 4 位编码值加 1 就是实际传输拍数范围 1 到 16。SIZE是 3 位2^SIZE就是每拍传输的字节数从 1 字节到 128 字节。BURST是 2 位b00固定长度FIXEDb01增量INCRb10回环WRAPb11保留。信号编码含义LENb0000~b1111传输拍数 编码值 1即 1~16SIZEb000~b111每拍字节数 2^编码值即 1~128BURSTb00FIXED地址不变用于 FIFOBURSTb01INCR地址递增用于普通内存BURSTb10WRAP地址递增到边界回卷用于 Cache Line回环突发有两个硬约束起始地址必须对齐到传输大小突发长度只能是 2、4、8、16。违反任何一条从机行为未定义。另外所有突发都不能跨越 4KB 边界这是为了防止一个突发跨到另一个从机的地址空间。3.2 增量与回环突发的地址递推公式规范里给了一套变量和公式我把它翻译成能直接写进 RTL 的形式。设Start_Address是主机给的起始地址Number_Bytes 2^SIZEBurst_Length LEN 1Data_Bus_Bytes是数据总线字节宽度。对齐地址Aligned_Address (Start_Address / Number_Bytes) * Number_Bytes即向下取整到Number_Bytes边界。第一拍地址就是Start_Address。从第二拍起第 N 拍地址Address_N Aligned_Address (N-1) * Number_Bytes。回环突发多一个回卷边界Wrap_Boundary (Start_Address / (Number_Bytes * Burst_Length)) * (Number_Bytes * Burst_Length)。当Address_N算出来等于Wrap_Boundary Number_Bytes * Burst_Length时把它改回Wrap_Boundary。def gen_burst_addr(start, size, length, burst, data_bus_bytes4): number_bytes 1 size burst_len length 1 aligned (start // number_bytes) * number_bytes addrs [] if burst 0b00: # FIXED addrs [start] * burst_len elif burst 0b01: # INCR addrs [aligned i * number_bytes for i in range(burst_len)] elif burst 0b10: # WRAP wrap_boundary (start // (number_bytes * burst_len)) * (number_bytes * burst_len) for i in range(burst_len): a aligned i * number_bytes if a wrap_boundary number_bytes * burst_len: a wrap_boundary addrs.append(a) return addrs # 例起始 0x34SIZE2(4字节)LEN3(4拍)WRAP print([hex(a) for a in gen_burst_addr(0x34, 2, 3, 0b10)]) # 输出 [0x34, 0x38, 0x3c, 0x30]最后一拍回卷到 0x30这段代码把三种突发的地址序列都算出来了。size是AWSIZE的整数值length是AWLEN的整数值burst是AWBURST的整数值。回环例子里起始 0x34 对齐到 4 字节边界还是 0x34四拍地址 0x34/0x38/0x3c/0x30最后一拍从 0x40 回卷到 0x30。写 RTL 时可以直接把这段逻辑综合成组合电路注意除法用移位实现。3.3 字节通道与 WSTRB 的对应关系每拍数据落在数据总线的哪些字节通道上由地址和SIZE共同决定。Lower_Byte_Lane Address_N - (Address_N / Data_Bus_Bytes) * Data_Bus_BytesUpper_Byte_Lane Lower_Byte_Lane Number_Bytes - 1。数据总线上对应的字节区间就是DATA[(8*Upper7) : (8*Lower)]。写通道的WSTRB每一位对应WDATA的一个字节WSTRB[n]对应WDATA[8n7:8n]。非对齐传输就是靠WSTRB把无效字节屏蔽掉。比如 32 位总线上传 1 字节到地址 0x35WSTRB应该是4b0010只有第二个字节通道有效。注意WSTRB在WVALID为低时可以是任意值但推荐保持为低或维持前值。从机只在WVALID和WREADY同时为高时才采样WSTRB。4. 用 SystemVerilog 搭一个 AXI3 Slave 验证环境4.1 验证环境的整体结构与激励生成协议看懂了不代表能调通最有效的验证方式是写一个最小 AXI3 Slave 模型用随机激励去撞握手和地址计算。我一般用 SystemVerilog 搭一个轻量环境一个 AXI3 Slave BFM 负责按协议响应一个激励生成器随机产生AWLEN/AWSIZE/AWBURST组合一个记分板比对读回数据和写入数据。Slave BFM 的核心是五条通道各自独立跑状态机但共享一个事务队列来维护 ID 顺序。写通道收到AWVALID后把地址和控制信息入队写数据通道按WLAST收齐后触发写响应读通道收到ARVALID后按地址公式生成数据流。// AXI3 Slave 写地址通道接收逻辑 always_ff (posedge ACLK or negedge ARESETn) begin if (!ARESETn) begin AWREADY 1b1; // 默认拉高随时可收 end else begin if (AWVALID AWREADY) begin // 锁存地址与控制信息 aw_queue.push_back({awid, awaddr, awlen, awsize, awburst}); // 队列满则拉低 AWREADY 背压 AWREADY (aw_queue.size() QUEUE_DEPTH); end else if (aw_queue.size() QUEUE_DEPTH) begin AWREADY 1b1; end end end这段逻辑用队列缓存写地址事务队列深度QUEUE_DEPTH控制能支持多少 outstanding。AWREADY默认拉高队列快满时拉低背压。锁存的信息包括AWID、AWADDR、AWLEN、AWSIZE、AWBURST后续写数据通道和写响应通道都从这里取。参数QUEUE_DEPTH一般设 4 到 8太小限制 outstanding 能力太大浪费面积。4.2 握手超时检测与协议违例断言验证环境里最值钱的是断言。AXI3 有几条必须检查的协议规则写成 SVA 能在仿真时第一时间抓到违例。// AWVALID 拉高后必须保持到 AWREADY 拉高 property p_awvalid_stable; (posedge ACLK) disable iff (!ARESETn) (AWVALID !AWREADY) | (AWVALID $stable(AWADDR) $stable(AWLEN)); endproperty assert property (p_awvalid_stable) else $error(AWVALID 在 AWREADY 前撤销或地址跳变); // WLAST 必须与 AWLEN 决定的拍数一致 property p_wlast_correct; (posedge ACLK) disable iff (!ARESETn) (WVALID WREADY WLAST) |- (beat_cnt awlen); endproperty assert property (p_wlast_correct) else $error(WLAST 拍数与 AWLEN 不符);第一条断言检查AWVALID在AWREADY到来前不能撤销且AWADDR、AWLEN必须稳定。第二条检查WLAST出现的拍数是否等于AWLEN。这两条能覆盖大部分握手和突发长度错误。实际项目里我还会加RLAST与ARLEN的一致性检查、BID与AWID的匹配检查。4.3 常见握手死锁的波形特征与定位仿真跑挂时波形上死锁有几种典型长相。第一种AWVALID和AWREADY都是低主机在等AWREADY从机在等AWVALID两边互等。这通常是主机逻辑写成了“等AWREADY再拉AWVALID”违反 VALID 不能依赖 READY 的规则。第二种WVALID拉高了但WREADY一直低从机在等AWVALID或地址队列有空位。如果地址通道已经堵了写数据通道自然收不了。定位方法是先看地址通道队列是不是满了再看从机是不是把WREADY的拉高条件绑在了AWVALID上。第三种读通道RVALID拉高但RREADY一直低主机没准备好收数据。如果主机RREADY默认拉低且只在特定状态拉高而那个状态又依赖RVALID同样会互锁。我一般让主机RREADY默认拉高除非有明确的背压需求。提示抓波形时先看五条通道的 VALID/READY 两两组合任何一条通道上 VALID 和 READY 同时为低超过几十个周期基本就是死锁顺着依赖链往回找就能定位。5. 乱序完成、outstanding 与寄存器片插入的工程取舍5.1 ID tag 如何支撑乱序与多虚拟主机AXI3 允许不同 ID 的事务乱序完成相同 ID 必须按序。互联负责给来自不同主机的 ID 附加额外位保证全局唯一。ID 的作用类似主机号但每个主机还能用不同 ID 值模拟多个虚拟主机在同一个物理端口上跑多路独立数据流。实际用的时候如果主机不要求顺序完成就给每个事务分配不同 ID让从机自由调度。如果要求严格顺序所有事务用同一个 ID。简单从机可以完全忽略 ID按序响应每个事务协议也允许。复杂从机比如带内部缓存的 DDR 控制器会利用 ID 把先准备好的数据先返回提升吞吐。5.2 outstanding 深度与寄存器片的时序收敛outstanding 指主机发完地址不用等数据回来就能发下一个事务。深度取决于从机地址队列能缓存多少事务。深度越大主机越不容易被地址通道阻塞但面积和复杂度也越高。我一般根据主机的最大并发需求来定DMA 场景设 8 到 16普通外设访问设 2 到 4 就够。寄存器片是 AXI 的杀手锏。因为五条通道方向独立、通道间没有固定时序关系可以在任意通道上插一级寄存器来切断长路径代价是增加一拍延迟。处理器到高性能内存的直连路径通常不插保证低延迟到低速外设的长路径插一级换频率提升。插寄存器片时要注意VALID/READY的握手逻辑要正确传递不能破坏依赖关系。// 单级寄存器片VALID 走寄存器READY 组合旁路 always (posedge ACLK or negedge ARESETn) begin if (!ARESETn) begin m_valid 1b0; end else if (s_ready || !m_valid) begin m_valid s_valid; end end assign s_ready m_ready || !m_valid; // 数据路径同样打一拍 always (posedge ACLK) begin if (s_ready) m_data s_data; end这段寄存器片逻辑的关键是s_ready m_ready || !m_valid当下游准备好或本级为空时上游可以进数据。m_valid只在s_ready有效时更新。这样既切断了组合路径又不会丢握手。参数上插入位置越靠近长路径中段效果越好具体插几级要看综合后的时序报告。5.3 非对齐传输与 WSTRB 的实战处理非对齐传输是 AXI3 相对 AHB 的一个便利点主机可以直接给非对齐起始地址靠WSTRB屏蔽无效字节。但要注意非对齐只影响第一拍后续拍地址按对齐后的Aligned_Address递推。从机收到非对齐地址时第一拍的WSTRB会部分有效从机必须按WSTRB逐字节写入不能整拍覆盖。读通道没有WSTRB对应机制非对齐读由从机返回整个数据拍主机自己从正确字节位置取。如果主机访问的是 FIFO 这类读敏感设备规范明确警告不能用大于请求的突发长度去读否则丢弃的读数据会导致 FIFO 数据丢失。这一点在写 DMA 描述符时特别容易忽略。注意非对齐突发不能跨越 4KB 边界这条规则同样适用计算Aligned_Address时要确保整个突发的地址范围不越界否则从机行为未定义。本文还有配套的精品资源点击获取
返回列表