ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AXI Interconnect自动连接与参数配置实战:从Block Design到性能优化

AXI Interconnect自动连接与参数配置实战:从Block Design到性能优化 1. AXI Interconnect IP核的定位为什么项目中总绕不开它在Vivado里做FPGA设计但凡你的系统里出现一个以上的AXI主设备比如PS端、DMA、自研加速模块和多个AXI从设备比如DDR控制器、BRAM控制器、各类外设寄存器AXI Interconnect这个IP核基本就是绕不开的关卡。很多刚接触Zynq或者MPSoC的工程师第一次在Block Design里手动连线时都会被那一堆AXI端口弄得头皮发麻——S_AXI、M_AXI、S_AXI_ARESETN、M_AXI_ARESETN再加上时钟和复位密密麻麻一大片稍不注意就漏连或者连错。AXI Interconnect本质上是一个可配置的AXI交换矩阵Crossbar。它的核心职责是解决多个主机怎么共享一组从机的问题。你可以把它理解成一个带有地址翻译功能的智能交换机每个从机接口挂载一段地址区间主机发起的读写事务进来之后Interconnect根据地址译码结果把事务路由到对应的从机端口上同时完成仲裁、数据宽度转换、时钟域跨越以及协议转换。这个IP核在实际工程里最常见的使用场景有三类。第一类是Zynq系SoC的PS-PL互联PS端通过M_AXI_GP接口连接PL侧的IPAXI Interconnect负责把AXI总线扩展成多个独立通道让PS可以同时访问不同的外设第二类是纯PL侧的多主系统比如DMA控制器和CPU软核同时要读写DDR和寄存器组第三类是数据宽度适配比如DMA是64位接口DDR控制器是128位接口中间需要Interconnect做位宽转换。我在实际项目里遇到过不少同学一遇到AXI Interconnect就默认选自动连接然后点完就编译结果仿真一堆问题时序也收敛不了。其实这个IP核的自动连接功能是Vivado里最被低估的效率工具它能把原本要花半小时的手工连线压缩到几分钟但前提是你得理解它背后做了什么以及哪些配置必须在自动连接之后手动确认。这篇就把我从踩坑到熟练的完整过程拆开讲清楚。2. 自动连接的正确打开方式5分钟完成Block Design集成2.1 准备工作先把AXI端口识别清楚进入正题之前先把AXI Interconnect的端口结构捋一遍因为自动连接的核心逻辑就建立在这些端口的对应关系上。一个典型的AXI Interconnect IP核包含以下端口组S_AXI接口从机侧接口连接的是主设备Master。名字里的S是Slave的意思也就是说它是作为从机被主设备访问的这个方向经常有人搞反。M_AXI接口主机侧接口连接的是从设备Slave。M是Master代表Interconnect作为主机去发起访问。S_AXI_ACLK和M_AXI_ACLK分别对应S侧和M侧的时钟。同一个Interconnect可以接多个不同时钟域的设备这也是它的一大价值——做异步跨时钟域桥接。S_AXI_ARESETN和M_AXI_ARESETN低电平有效的复位信号分别复位S侧和M侧的逻辑。如果启用了AXI数据宽度转换还会有AXI_ACLK这样的全局时钟端口用于内部转换逻辑。只要把这些端口的对应方向搞明白后面的自动连接就不会出现插反了的问题。Vivado的自动连接工具其实非常聪明它基于IP的接口定义比如接口协议、时钟要求、复位极性来自动匹配可连接的端口但前提是你得让它在正确的上下文里工作。2.2 实际操作Block Design中的自动连接三步法下面是我在Vivado 2020.2和2022.2上都验证过的操作流程核心就三步实测从创建Block Design到完成连接5分钟足够第一步创建Block Design把需要的IP添加进来。比如做Zynq-7020的PL侧加速系统我会添加ZYNQ7 Processing System、AXI Interconnect、AXI GPIO、AXI SmartConnect备用、AXI BRAM Controller、DDR3控制器这些IP。添加完成之后先别急着点自动连接先把ILA之类的调试IP也加进来否则后面又得重新触发连接反而浪费时间。第二步在Diagram窗口中先手动把PS端的M_AXI_GP0接口和AXI Interconnect的S_AXI接口拉一条线。这一步的目的是给Vivado一个明确的提示——我要把这条AXI总线接进这个Interconnect。注意这里不要继续手动往下连把这一条主线拉通就够了后面的分支交给工具。第三步在工具栏点击Run Connection Automation弹出的对话框里会有所有待连接的接口列表。这里要重点看两个信息一个是每个接口的自动连接目标Suggested Connection另一个是连接时的时钟和复位选项。例如ZYNQ的FCLK_CLK0要勾选连到Interconnect的S_AXI_ACLK和M_AXI_ACLK复位信号勾选连到对应的ARESETN端口。检查一遍没错之后点OKVivado会在几秒内把所有的S_AXI、M_AXI、时钟、复位、以及从机的外设访问线路全部自动连好。2.3 自动连接后必须手动检查的三个地方自动连接不是万能的工具完成的只是连接这个动作但连接得对不对还是得人来把关。我每次跑完自动连接都会按固定顺序检查下面三个位置首先是交叉连接的正确性。自动连接有时会把多个主机的总线全部连接到同一个Interconnect的S端口这个逻辑没问题但如果你在一个Block Design里放了多个Interconnect比如PS和PL各自独立一套总线域工具会严格按照拓扑关系连接这时候就要检查PS的M_AXI_GP0是不是连到了Green的Interconnect而DMA的M_AXI是不是连到了另一个Interconnect。方向错了地址映射对不上后面全是问题。其次是时钟域的一致性。AXI Interconnect最大的隐性要求是同一个S_AXI接口下的逻辑接口内部逻辑、连接的从设备逻辑、以及对应地址空间内的外设必须在同一个时钟域里正常工作。自动连接默认会用同一个时钟去驱动S侧和M侧这当然没问题但如果你后续手动把某个从设备的时钟改了而Interconnect的M_AXI时钟没跟着改就会出现偶发性的数据错误而这类错误在仿真中很难复现非常折磨人。第三是外部接口的引出情况。如果某个从设备不在Block Design内部而是要通过模块端口引出到外部自动连接工具不会帮你创建端口需要手动右键对应的M_AXI接口Make External生成外部端口再在顶层HDL里连到实际的物理逻辑上。这一步经常被遗漏导致综合报unconnected port错误。3. 关键参数逐项解析别让默认配置拖垮你的性能3.1 接口协议、数据宽度和地址宽度的匹配策略双击AXI Interconnect打开配置界面第一页General里最关键的三个参数就是Interface Protocol、Data Width和Address Width。很多人的习惯是照搬默认值但默认的32位数据宽度在大多数DDR相关系统里都不够用我建议你从设计需求倒推这三个参数。数据宽度的选择逻辑其实很简单看从设备接口的最大数据位宽。比如DDR控制器通常是128位或256位那就把Interconnect的M_AXI数据宽度设为同样的宽度S_AXI数据宽度取决于主设备的接口宽度。如果主设备是64位、从设备是128位就保持两种宽度不同让Interconnect内部做宽度转换。这里有个容易犯的错误有人为了让所有端口宽度一致强行把S侧也改成128位结果DMA的64位接口连上来时协议不匹配Vivado直接报错最后还得花时间排查。宽度不一致不丢人Interconnect生来就是干这个的。地址宽度这里要特别提醒AXI总线是32位地址还是64位地址决定了对从设备的寻址空间上限。在Zynq-7000系列里PS端的M_AXI_GP口通常是32位地址PL侧的多数外设也是32位寻址这没问题。但如果你用到MPSoC的HP口或者较大地址空间的DDR区域就要把地址宽度改成64否则高于4GB的地址会被截断访问直接出错。自动连接时ZYNQ IP的接口定义里已经带了地址宽度信息工具会匹配好但如果是纯PL侧的AXI接口互连手动配置时一定要先查清楚两边的地址宽度。3.2 并发事务数与流水线寄存器性能看不见的抓手在配置界面的Read Transaction、Write Transaction这些项里有几组看着不起眼的下拉菜单直接决定Interconnect内部每个端口的并发处理能力。Outstanding transaction未完成事务数这个参数通俗说就是主设备往从设备发了一个读请求从设备处理需要几十个周期在这段时间里主设备能否继续发新的请求如果设置为1那主设备一次只能有一个请求在飞行中下一个请求必须等前一个完成总线利用率很低。如果设置为8或者16主设备可以一口气发多个请求Interconnect内部的队列会缓存这些请求按顺序或按优先级处理从设备忙的时候数据自动排队等待。那是不是设置得越大越好不是。并发事务数越大Interconnect内部需要消耗的寄存器资源和存储资源越多组合逻辑路径也会变长时序压力随之上升。在大部分设计中DMA和PS的AHB转AXI接口设置为8到16比较合理普通控制类外设设置为2到4就够。我见过有人把所有端口都设成32结果Fmax掉了几十MHz纯属自找麻烦。Lite协议AXI4-Lite是一个特例它本身不支持outstanding transaction固定为1。所以如果某个从设备只是做寄存器读写Lite接口完全够用别纠结并发数。Interconnect在针对Lite接口的通道上会自动禁用并发队列这也是为什么控制类外设挂Lite总线省资源的原因。Pipeline寄存器流水线寄存器是另一个容易被忽略的配置。我倾向于把Interconnect内部的流水线档位分成三种场景来看跨时钟域的场景建议启用流水线因为它可以打断跨时钟域的长路径组合逻辑链对时序收敛有明显帮助同频同相且对时延敏感的场景比如CPU软核访问紧耦合RAM建议把流水线设到最低减少访问时延高速数据流场景比如视频DMA建议在数据通道上启用2级流水线牺牲一点首字延迟换取更高的吞吐率稳定度。3.3 地址映射的正确姿势Address Editor里的学问地址映射是AXI Interconnect使用中的另一个重头戏。自动连接完成后Vivado会为每个从机分配一个默认的地址段但这个默认地址未必合理必须手动调整。在Block Design的窗口下方切到Address Editor标签页可以看到Interconnect的M_AXI端口下挂着所有从设备每个从设备都有对应的地址偏移Offset和地址范围Range。这里的设置逻辑是Offset是Interconnect发给这个从设备的基地址从设备内部寄存器或存储空间映射在基地址偏移量之上。比如一个挂BRAM Controller的从设备分配了0x0000_0000到0x0000_FFFF的64KB空间那么基地址就是0x0000_0000BRAM内部地址从0开始。多个从设备之间绝对不能有地址重叠。Vivado的地址编辑器会在有重叠时给出红色错误提示但根据不同IP的默认地址偶尔会出现看似没报错、实际地址区间互相咬边的情况特别是当你手动改过Range之后。我的习惯是每个从设备分配完地址后把所有从设备的地址范围加一遍确认总和不超过主设备的地址空间再检查任何两个区间无交集。这一步马虎一次后面在硬件上调试时查一天都未必找得到问题。地址映射还会影响自动连接的效率。比如ZYNQ的PS端PL侧的AXI外设一般分配在高位地址区比如0x4000_0000往上方便和PS内部的DDR地址空间避开。这样PS访问PL外设时地址译码路由清晰Interconnect内部的地址比较逻辑也更简单。反过来如果外设地址挤在DDR空间中间Interconnect虽然也能工作但每次事务都要做大范围地址比较路径延迟会变长。4. 优化配置思路从能用到好用4.1 时钟拓扑设计别让Interconnect承担太多跨时钟任务AXI Interconnect的跨时钟能力很容易让人产生依赖性动辄就把所有异步模块都接到同一个Interconnect上让它去统一处理时钟跨越。从功能性角度讲它确实能做到但从时序和面积的角度讲这不是一个好方案。一个完整的AXI事务包含五条通道写地址、写数据、写响应、读地址、读数据。每一条通道跨时钟域时Interconnect内部都需要一套同步逻辑如果五个通道全部跨时钟资源消耗直接翻倍甚至更多。更致命的是跨时钟域的数据路径上每个通道都可能出现气泡bubble也就是等待同步完成产生的空周期整体事务时延会被拉长。我的实践原则是尽量让数据量大、频率高的通道在同一个时钟域里不要让高吞吐路径跨时钟。比如视频DMA的数据流如果和DDR控制器在不同时钟域与其让Interconnect去处理不如把DMA和DDR放在同一个时钟组里用Clocking Wizard统一生成只在控制通道上保留跨时钟能力。这样Interconnect内部的跨时钟域逻辑只作用于低频率的配置寄存器访问性能损失可以忽略。如果实在躲不开必须让Interconnect跨时钟那么配置上有一个隐蔽而重要的选项在Interconnect的每个S_AXI接口配置里有一个Enable Clock Conversion启用时钟转换选项。这个选项默认是关闭的但当你把S_AXI时钟和M_AXI时钟接成不同频率时Vivado会建议你开启。我建议是明确知道自己要跨时钟就手动打开如果两个时钟实际同源同频就保持关闭避免白白增加额外的同步逻辑。4.2 数据宽度转换的代价读透翻译官的工作方式数据宽度转换是AXI Interconnect的绝活但它也是资源消耗的主要来源之一。一个64位主设备访问128位从设备Interconnect内部做的事情是写数据时把64位数据按字节掩码拼成128位等待凑够一次完整写入读数据时把128位读结果拆成两次64位返回。实际使用中这个转换过程对吞吐量的影响主要体现在跨周期边界的时候。比如DMA以64位突发burst方式写DDRInterconnect接收到突发长度16的64位写数据内部会重新打包成突发长度8的128位写数据再发给DDR控制器。这个过程流水化处理得好几乎没有额外气泡但如果主设备的突发长度和从设备的宽度不匹配比如突发长度是奇数就会出现最后一个周期只写半个数据、还要等下一个事务的情况效率大幅下降。我的建议是需要做数据宽度转换时尽量让主设备的突发长度是转换倍数宽度比的整数倍。64位转128位时突发长度用8、16、24这样的偶数64位转256位时突发长度用4、8、16这样的4的倍数。这个听起来有点吹毛求疵但在跑高速DDR访问时实测吞吐率能差出10%到15%值得提前规划。4.3 缓存与先进先出Interconnect的隐藏配置项在Interconnect的接口级配置里还有一组Options for S_AXI和Options for M_AXI标签页里面有几个不显眼的选项值得专门调一调。S_AXI侧的Write Data FIFO Depth写数据FIFO深度和Read Data FIFO Depth读数据FIFO深度决定每个从端口的数据缓存能力。默认深度一般是32但这个值对于高速DMA场景来说偏浅。我看过不少公司的代码DMA到DDR的路径上写FIFO深度只有32结果DMA一个突发还没发完FIFO就满了总线效率卡在70%左右上不去。把深度改成64或128吞吐率立刻回升代价是多用几个BRAM性价比完全划算。但是FIFO深度不是越大越好因为它会增加数据路径上的延迟。对于控制类外设如GPIO、定时器数据流量小FIFO深度保持默认或降低到一个更小的值比如16都可以没必要浪费存储资源。判断标准就一句话流量大的端口给大缓存流量小的端口给小缓存。还有一个Enable Register Slicing启用寄存器切片的选项组包括Write Data、Read Data、Write Channel、Read Channel四个方向。寄存器切片本质上是在长路径中插入流水线寄存器打断组合逻辑链路提升时序收敛能力。启用切片后信号的延迟会增加一个周期左右但对几百MHz以上的高速总线来说多一个周期的延迟换来的是时序收敛这笔交易是划算的。如果设计跑在100MHz以下且时序余量充足就没必要开切片保持最低延迟。5. 常见问题与排查技巧实录5.1 自动连接后触发器IO口飞出外部端口没有引出这是我在Zynq项目里遇到最多的自动连接后遗症。现象是综合时报大量unconnected port警告或者生成的HDL顶层里多了一堆没有连接的端口。原因往往是自动连接时工具检测到S_AXI或M_AXI接口没有配对对象就直接把它们作为外部端口引出了而不是报错。排查方法很简单在Diagram窗口里查看那些多出来的端口确认它们的类型和方向。如果是AXI接口误被引出找到对应的IP确认是否需要在内部连接如果是BLOCK设计确实要对外提供AXI接口比如你的设计本身就是做一个AXI外设那就保留端口并到顶层做好连接同时确认时钟和复位端口也被正确引出。5.2 仿真全零地址映射错误导致的事务接收方异常情况是仿真时主设备发读写请求从设备响应全零。逐一排查下来时钟复位都正常但地址映射表里分配了重叠区域或者漏掉了某个区间。Interconnect收到地址后发现没有匹配的从设备区间就会执行默认行为——返回一个错误响应或者IDLE表现出来就是数据全零。这种问题在Block Design里经常藏在Address Editor的边界缝里我建议在仿真前用Vivado的Address Editor自动重排功能刷新一遍地址表再手动检查高亮区域是否存在重叠基本可以避免后续头大的调试。5.3 性能上不去FIFO深度和并发数拖了后腿某次项目DMA读DDR的实测带宽只有理论值的60%读写路径上的FIFO深度都是默认32并发事务数是4。把读FIFO深度调到128、并发事务数调到16之后实测带宽恢复到理论值的90%以上。这个案例说明性能优化要先从这些关键参数入手而不是一上来就去堆DDR控制器的效率。5.4 时序违例与Conbination LoopInterconnect不是万能背锅侠AXI Interconnect本身是一个复杂的组合逻辑实体优化不到位时很容易在Interconnect内部的长路径上出现减少了几十MHz的Fmax。如果你在Timing Summary里看到一条路径起点是Interconnect的某个S_AXI接口终点是Interconnect内部逻辑块大概率是组合逻辑加数据宽度转换加多个FIFO级联造成的。碰到这种情况我不建议直接把整个Interconnect换掉或者大改架构先尝试开启寄存器切片。如果加了切片还是不收敛检查一下有没有冗余的数据宽度转换——比如你的主设备和从设备其实同宽却在中间串了两个Interconnect叠变换这种链路设计在早期规划时容易埋雷。大部分时序问题在经过这几步调整后都能明显缓解。5.5 遇到SmartConnect何时选它作为替代方案Xilinx后来推出的SmartConnect在不少场景下比AXI Interconnect更省心但它也不是全能的。我在多个项目里做过对比如果系统里有大量AXI接口要做地址映射和自动连接SmartConnect的姿态是零配置起步对标准的地址映射和时钟分配处理得非常聪明。但如果你需要对数据宽度转换做精细控制或者希望显式控制每个端口的FIFO深度和切片策略AXI Interconnect反而更透明。从时序角度看SmartConnect在部分大位宽转换场景下资源更省、时序更好但在低延迟控制路径上有时候略逊色于手调过的Interconnect链条。我的经验是纯PL侧的高频数据流优先用AXI Interconnect手调参数Zynq PS侧的通用互联SmartConnect是默认更省心的选择。两者的自动连接机制类似但SmartConnect的默认参数更激进一些不适合作为无脑替换的选项。6. 一些我自己总结的实操心得最后专门写一小节给那些时间紧、任务重不想读文档只想抄作业的工程师。我做了几年FPGA在AXI Interconnect上踩过的坑不少总结下来有下面几条可以避坑的个人经验。第一不管项目多急第一次跑自动连接之前先花两分钟想清楚系统拓扑主设备是谁从设备是谁哪些走高速数据哪些走控制寄存器。方向错了自动连一万次也白搭。第二自动连接完成后打开Address Editor看一眼地址分配顺手把地址编得规整一点按外设功能分组留好扩展空位这个习惯在后期调试时特别有用因为Xilinx的硬件管理器、SDK/ Vitis里的基地址都跟这里一致编乱了到时候找寄存器全靠翻代码。第三Interconnect的配置改完之后建议重新检查一遍跨时钟路径。有一个坑是你改了某个S入口的时钟线但Interconnect的异步逻辑还认为两边同频导致仿真通过、上板偶发数据错误。解决的办法其实很简单修改时钟拓扑后删掉Interconnect重新生成一次让Vivado重新自动配置比手动抠配置项更靠谱。第四调试AXI总线问题ILA一定要加在足够靠近Interconnect的位置。我习惯在Interconnect的M_AXI端口挂ILA它会比挂在外设端更容易定位到仲裁、路由、地址匹配这些问题。插上JTAG跑一轮硬件调试用Vivado的逻辑分析仪抓波形别一上来就怀疑DDR控制器先看总线协议层有没有毛刺。第五最后一个值得花时间做的是每接触一个新板卡或新项目先花半天时间做一个最小的AXI Interconnect读写测试工程用Vivado的自动连接把PS、Interconnect、BRAM Controller、ILA串起来跑一次硬件读写验证。这个工程虽然小但它是你后续所有工作的金标准CPU软核、DMA、中断这些功能都是在这个基础上长出来的。AXI Interconnect虽然名字听着复杂但一旦你理解了它的定位——一个会做地址翻译、仲裁和协议转换的智能交换矩阵——它的配置项就不再是玄学。自动连接省下的是连线时间而配置优化比拼的才是对系统整体的理解。希望在读完这篇之后你再打开Vivado跑自动连接能比之前的自己多几分把握。
返回列表