资讯动态

AXI4总线协议实战:握手机制、死锁规避与Master/Slave设计

发布时间:2026/10/15 8:39:08 来源:尧图企业网站定制
简介精选自网络的AXI4总线协议详解文档面向SoC设计工程师、FPGA开发者和嵌入式学习者系统梳理AMBA协议家族中应用广泛的AXI4规范。文档从官方手册出发完整覆盖读地址、读数据、写地址、写数据、写回应五个独立通道的信号定义与握手机制并结合ZYNQ中ARM与FPGA交互的实际场景解析突发传输、非对齐数据传输、乱序收发等特性特别对写回应通道为何独立给出深入分析便于透彻理解协议核心。资源为单个docx文档压缩包约3.27MB内容先总览通道信号再详解VALID/READY握手时序条理清晰适合协议学习与项目开发参考。已有418人学习下载来自网络的精选整理值得SoC入门及进阶者收藏。1. AXI4总线协议片上互连的事实标准也是新手最容易卡死的地方“AXI4总线协议”这几个字在FPGA/ASIC招聘里出现率极高但真正见过它翻车现场的人才知道它和普通寄存器读写接口差在哪。AXI4把一次读写拆成地址、数据、响应三个独立通道允许大量事务同时在总线上飞行吞吐确实高代价是握手规则一旦写错总线不是变慢而是直接死锁——两边都在等对方先动谁都不让。网上精选的AXI4资料大多停在波形图层面讲清楚“为什么卡死、怎么排查、参数怎么定”的很少。这篇笔记写给要上手AXI4的工程师用最小可用的Master和Slave示例讲清实现路径、参数取舍和典型坑方便你照着改、照着验。2. 五个通道与握手机制VALID/READY谁先谁后决定了总线会不会卡死AXI4属于片上总线AMBA协议家族的第4代是一种主从多点互联协议。理解它不需要背信号表抓住“通道”和“握手”两个概念就够了。五个通道分别是写地址AW、写数据W、写响应B、读地址AR、读数据R通道之间相互独立各自有自己的VALID/READY握手信号。读事务只走AR和R两个通道写事务则要经历AW、W、B三段。通道的独立性是AXI4高性能的根源Master可以在写地址还没握手完成时就把写数据发出去也可以同时挂多个读请求在总线上飞行。这种并行能力让AXI4能支撑高带宽场景但也让调试难度上升。很多初学者的第一个死锁就是把五个通道当成一个顺序接口来处理在代码里加了莫名其妙的依赖。2.1 读事务AR通道发起、R通道回数闭环比想象中简单一次读事务由Master先发ARVALID和ARADDR。Slave收到地址并握手ARVALID和ARREADY同拍为高后开始准备数据。随后数据通过R通道返回每拍一组RDATA通道上还带RLAST标记最后一拍。Master等到RVALID与RREADY握手完成且RLAST为高这笔读事务才算结束。这里有一个新手容易误解的点AR通道握手完成后R数据不会立刻出现。Slave可能延迟几个周期甚至几十个周期才返回第一笔数据也可能在返回过程中暂停。只要Slave保证“RVALID一旦拉高直到本笔事务最后一拍握手完成前不能撤销”中间插几个空拍是允许的。所以Master写读逻辑时不能假设“发了地址下一拍必有数据”必须用状态机或计数器等RVALID。读事务还有一个隐含的保序规则同一个ARID上发出的多个读请求返回的R数据必须按发起顺序返回。这是AXI4协议层面保证的。如果Master用同一个ID连续发两个读请求Slave返回时不能把第二笔的数据先送回来。如果Slave不守这条规矩Master就必须能在ID匹配之外做重排序工程上通常直接用FIFO保存ARID和返回数据的对应关系。通道方向Master视角作用关键信号读地址ARMaster → Slave发起读请求携带地址、长度、大小、突发类型ARADDR、ARLEN、ARSIZE、ARBURST、ARVALID、ARREADY读数据RSlave → Master返回读数据携带响应状态和最后一拍标记RDATA、RRESP、RLAST、RVALID、RREADY写地址AWMaster → Slave发起写请求携带地址、长度、大小、突发类型AWADDR、AWLEN、AWSIZE、AWBURST、AWVALID、AWREADY写数据WMaster → Slave传输写数据和字节使能最后一拍置WLASTWDATA、WSTRB、WLAST、WVALID、WREADY写响应BSlave → Master返回写事务完成状态BRESP、BVALID、BREADY2.2 写事务AW、W、B三段式B响应不能抢跑写事务比读事务多一条响应通道B。Master先发AW再发W数据Slave收完数据后返回BVALID和BRESP。三步之间没有严格的先后关系AW和W可以同时发起甚至可以不等AW握手完成就把W发出去因为Slave内部会自己处理地址与数据的匹配。真正严格的一条是Slave必须收到W通道最后一拍WVALID、WREADY、WLAST三者同时为高之后才能返回BVALID。这条约束经常被写Slave的人忽略。有些Slave为了“省事”一看到AWVALID就立刻回BVALID仿佛写事务已经完成。在单拍、无等待的场合可能碰巧能跑一旦Master发出多拍burst数据还没送完Slave就回了响应Master就会认为整笔写已完成后续数据全部错位。正确的做法是把“最后一拍W数据到达”当作生成BVALID的唯一触发条件。B通道响应本身也有RESP[1:0]常用值是OKAY和SLVERR。如果Slave发现地址非法、写保护等异常情况可以返回SLVERR。注意RESP是随BVALID一起给出去的不是可选的附加信息。Master拿到BVALID且BREADY为高后要采样BRESP判断这笔写是否真的成功。2.3 握手的4条规则与死锁路径没人是“先动”的总线就停了AXI4所有通道的传输都建立在VALID/READY握手上。规则一共4条前两条管发起方后两条管接收方。第一源端一旦拉高VALID就必须保持到握手完成不能中途撤下。第二源端不能等待READY为高才拉VALID也就是说VALID的产生不能依赖于对READY的采样结果。第三目的端的READY可以在VALID拉高之前就保持为高称为提前就绪也可以看到VALID后再拉高。第四无论哪种方式VALID和READY之间不能形成组合逻辑环路。死锁的典型路径是这样的Master写内部信号“if (ready) valid 1”Slave写“if (valid) ready 1”。仿真波形上看两个信号在时钟上升沿处互相看着对方谁都先不变高握手永远完成不了。更隐蔽的版本是跨模块的组合环路Master的VALID由Slave的READY组合产生Slave的READY又由Master的VALID组合产生中间插入了几级组合逻辑表面看波形有变化实际上形成了振荡或亚稳态。排查这类问题最直接的办法是在仿真波形里找到“握手信号长期只有一方为高”的窗口再看它们各自是由什么信号触发的。只要发现某个VALID的逻辑表达式里出现了对应的READY基本就是依赖反了。3. 从零写一个AXI4写Master最小状态机、握手细节与参数配置这一章直接给代码。目标是用Verilog/SystemVerilog实现一个能完成单笔INCR突发写事务的最小Master支持可配置的突发长度。代码刻意不用AXI3的写交织也没有outstanding能力先把一笔事务跑通再看怎么把流水线打开。3.1 状态机选型先写串行AW→W→B再谈全流水工程上写AXI4 Master常见的做法是先搭一个串行状态机把事务拆成“发地址—发数据—收响应”三个状态。这样做吞吐不是最高的但每个状态只关心一个通道调试时波形一眼能看懂。// AXI4 写事务主端状态机一次INCR突发写长度可配 module axi4_wr_master #( parameter ADDR_WIDTH 32, parameter DATA_WIDTH 32, // 8/16/32/64/128要和SIZE匹配 parameter ID_WIDTH 4 )( input logic ACLK, input logic ARESETn, // 与上层应用之间的简单请求接口 input logic wr_req, input logic [ADDR_WIDTH-1:0] wr_addr, input logic [7:0] wr_len, // 突发长度-10表示1拍255表示256拍 output logic wr_done, // AXI4 写地址通道 AW output logic [ID_WIDTH-1:0] awid, output logic [ADDR_WIDTH-1:0] awaddr, output logic [7:0] awlen, output logic [2:0] awsize, output logic [1:0] awburst, output logic awvalid, input logic awready, // AXI4 写数据通道 W output logic [DATA_WIDTH-1:0] wdata, output logic [DATA_WIDTH/8-1:0] wstrb, output logic wlast, output logic wvalid, input logic wready, // AXI4 写响应通道 B input logic [ID_WIDTH-1:0] bid, input logic [1:0] bresp, input logic bvalid, output logic bready ); typedef enum logic [1:0] { S_IDLE 2d0, S_AW 2d1, S_W 2d2, S_B 2d3 } state_t; state_t state; always_ff (posedge ACLK or negedge ARESETn) begin if (!ARESETn) state S_IDLE; else begin case (state) S_IDLE: if (wr_req) state S_AW; // 收到请求先发地址 S_AW: if (awvalid awready) state S_W; // 地址握手完成再发数据 S_W: if (wvalid wready wlast) state S_B; // 最后一拍写完成等响应 S_B: if (bvalid bready) state S_IDLE; // 响应收到写事务结束 endcase end end这段代码里S_AW到S_W的跳变依赖awvalid与awready同时为高S_W到S_B的跳变要求wvalid、wready、wlast三个信号同时有效。这里特意让AW先完成再发数据牺牲了一点并发换取状态清晰。实际产品里AW和W可以并行发起状态机也可以拆成两个独立进程分别控制AW和W通道互不等待性能会好很多。初学者先把串行版本跑通再改并行能少踩很多坑。wr_len参数是“长度减1”这是AXI4协议本身的规定。想写4个32位字wr_len填3只写1个字wr_len填0。代码里AWLEN直接赋值wr_len所以上层给参数时务必按“减1”后的值传入。这个约定是AXI4里最容易被忽略的细节后面避坑章节会再展开。3.2 W通道与WLAST生成burst计数器怎么算才不出错W通道的难点在WLAST的生成。WLAST必须与最后一拍数据同拍为高提前一拍或延后一拍都会让Slave的B响应逻辑错乱。计数器wcnt记录的是“当前正在发送第几个数据”它与wvalid、wready握手同步递增。// W通道控制burst计数与WLAST生成 logic [7:0] wcnt; logic w_active; assign w_active (state S_W); always_ff (posedge ACLK or negedge ARESETn) begin if (!ARESETn) begin wvalid 1b0; wcnt 8h00; end else if (state S_IDLE wr_req) begin wvalid 1b1; // 请求有效允许发数据 wcnt 8h00; end else if (w_active wvalid wready) begin if (wlast) begin wvalid 1b0; // 最后一拍被接收W通道结束 end wcnt wcnt 1b1; // 每完成一拍计数加1 end end // WLAST当前拍计数等于AWLEN即为最后一拍 assign wlast (wcnt awlen); assign wdata wr_data_ram[wcnt]; // 从用户侧RAM读数据 assign wstrb {DATA_WIDTH/8{1b1}}; // 本例全字节使能这段逻辑的关键在于wcnt和wlast的配合。假设awlen3表示共4拍数据。起始wcnt0发送第0拍时wlast为0握手完成后wcnt变1发送第1拍时wlast仍为0直到wcnt3时wlast拉高这一拍握手完成后wvalid清零状态机进入S_B。整个过程中wlast和最后一拍数据正好出现在同一拍没有偏移。常见错误是把wlast写成“wcnt awlen - 1”这样会在倒数第二拍就拉高Slave提前返回B响应Master的数据还差一拍没发完整笔事务错位。另一个常见错误是在非握手周期也让wcnt递增比如把wcnt放在固定的时钟计数里结果wready为低时数据没被接受计数却走了整个burst长度全部漂移。记住AXI4的计数器只跟着握手走不接受的数据不算数。3.3 参数决策ID、SIZE、BURST与数据宽度怎么配B通道的接收逻辑相对简单。Master端bready可以保持常高表示随时准备接收响应每次bvalid与bready同拍为高就把bresp采样下来并给应用层一个wr_done脉冲。// B通道采样写响应并上报完成 logic [1:0] bresp_q; always_ff (posedge ACLK or negedge ARESETn) begin if (!ARESETn) begin bresp_q 2b00; end else if (bvalid bready) begin bresp_q bresp; // 记录响应状态必要时上报异常 end end assign bready 1b1; // Master始终准备好接收响应 assign wr_done (state S_B) bvalid bready;wr_done是单拍脉冲在响应握手完成的同一拍拉高。如果你的应用层需要一个“持续到下一笔请求开始”的电平信号可以把wr_done寄存一拍再输出或者改成置位/清零模式。参数配置方面几个最常用的参数选择和理由如下表参数取值范围选型建议DATA_WIDTH8的整数倍常用32/64/128决定单拍吞吐128位总线在FPGA里布线压力明显增大按实际带宽需求选AWLEN0~255表示突发长度减1INCR突发最多256拍AWSIZE0~72^SIZE表示每拍字节数务必与DATA_WIDTH匹配例如32位总线配3b010AWBURST2b00/01/10常用INCR(2b01)FIXED适合FIFO口WRAP适合cachelineID_WIDTH视outstanding深度而定串行单事务用4位就够要挂多个outstanding事务ID位宽要对应用例数这里有个血泪经验SIZE和DATA_WIDTH不匹配是最隐蔽的配置错误。比如数据总线是64位但SIZE配成了3b0118字节这恰好匹配。如果总线64位却配了3b0104字节Slave会认为每拍只传输低4字节有效地址递增逻辑也会按4字节跳数据全部错位。AXI4没有机制帮你检查SIZE与总线宽度的匹配关系仿真时波形看起来每拍都在传输就是数据不对排查起来非常痛苦。4. 把Slave接进AXI4总线地址译码、响应生成与寄存器映射Master写完了总得有个Slave接着。实际项目里Slave往往是自己写的寄存器堆、FIFO、SRAM控制器或者某个外设接口。这一章讲最常用的寄存器型Slave怎么接AXI4重点在地址译码和B响应生成。4.1 地址译码与寄存器映射先定地址空间还是先定对齐地址译码是Slave设计的第一步。常见做法是划出一段连续的地址空间用高几位地址做片选低几位做寄存器偏移。比如32位地址总线用bit[31:28]区分4个Slave每个Slave占256MB空间内部再用bit[7:0]访问寄存器。// 从写地址译出Slave选通 wire hit_slave0; wire hit_slave1; assign hit_slave0 (awaddr[31:28] 4h1); // 0x1000_0000 ~ 0x1FFF_FFFF assign hit_slave1 (awaddr[31:28] 4h2); // 0x2000_0000 ~ 0x2FFF_FFFF译码越简单越好。用高4位译码每个Slave地址空间大寄存器偏移直接在低28位里算用高12位译码则可以把空间切得更细但组合逻辑会变长时序压力上升。对于寄存器型Slave高4位或高8位译码是常见选择。地址对齐要结合AWSIZE一起看。如果Slave的数据总线是32位每次读写的有效数据是4字节那么地址的低2位必须为0。Master发地址时如果违反对齐Slave要么返回SLVERR要么自己截断。工程上常见的做法是Slave内部不处理非对齐地址直接在译码时把低2位忽略同时通过RESP返回SLVERR告知Master地址非法。寄存器映射表建议在RTL里用宏或参数统一管理不要散布在代码里。以下是一张典型的映射表寄存器名偏移地址读写属性作用说明CTRL0x00读写控制启动/停止bit0为启动位STAT0x04只读状态寄存器bit0表示忙/闲DATA00x08读写数据寄存器0按字对齐DATA10x0C读写数据寄存器14.2 写响应生成必须等最后一拍W不能提前也不能超时Slave的B响应逻辑是最容易写错的地方。正确的触发条件是检测到W通道最后一拍握手wvalid为高、wready为高、wlast为高。三者缺一不可。// Slave侧W数据接收与B响应生成核心段 logic w_last_hit; assign w_last_hit wvalid wready wlast; // 写数据最后一拍完成 logic bvalid_r; logic [1:0] bresp_r; always_ff (posedge ACLK or negedge ARESETn) begin if (!ARESETn) begin bvalid_r 1b0; bresp_r 2b00; end else if (w_last_hit) begin bvalid_r 1b1; // 最后一拍到达允许返回B响应 bresp_r 2b00; // 默认OKAY end else if (bvalid_r bready) begin bvalid_r 1b0; // 响应握手完成撤下BVALID end end assign bvalid bvalid_r; assign bresp bresp_r;这段逻辑里bvalid_r一旦置高会保持到bready返回。如果Master一直不拉BREADYbvalid就会一直为高这是AXI4协议允许的不会造成问题。但如果Slave在w_last_hit后的下一拍又把bvalid置低了Master可能采样不到这笔写的响应就会丢失。值得强调的是B响应不应带超时逻辑。有些工程师习惯在Slave里加一个计数器超过N拍没收到W数据就强制返回BVALID——这在AXI4里是错误做法。协议要求B响应只能由W数据完成触发超时返回的BVALID会让Master误认为数据已经写入。如果确实担心Master发数据不完整正确做法是在Master侧加超时看门狗而不是在Slave侧造假响应。4.3 多个Slave与AXI互联什么时候该用现成互连IP当总线上有多个Master和多个Slave时必须有一个互连结构来路由请求。常见的做法是采用AXI交叉开关Crossbar或AXI数据通路IP而不是自己写全交叉逻辑。交叉开关负责地址译码、请求路由、响应返回和仲裁。选择现成互连IP还是自己写的判断标准很简单只要出现两个及以上Master或者Slave数量大于等于3建议直接用现成IP。自己写全交叉的最大问题不是功能而是仲裁策略和时序收敛。多Master并发访问同一Slave时仲裁要处理优先级、公平性和outstanding深度任何一处考虑不周都会在极低概率的并发场景下暴露问题这种问题仿真很难复现。如果只有一个Master访问多个Slave可以考虑自己写一个轻量级译码器把AW、W、AR、R、B五组信号分别做MUX。每个Slave的地址区间独立互不重叠仲裁规则简化为“同一时刻只有一个Slave被选中”。这种结构在中小规模设计里足够用而且代码完全可控调试方便。等将来Master数量变多再切换到现成互连IP。5. AXI4实战避坑五条典型的握手死锁与响应丢失记录下面五条都是从实际调试里沉淀下来的问题每条按“现象→原因→解决”展开希望能让你少走弯路。5.1 地址对齐与BURST配置错回读数据错位现象连续读4个32位寄存器前两个地址返回的数据正确后两个全部错位。用ILA抓波形每次读请求的ARADDR都正常递增R通道数据也有RLAST看起来一切正常。原因ARSIZE配置成了3b0104字节但地址低2位没有对齐。比如第二个寄存器地址是0x04第三个是0x08如果Master在计算地址时把偏移直接相加而忽略了总线宽度就会从0x05开始读数据整体偏移了一个字节。另一个隐蔽原因是BURST类型配成了FIXED地址不递增每拍都访问同一个地址读数自然全部是同一个值。解决先确认DATA_WIDTH与SIZE匹配再确认起始地址按SIZE对齐。对于32位总线、SIZE4字节的场景起始地址低2位必须是00。INCR突发下地址按“每拍2^SIZE字节”递增不能用“地址加1”的方式生成下一拍地址。建议在验证环境里加一个地址递增的断言专门检查相邻两拍地址差是否等于2^SIZE。5.2 WLAST缺失或错拍写响应永远不来现象应用层发完写请求后B通道一直没有响应总线级的超时计数器先报警。抓波形发现W通道数据早就发完了但wvalid一直为高wready也一直为高事务就挂在那里。原因WLAST没有在最后一拍拉高而是晚了一拍。Slave判断“最后一拍数据完成”依赖wlastwlast不拉高Slave就不认为写数据结束自然不会返回BVALID。很多Master代码的WLAST由组合逻辑生成但生成条件里用了握手后的计数结果导致WLAST和数据错开了一拍。解决务必在仿真波形里把WLAST和最后一笔WDATA放在同一拍对齐检查。可以用一条断言wlast为高时wvalid必须为高同时这一拍握手完成后burst计数器应当清零。调试时也可以临时把Slave的B响应触发条件改成“不依赖wlast收到固定拍数就返回”但这只能用来确认通路最终必须改回协议正确写法。5.3 VALID/READY互相等待总线一上电就卡死现象仿真从复位结束后第一个写事务的AWVALID和AWREADY都保持为低等了上千个周期仍然没有变化。波形放大后看到两个信号层层依赖没有一个主动发起。原因Master内部用“if (awready) awvalid 1”的逻辑产生握手Slave内部又用“if (awvalid) awready 1”的逻辑产生就绪。两边都在等对方先拉高形成典型的互相等待死锁。这类问题在RTL仿真里表现为时序不推进上板后表现为模块像死机一样无响应。解决按第2章的握手四规则改代码。VALID永远由内部状态或请求条件触发等待与READY无关READY可以常高也可以等看到VALID后再拉高但READY逻辑里不能反向依赖另一个通道的VALID。如果为了低功耗想在无事务时不拉READY也要保证READY的产生只依赖本通道的VALID或内部状态不能串到对方通道上。5.4 同一ID多个未完成请求返回数据张冠李戴现象Master发出两个连续读请求ARID都是0。仿真时发现第二笔读的返回数据先到第一笔的反而后到上层逻辑把两笔数据用反了。原因AXI4协议要求同一ID的读响应必须按发起顺序返回但某些Slave或互连IP没有严格实现这个保序或者Master自身的返回匹配逻辑用了简单的“谁先握手谁先取数”方式没有按ID和顺序做匹配。如果Master发出outstanding请求时全部复用同一个ID就无法区分返回数据属于哪一笔事务。解决要么不做outstanding一笔读完成后再发下一笔ID固定一个值简单可靠要么使用不同ID区分在多笔outstanding事务返回时按ID匹配配合FIFO保存请求顺序。第一种方案吞吐低第二种方案逻辑复杂。工程上两者都常见关键是要先评估性能需求不要为了那点吞吐把验证成本堆上去。5.5 跨时钟域直接打拍同步偶发丢数据现象AXI4接口的时钟与内部逻辑时钟不同设计里用两级触发器对AXI4的VALID和DATA分别打拍。功能仿真偶尔通过上板后低频偶发地丢一拍数据或数据错位用ILA多次触发才抓到一次。原因AXI4本身没有内建跨时钟域机制它的VALID、READY、DATA之间存在严格的同拍关系。两级触发器同步只能处理单bit信号对多bit的DATA各自打拍后组合回同一拍时可能采样到新旧混合的数据。VALID的抖动也可能产生虚假握手让总线状态错乱。解决跨时钟域接入AXI4时不要对单个信号打拍正确的做法是让AXI4接口整体工作在一个时钟域内跨时钟边界处用异步FIFO或同步FIFO做数据缓冲把AXI4事务完整拆成“写入侧”和“读出侧”两侧各自锁存。这里有个常见误用两个时钟频率相同但相位不同有人直接打拍同步这同样会偶发错拍正确做法是同步FIFO加上握手缓冲而不是对每个信号分别同步。6. 验证与性能优化用断言锁协议把事务流水线跑满AXI4的验证不能只靠人工看波形信号太多、通道并行肉眼很难覆盖到边界情况。我的做法是两层第一层加协议断言第二层加握手计数器和超时看门狗。协议断言推荐从三条开始写。第一条检查AW握手必然完成第二条检查WLAST与WVALID同拍第三条检查B响应不能在WLAST之前出现。这三条覆盖了写通道最核心的协议红线。// 最值得加的3条AXI4断言SystemVerilog // 1) AWVALID拉高后握手必须在有限时间内完成 property p_aw_handshake; (posedge ACLK) disable iff (!ARESETn) $rose(AWVALID) | ##[1:$] (AWVALID AWREADY); endproperty assert property(p_aw_handshake); // 2) WLAST必须与WVALID同拍 property p_wlast_with_wvalid; (posedge ACLK) disable iff (!ARESETn) WLAST |- WVALID; endproperty assert property(p_wlast_with_wvalid); // 3) 写响应不得早于最后一次写数据握手 sequence s_w_last_hit; WVALID WREADY WLAST; endsequence assert property((posedge ACLK) disable iff (!ARESETn) BVALID |- s_w_last_hit.triggered);断言的作用是把协议约束写成机器可查的逻辑跑仿真时一旦违反立刻报错。不要贪多先保证这几条在所有测试用例里持续运行比堆几十条断言更有价值。性能优化方面AXI4最大的潜力在outstanding。串行写事务每笔至少要经历“地址握手数据穿梭响应返回”三段响应等待期间总线是空的。打开outstanding后Master可以连续发多个AW和W不等上一笔B响应就发起下一笔。理论上当总线宽度为128位、突发长度为256拍时数据通道可以做到几乎每拍都有效事务间的地址和响应开销被完全掩盖。判断性能是否到位可以先量一笔写事务的最小拍数。传输N字节数据理论最小拍数为数据拍数加上地址和响应各一拍。如果测出来的吞吐远低于这个值优先查两处Master是否在AW握手完成前不发起下一笔Slave的B响应是否有额外延迟。这两个位置通常是流水线断点。我现在收一个新AXI4模块的习惯是先不优化用串行Master把读写跑通记录实际吞吐再加上断言和看门狗跑一晚上随机测试确认协议稳定后再打开outstanding每开一档性能就重跑一遍回归。某次项目里我把读ID拆成4个独立ID来提升乱序容忍度结果性能没涨多少验证环境却多了一堆重排序逻辑后来退回单ID串行读吞吐反而更可控。AXI4很多时候不是协议难是“够用就好”这四个字最难。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑