計(jì)全解析:從算法策略到協(xié)議約束與調(diào)試實(shí)戰(zhàn))
AXI總線仲裁器這個(gè)話題說實(shí)話是很多做SoC集成和FPGA開發(fā)的同事容易忽略又不得不面對(duì)的東西。剛開始接觸AXI的時(shí)候可能大家都會(huì)把精力放在valid/ready握手、outstanding傳輸、亂序返回這些協(xié)議細(xì)節(jié)上但一旦系統(tǒng)里掛了多個(gè)master——比如CPU、DMA、以太網(wǎng)MAC、USB控制器——你會(huì)發(fā)現(xiàn)總線仲裁器的設(shè)計(jì)直接決定了整個(gè)系統(tǒng)的帶寬分配和延遲表現(xiàn)。這篇是“AXI協(xié)議理解”系列的第一篇專門把仲裁器這塊拆開講清楚它到底解決什么問題、常用的仲裁策略有哪些、AXI協(xié)議給仲裁器設(shè)計(jì)埋了哪些坑、以及我自己在實(shí)際項(xiàng)目里踩過的雷。適合剛?cè)腴TAXI的FPGA/IC工程師也適合做了幾年集成但沒仔細(xì)摳過仲裁細(xì)節(jié)的朋友。1. 為什么AXI總線需要仲裁器1.1 AXI總線的基本結(jié)構(gòu)與仲裁器位置AXIAdvanced eXtensible Interface是ARM AMBA協(xié)議家族里的高性能總線協(xié)議它的核心特點(diǎn)是通道獨(dú)立讀地址通道AR、讀數(shù)據(jù)通道R、寫地址通道AW、寫數(shù)據(jù)通道W、寫響應(yīng)通道B各自獨(dú)立工作。這種設(shè)計(jì)讓讀和寫可以同時(shí)進(jìn)行也讓outstanding未完成傳輸?shù)臄?shù)量可以做得很大從而隱藏內(nèi)存訪問延遲。但通道獨(dú)立帶來一個(gè)直接問題多個(gè)master同時(shí)發(fā)起訪問時(shí)誰先誰后比如CPU要讀DDR里的指令DMA要往DDR寫一幀圖像數(shù)據(jù)以太網(wǎng)控制器也要讀取描述符這幾個(gè)請(qǐng)求幾乎同時(shí)到達(dá)。從設(shè)備比如DDR控制器只有一個(gè)地址端口同一時(shí)刻只能接收一個(gè)請(qǐng)求這時(shí)候就必須有一個(gè)仲裁器來決定放行哪個(gè)請(qǐng)求。仲裁器就位于master和slave之間在多master互聯(lián)的場(chǎng)景下它承擔(dān)著“交通警察”的角色。在典型SoC里仲裁器通常不是獨(dú)立存在的而是集成在互聯(lián)矩陣Interconnect或者NICNetwork Interconnect里。比如ARM的NIC-400、NIC-450或者Xilinx的AXI Interconnect IP內(nèi)部都包含了仲裁邏輯。但理解仲裁器本身的設(shè)計(jì)思路比直接調(diào)IP更有價(jià)值——因?yàn)楹芏嘈阅軉栴}歸根結(jié)底是仲裁策略選擇不當(dāng)造成的。1.2 沒有仲裁器會(huì)發(fā)生什么總線沖突的現(xiàn)場(chǎng)要是沒有仲裁器多個(gè)master同時(shí)驅(qū)動(dòng)地址總線和數(shù)據(jù)總線結(jié)果就是總線沖突兩個(gè)master的電平互相打架協(xié)議層面完全失效??赡苡腥藭?huì)說那讓每個(gè)master分時(shí)使用總線不就行了但問題在于AXI是通道獨(dú)立的不同通道的仲裁需要分別做。比如master A的寫地址可以仲裁通過master B的寫數(shù)據(jù)也需要仲裁通過如果兩者割裂處理數(shù)據(jù)通道和地址通道就可能對(duì)不上。還有一個(gè)容易被忽略的點(diǎn)AXI并沒有規(guī)定仲裁應(yīng)該放在哪個(gè)通道上。按照協(xié)議master發(fā)出請(qǐng)求后slave通過valid/ready握手來接收。仲裁器介入的時(shí)機(jī)可以是地址通道決定誰的命令先被slave接收也可以是數(shù)據(jù)通道決定誰的數(shù)據(jù)先傳輸。更常見的做法是在地址通道上做仲裁因?yàn)榈刂吠ǖ赖恼?qǐng)求頭包含了完整的傳輸信息地址、突發(fā)長(zhǎng)度、ID等仲裁器只需要決定這些請(qǐng)求頭誰先通過數(shù)據(jù)通道就順著走就行了。我之前見過一個(gè)實(shí)際的項(xiàng)目工程師把仲裁放在了數(shù)據(jù)通道上結(jié)果出現(xiàn)了兩個(gè)master的寫數(shù)據(jù)在總線上一半一半交錯(cuò)傳輸?shù)脑幃惉F(xiàn)象協(xié)議仿真能過但上板之后DDR的數(shù)據(jù)就是錯(cuò)亂的。后來追查下來問題就出在仲裁位置放錯(cuò)了寫數(shù)據(jù)通道一旦被分片寫響應(yīng)和寫數(shù)據(jù)之間的配對(duì)關(guān)系就亂了。這個(gè)案例后面會(huì)細(xì)說。1.3 仲裁器在SoC設(shè)計(jì)中的實(shí)際部署仲裁器的部署位置通常有三種。第一種是點(diǎn)對(duì)點(diǎn)互聯(lián)一個(gè)master連一個(gè)slave一般不需要仲裁器除非這個(gè)master內(nèi)部有多個(gè)請(qǐng)求源。第二種是共享總線式的多master互聯(lián)仲裁器集中管理所有master對(duì)單個(gè)slave的訪問這種結(jié)構(gòu)簡(jiǎn)單但容易成為性能瓶頸適合對(duì)帶寬要求不高的系統(tǒng)。第三種是交叉開關(guān)矩陣Crossbar每個(gè)slave端口都有一個(gè)獨(dú)立的仲裁器多個(gè)master可以同時(shí)訪問不同的slave這時(shí)仲裁器分布在交叉開關(guān)的每個(gè)輸出端口上。在Xilinx的AXI Interconnect IP里打開配置界面就能看到每個(gè)slave端口對(duì)應(yīng)的仲裁策略選項(xiàng)比如Round Robin或者Priority。默認(rèn)的Round Robin通常不會(huì)出大問題但如果你有實(shí)時(shí)性要求高的master就必須按優(yōu)先級(jí)來配否則延遲抖動(dòng)會(huì)非常明顯。這個(gè)選擇需要結(jié)合具體業(yè)務(wù)來確定不能一張配置單打天下。2. 常見的AXI仲裁算法與選型分析2.1 固定優(yōu)先級(jí)仲裁簡(jiǎn)單但餓死風(fēng)險(xiǎn)高固定優(yōu)先級(jí)仲裁Fixed Priority是最直覺的做法給每個(gè)master分配一個(gè)優(yōu)先級(jí)編號(hào)仲裁時(shí)直接選出編號(hào)最高的請(qǐng)求。這個(gè)方案邏輯最簡(jiǎn)單一個(gè)比較器加一個(gè)多路選擇器就能搞定占用資源極少時(shí)序也容易收斂。但它的缺點(diǎn)和優(yōu)點(diǎn)一樣明顯低優(yōu)先級(jí)master可能永遠(yuǎn)得不到服務(wù)這就是所謂的餓死starvation問題。舉個(gè)實(shí)際例子CPU和UART的DMA訪問同一個(gè)DDR控制器如果CPU永遠(yuǎn)是最高優(yōu)先級(jí)而CPU又持續(xù)有緩存未命中的讀請(qǐng)求UART的DMA可能幾毫秒都拿不到總線。對(duì)于UART這種需要實(shí)時(shí)從FIFO搬運(yùn)數(shù)據(jù)的設(shè)備來說幾毫秒的空窗就意味著FIFO溢出數(shù)據(jù)直接丟失。我之前做過一個(gè)帶AXI UART16550核的項(xiàng)目默認(rèn)配置里CPU是最高優(yōu)先級(jí)低優(yōu)先級(jí)里掛了一個(gè)UART DMA通道。調(diào)試串口經(jīng)常出現(xiàn)亂碼剛開始懷疑是波特率不匹配后來抓了總線的波形才發(fā)現(xiàn)UART的讀請(qǐng)求經(jīng)常被CPU的突發(fā)讀插隊(duì)DMA服務(wù)間隔不穩(wěn)定FIFO發(fā)生了下溢。改成UART DMA的優(yōu)先級(jí)高于CPU之后問題當(dāng)場(chǎng)就消失了。所以固定優(yōu)先級(jí)仲裁不是不能用而是要用對(duì)地方。如果高優(yōu)先級(jí)master的請(qǐng)求頻率有上限或者低優(yōu)先級(jí)master本身容忍大延遲那固定優(yōu)先級(jí)反而是最優(yōu)選擇因?yàn)樗难舆t是可預(yù)測(cè)的資源耗費(fèi)也最低。2.2 輪詢仲裁保證公平性的基礎(chǔ)方案輪詢仲裁Round-Robin是解決餓死問題最直接的策略多個(gè)master的請(qǐng)求排成一個(gè)圈仲裁指針每拍移動(dòng)到下一個(gè)master有請(qǐng)求就放行沒請(qǐng)求就跳過。這個(gè)方案保證了所有master在長(zhǎng)期統(tǒng)計(jì)下能獲得大致相等的總線訪問機(jī)會(huì)。設(shè)計(jì)上有兩個(gè)變體需要注意。一種是固定順序輪詢指針永遠(yuǎn)按0→1→2→3的順序移動(dòng)無論當(dāng)前master是否有請(qǐng)求。另一種是跳過式輪詢指針會(huì)跳到有請(qǐng)求的master減少無效輪詢周期。后者的效率更高但實(shí)現(xiàn)上需要額外的查找邏輯時(shí)序要稍微緊一點(diǎn)。不過輪詢仲裁也有它的軟肋它對(duì)延遲不敏感也沒有優(yōu)先級(jí)概念。如果某個(gè)master對(duì)實(shí)時(shí)性要求很高比如視頻解碼器需要每幀固定的帶寬輪詢給出的只是統(tǒng)計(jì)學(xué)意義上的公平延遲抖動(dòng)依然存在。這時(shí)候就需要加權(quán)輪詢或者QoS機(jī)制來調(diào)節(jié)。在實(shí)際工程里一個(gè)常見的折中方案是“輪詢?yōu)橹鲀?yōu)先級(jí)為輔”默認(rèn)所有master按輪詢仲裁但每當(dāng)某個(gè)高優(yōu)先級(jí)master連續(xù)等待超過設(shè)定周期時(shí)臨時(shí)把仲裁結(jié)果切給它。這種自適應(yīng)方案兼顧了公平和實(shí)時(shí)不過狀態(tài)機(jī)復(fù)雜度會(huì)明顯上升。2.3 加權(quán)輪詢按帶寬需求分配總線時(shí)間加權(quán)輪詢Weighted Round-Robin解決的是“公平但不夠用”的問題。比如DMA需要70%的帶寬CPU只需要30%簡(jiǎn)單的輪詢會(huì)各分50%DMA的帶寬就欠了。加權(quán)的思路是給每個(gè)master分配一個(gè)權(quán)重值權(quán)重大的master在每輪仲裁中獲得更多的服務(wù)次數(shù)。實(shí)現(xiàn)上有兩種常見做法。第一種是令牌式每個(gè)周期給所有master發(fā)放與權(quán)重成正比的令牌數(shù)請(qǐng)求消耗令牌令牌多的master自然獲得更多服務(wù)。第二種是分槽式把仲裁周期切成與總權(quán)重等長(zhǎng)的槽位按權(quán)重比例分配槽位給各個(gè)master。第一種方式更靈活第二種更容易做到嚴(yán)格周期。加權(quán)輪詢的難點(diǎn)在于權(quán)重怎么定。理論上可以根據(jù)系統(tǒng)帶寬模型來計(jì)算但在實(shí)際SoC里主master的帶寬需求往往是動(dòng)態(tài)的——比如CPU的DDR訪問量隨負(fù)載波動(dòng)非常大。如果權(quán)重是固定的要么浪費(fèi)帶寬要么仍然不夠用。所以更先進(jìn)的仲裁器會(huì)引入動(dòng)態(tài)權(quán)重調(diào)整這已經(jīng)接近QoS的思路了。2.4 基于QoS的仲裁AXI4標(biāo)準(zhǔn)里的QoS接口AXI4協(xié)議在ARID和AWID之外增加了一個(gè)QOS信號(hào)寬度是4位表示每次傳輸?shù)姆?wù)質(zhì)量等級(jí)。從0到15數(shù)值越大優(yōu)先級(jí)越高。這給仲裁器設(shè)計(jì)提供了一個(gè)標(biāo)準(zhǔn)化的優(yōu)先級(jí)接口仲裁器不需要知道m(xù)aster是誰只需要看QOS值就能做仲裁決定。QOS信號(hào)的價(jià)值在于它把“誰的請(qǐng)求重要”這個(gè)決策從硬件架構(gòu)層搬到了軟件可配置層。系統(tǒng)軟件可以在運(yùn)行時(shí)動(dòng)態(tài)調(diào)整某個(gè)master的QOS值從而改變總線服務(wù)的偏向。比如視頻播放時(shí)提高顯示控制器的QOS保證幀不撕裂后臺(tái)跑基準(zhǔn)測(cè)試時(shí)降低CPU的QOS給存儲(chǔ)控制器的維護(hù)操作騰帶寬。不過QOS只是一個(gè)提示信號(hào)AXI協(xié)議并不強(qiáng)制仲裁器必須響應(yīng)它。我在設(shè)計(jì)仲裁器的時(shí)候通常會(huì)把QOS值映射為動(dòng)態(tài)優(yōu)先級(jí)再結(jié)合輪詢機(jī)制做一個(gè)混合仲裁器優(yōu)先級(jí)高的先服務(wù)相同優(yōu)先級(jí)之間輪詢。這種方式兼顧了靈活性和公平性是目前比較推薦的實(shí)現(xiàn)思路。3. AXI協(xié)議對(duì)仲裁器設(shè)計(jì)的特殊約束3.1 valid/ready握手與仲裁時(shí)機(jī)的選擇AXI協(xié)議里每個(gè)通道的數(shù)據(jù)傳輸都通過valid/ready握手完成。發(fā)起方拉高valid表示數(shù)據(jù)有效接收方拉高ready表示可以接收兩者同時(shí)為高時(shí)傳輸發(fā)生。仲裁器介入后實(shí)際上扮演了“接收方發(fā)起方”的雙重角色對(duì)上游master來說是slave對(duì)下游slave來說是master。仲裁時(shí)機(jī)的選擇直接關(guān)系到一個(gè)問題是等master的valid信號(hào)拉高之后再仲裁還是提前預(yù)判我的經(jīng)驗(yàn)是對(duì)于地址通道通常等valid拉高后再仲裁就夠了因?yàn)榈刂吠ǖ赖恼?qǐng)求不是每拍都有的仲裁器本身也要等請(qǐng)求到來才能做決定。但對(duì)于數(shù)據(jù)通道如果希望做到背靠背傳輸back-to-back預(yù)判是必要的——在最后一拍數(shù)據(jù)還沒傳完時(shí)就開始仲裁下一筆傳輸?shù)臄?shù)據(jù)通路。握手還有一個(gè)重要的特性一旦valid拉高發(fā)起方就不能撤銷必須等到握手完成。這意味著仲裁器一旦向某個(gè)master給出了ready信號(hào)就必須完成這筆傳輸。如果這時(shí)發(fā)現(xiàn)仲裁錯(cuò)了——比如出現(xiàn)了更高優(yōu)先級(jí)的請(qǐng)求——也不能反悔只能等當(dāng)前傳輸結(jié)束。這在設(shè)計(jì)里叫“不可搶占”特性是AXI仲裁與普通CPU總線仲裁的重要區(qū)別。3.2 outstanding傳輸與ID管理的仲裁影響AXI協(xié)議允許master在未收到前一筆傳輸響應(yīng)之前就發(fā)起后續(xù)傳輸這就是outstanding。這個(gè)特性極大提升了總線利用率但也給仲裁器帶來了麻煩仲裁器不能只看當(dāng)前一筆請(qǐng)求還要考慮master發(fā)出的請(qǐng)求隊(duì)列深度。比如一個(gè)DMA控制器可以同時(shí)發(fā)出16筆讀突發(fā)但如果仲裁器一筆一筆地處理每筆之間還要等DDR的響應(yīng)返回DMA的outstanding能力就浪費(fèi)了。正確的做法是仲裁器也維護(hù)一個(gè)與master對(duì)應(yīng)的未完成傳輸計(jì)數(shù)只要計(jì)數(shù)沒到上限就允許master連續(xù)發(fā)起新的請(qǐng)求。ID信號(hào)的管理更加微妙。AXI的ID信號(hào)用于標(biāo)記傳輸?shù)臍w屬支持亂序返回。仲裁器在合并多個(gè)master的請(qǐng)求時(shí)必須為每個(gè)master的ID做映射避免兩個(gè)master的ID沖突。比如master A和master B都用了ID0如果不做映射slave返回的數(shù)據(jù)就無法區(qū)分屬于哪個(gè)master。我踩過一個(gè)ID映射的坑當(dāng)時(shí)在做一個(gè)AXI to AXI Bridge兩個(gè)master的ID都是4位寬度理論上直接級(jí)聯(lián)就行。但其中一個(gè)master發(fā)起了亂序讀另一個(gè)master的ID恰好和它重疊導(dǎo)致返回?cái)?shù)據(jù)被Bridge分發(fā)到了錯(cuò)誤的master。最后不得不給Bridge增加了一個(gè)ID remap機(jī)制把每個(gè)master的ID空間獨(dú)立開才徹底解決。3.3 寫通道仲裁的特殊性AW、W、B三個(gè)通道的配合很多剛開始接觸AXI仲裁的人會(huì)犯一個(gè)錯(cuò)誤只仲裁AW通道忽略了W通道。實(shí)際上寫操作涉及三個(gè)通道AW寫地址、W寫數(shù)據(jù)、B寫響應(yīng)。如果AW和W的仲裁策略不一致就會(huì)出現(xiàn)地址通道選了master A數(shù)據(jù)通道卻傳著master B的數(shù)據(jù)結(jié)果這兩個(gè)master的寫操作互相串?dāng)_。為了保證寫操作的正確性仲裁器通常需要把AW和W通道綁定在同一仲裁域里。也就是說當(dāng)仲裁器決定為master A的寫操作打開閘門時(shí)它的AW請(qǐng)求和W請(qǐng)求都必須被同時(shí)放行。這帶來一個(gè)數(shù)據(jù)緩沖的問題如果下游slave暫時(shí)無法接收W數(shù)據(jù)仲裁器要把master A的寫數(shù)據(jù)緩存下來這就涉及FIFO深度設(shè)計(jì)。AW和W還有一個(gè)同步問題AXI協(xié)議不要求W數(shù)據(jù)和AW請(qǐng)求嚴(yán)格同拍到達(dá)但要求所有W數(shù)據(jù)必須在對(duì)應(yīng)的AW請(qǐng)求之后到達(dá)。仲裁器需要記錄每個(gè)master的寫請(qǐng)求狀態(tài)確保不會(huì)出現(xiàn)AW還沒放行W數(shù)據(jù)先到的情況。實(shí)際實(shí)現(xiàn)中最簡(jiǎn)單的策略是AW和W按同一個(gè)仲裁結(jié)果走仲裁為誰服務(wù)就把兩個(gè)通道的閘門都打開。3.4 多master訪問DDR時(shí)的死鎖與屏障處理多master并發(fā)訪問DDR時(shí)最頭痛的問題是死鎖??紤]一個(gè)場(chǎng)景master A正在對(duì)slave X做讀操作master B正在對(duì)slave Y做寫操作而這兩個(gè)slave內(nèi)部又相互依賴。仲裁器如果不加約束理論上就可能互相等待。AXI協(xié)議本身沒有定義屏障Barrier機(jī)制但AXI4增加了屏障事務(wù)Barrier Transaction的概念當(dāng)一個(gè)master發(fā)出屏障請(qǐng)求時(shí)它要求在此之前所有outstanding的傳輸都完成之后的新傳輸才能開始。仲裁器在收到屏障請(qǐng)求后需要暫時(shí)停止對(duì)這個(gè)master放行新請(qǐng)求直到它的所有未完成傳輸全部返回。系統(tǒng)級(jí)死鎖的預(yù)防還需要考慮更宏觀的因素——比如CPU核和DMA之間通過外設(shè)寄存器的握手邏輯。如果CPU在等待DMA完成中斷而DMA又在等待CPU釋放某個(gè)外設(shè)鎖兩邊都卡在總線訪問上系統(tǒng)就死鎖了。這類問題通常靠超時(shí)計(jì)數(shù)器來兜底仲裁器里的每筆請(qǐng)求都應(yīng)該維護(hù)一個(gè)超時(shí)標(biāo)志超時(shí)后強(qiáng)制丟棄或上報(bào)。4. 實(shí)操從零搭建一個(gè)AXI仲裁器4.1 接口設(shè)計(jì)與仲裁狀態(tài)機(jī)下面給出一個(gè)精簡(jiǎn)的AXI仲裁器設(shè)計(jì)思路重點(diǎn)展示地址通道的仲裁邏輯。這個(gè)設(shè)計(jì)假設(shè)有4個(gè)master端口每個(gè)端口都遵循AXI4協(xié)議仲裁器輸出到一個(gè)slave端口。module axi_arbiter #( parameter ID_WIDTH 4, parameter ADDR_WIDTH 32, parameter DATA_WIDTH 64, parameter N_SLAVES 4 )( input clk, input rst_n, // 4個(gè)master端口的AR通道輸入 input [N_SLAVES-1:0] ar_valid_i, output [N_SLAVES-1:0] ar_ready_o, input [N_SLAVES*ADDR_WIDTH-1:0] ar_addr_i, input [N_SLAVES*ID_WIDTH-1:0] ar_id_i, // 輸出到slave的AR通道 output reg ar_valid_o, input ar_ready_i, output reg [ADDR_WIDTH-1:0] ar_addr_o, output reg [ID_WIDTH-1:0] ar_id_o );仲裁器的核心是一個(gè)狀態(tài)機(jī)狀態(tài)包括IDLE、ARB、WAIT_HANDSHAKE。IDLE狀態(tài)檢測(cè)是否有AR請(qǐng)求ARB狀態(tài)根據(jù)仲裁算法選擇winnerWAIT_HANDSHAKE狀態(tài)等待slave的ar_ready握手完成后回到IDLE。如果采用輪詢算法還要維護(hù)一個(gè)指針寄存器。// 輪詢指針 reg [N_SLAVES-1:0] grant_ptr; wire [N_SLAVES-1:0] req_vec ar_valid_i; wire [N_SLAVES-1:0] masked_req req_vec ~(grant_ptr - 1); wire [N_SLAVES-1:0] grant masked_req ? (masked_req ~(masked_req - 1)) : (req_vec ~(req_vec - 1));上面這段是經(jīng)典的總線仲裁輪詢算法優(yōu)先服務(wù)當(dāng)前指針之后的最低有效位請(qǐng)求如果沒有再從最低位開始找。這個(gè)寫法簡(jiǎn)潔高效FPGA綜合后只會(huì)占用很少的LUT。4.2 寫數(shù)據(jù)通道的FIFO緩沖與背壓處理地址通道仲裁只是第一步。為了讓寫數(shù)據(jù)W通道能夠與AW通道解耦仲裁器內(nèi)部通常需要為每個(gè)master設(shè)置一個(gè)寫數(shù)據(jù)FIFO。master的數(shù)據(jù)先寫入FIFO仲裁器按仲裁結(jié)果從對(duì)應(yīng)FIFO讀出數(shù)據(jù)送往slave。FIFO深度怎么選經(jīng)驗(yàn)公式是FIFO深度 ≥ 最大突發(fā)長(zhǎng)度 × 數(shù)據(jù)寬度 / 8以字節(jié)為單位如果max burst是16 beats數(shù)據(jù)寬度是64位8字節(jié)那FIFO深度至少要128字節(jié)。這里還要考慮burst類型和地址對(duì)齊的情況。實(shí)際項(xiàng)目中我一般會(huì)多留25%的余量因?yàn)锳XI的W通道允許數(shù)據(jù)提前到達(dá)FIFO太淺會(huì)造成背壓。背壓Backpressure是AXI里一個(gè)重要的概念。當(dāng)FIFO滿時(shí)仲裁器必須拉低W通道的ready信號(hào)這相當(dāng)于告訴master“我暫時(shí)收不了數(shù)據(jù)”。這個(gè)信號(hào)會(huì)一級(jí)一級(jí)向上游傳遞最終可能讓DMA暫停搬運(yùn)。如果背壓處理不好就可能出現(xiàn)總線上某個(gè)master長(zhǎng)時(shí)間占有數(shù)據(jù)通路、而其他master被餓死的現(xiàn)象。為了解決這個(gè)問題我給仲裁器的每個(gè)FIFO都加了一個(gè)almost_full信號(hào)當(dāng)FIFO快滿時(shí)就不再對(duì)該master進(jìn)行仲裁。這個(gè)細(xì)節(jié)在實(shí)際調(diào)試中幫了大忙否則DMA在突發(fā)傳輸中途被插斷恢復(fù)起來非常影響性能。4.3 讀數(shù)據(jù)返回通道的仲裁與ID重映射讀數(shù)據(jù)通道R的仲裁和寫數(shù)據(jù)通道不同。R通道方向是從slave返回master仲裁器需要把從slave收到的讀數(shù)據(jù)分發(fā)給對(duì)應(yīng)的master。這里的關(guān)鍵是ID信號(hào)slave返回?cái)?shù)據(jù)時(shí)帶上ID仲裁器通過ID判斷這筆數(shù)據(jù)屬于哪個(gè)master。但如果多個(gè)master的ID空間重疊——比如都用了ID 0、1、2——仲裁器就必須做ID重映射。通常的做法是給每個(gè)master的ID增加高位前綴將master編號(hào)編入ID。比如master 0的ID保持原樣master 1的ID最高位加1依此類推。slave端看到的ID就是唯一的返回時(shí)仲裁器根據(jù)高位前綴決定數(shù)據(jù)分發(fā)到哪個(gè)master再把前綴去掉。這種方案在Xilinx的AXI Interconnect里也采用了類似的機(jī)制叫做ID Width Adaptation。值得注意的是ID重映射會(huì)改變ID的總線寬度如果原設(shè)計(jì)里ID寬度是4位4個(gè)master映射后slave端ID可能需要6位。這會(huì)影響后續(xù)slave的設(shè)計(jì)務(wù)必提前規(guī)劃。4.4 驗(yàn)證方法直接看時(shí)序圖比什么都直觀仲裁器設(shè)計(jì)的驗(yàn)證除了跑仿真外我還習(xí)慣抓取總線時(shí)序圖來人工檢查。重點(diǎn)看幾個(gè)信號(hào)arb_grant當(dāng)前仲裁勝利者、ar_ready地址通道握手、以及各master的ar_valid。抓時(shí)序圖時(shí)最容易發(fā)現(xiàn)的問題是仲裁切換過快或過慢。仲裁切換過快一個(gè)master還沒發(fā)完一筆突發(fā)請(qǐng)求就被切走會(huì)導(dǎo)致slave端收到碎片化的請(qǐng)求序列切換太慢則可能在其他master有高優(yōu)先級(jí)請(qǐng)求時(shí)仍然占用總線。一個(gè)常見的時(shí)序圖場(chǎng)景是master A的ar_valid持續(xù)拉高但ar_ready只在某些周期有效。如果仲裁器在ar_ready無效時(shí)切換了grant下一拍ar_ready有效時(shí)slave端看到的可能是master B的請(qǐng)求這時(shí)master A的請(qǐng)求就被“餓”了一拍。好的仲裁器設(shè)計(jì)應(yīng)該在grant切換和握手完成之間插入一個(gè)同步邏輯確保grant只在握手完成后的空拍切換。這些細(xì)節(jié)都可以從波形上直觀觀察到。5. 線上調(diào)試中的常見問題與排查技巧5.1 問題速查表癥狀可能原因排查方法DMA傳輸數(shù)據(jù)錯(cuò)亂寫數(shù)據(jù)通道仲裁與地址通道不一致抓W和AW通道波形對(duì)比仲裁結(jié)果UART/串口亂碼低優(yōu)先級(jí)master被餓死FIFO溢出檢查仲裁策略提高UART優(yōu)先級(jí)或加輪詢總線延遲抖動(dòng)大fixed priority下高優(yōu)先級(jí)請(qǐng)求過于頻繁改用RRQOS混合仲裁或增加權(quán)重讀數(shù)據(jù)返回亂序錯(cuò)亂ID重映射錯(cuò)誤多個(gè)master的ID沒有隔離檢查仲裁器的ID映射表系統(tǒng)卡死總線一直busyoutstanding計(jì)數(shù)溢出或死鎖加超時(shí)計(jì)數(shù)器檢查屏障處理帶寬遠(yuǎn)低于預(yù)期仲裁周期太長(zhǎng)FIFO背壓頻繁配置仲裁器預(yù)取模式增加FIFO深度5.2 實(shí)測(cè)案例AXI UART16550的DMA傳輸異常這個(gè)案例我印象特別深。項(xiàng)目里用了一個(gè)帶AXI接口的UART16550核收發(fā)數(shù)據(jù)走DMA。DMA通過AXI總線訪問UART的寄存器FIFO實(shí)際上就是AXI讀寫寄存器操作但請(qǐng)求頻率不高——每次就4字節(jié)的讀或?qū)?。系統(tǒng)里還有一個(gè)千兆以太網(wǎng)MAC其DMA會(huì)發(fā)起長(zhǎng)突發(fā)讀和寫DDR。一開始UART在現(xiàn)代調(diào)試串口上偶爾丟字符沒太當(dāng)回事直到有一天從FPGA上采集到UART的DMA請(qǐng)求延遲超過了100微秒才意識(shí)到問題嚴(yán)重。排查過程是這樣的先看仲裁器的grant信號(hào)發(fā)現(xiàn)UART的AXI讀請(qǐng)求雖然一直有效但grant經(jīng)常被以太網(wǎng)MAC搶走。仲裁策略是固定優(yōu)先級(jí)以太網(wǎng)MAC的優(yōu)先級(jí)高于UART。后來我改成了加權(quán)輪詢給UART一個(gè)最低權(quán)重確保每個(gè)輪詢周期至少服務(wù)一次。改完之后抓波形UART DMA請(qǐng)求的服務(wù)間隔穩(wěn)定在2微秒以內(nèi)丟字符問題徹底消失。這個(gè)案例告訴我們仲裁策略的設(shè)計(jì)不能只盯著高帶寬設(shè)備低帶寬但實(shí)時(shí)性要求高的設(shè)備同樣需要照顧。從系統(tǒng)的角度看仲裁器應(yīng)該是一個(gè)“按需分配”的機(jī)構(gòu)而不是簡(jiǎn)單的“強(qiáng)者恒強(qiáng)”。5.3 AXI Quad SPI與DDR讀寫并發(fā)時(shí)的帶寬分配另一個(gè)常見場(chǎng)景是AXI Quad SPIQSPI控制器和CPU同時(shí)訪問DDR。QSPI需要周期性讀寫Flash速度不快但每次訪問的延遲必須穩(wěn)定因?yàn)镕lash的時(shí)序窗口很窄——如果QSPI的讀請(qǐng)求被DDR的長(zhǎng)突發(fā)卡住太久Flash的讀命令就可能超時(shí)。我在這類設(shè)計(jì)里通常的做法是給QSPI控制器分配一個(gè)獨(dú)立的仲裁槽位即使它只有1/8的權(quán)重也能保證每個(gè)仲裁周期內(nèi)至少服務(wù)一次。這樣DDR的大塊讀寫可以吃滿剩余帶寬而QSPI的訪問延遲始終可控。另一種思路是讓QSPI走專用的低延遲路徑繞過主仲裁器。在SoC里這叫做側(cè)信道sideband專門給對(duì)延遲敏感但帶寬需求低的控制面通信使用。這個(gè)方案在復(fù)雜的SoC里經(jīng)常看到不過會(huì)增加布線復(fù)雜度。選擇哪種方案需要綜合評(píng)估系統(tǒng)對(duì)延遲的容忍度和對(duì)布局面積的約束。5.4 驗(yàn)證過程中值得注意的邊界情況仲裁器的驗(yàn)證最容易漏掉的是邊界情況。我總結(jié)了幾類必測(cè)的場(chǎng)景多個(gè)master同時(shí)發(fā)起請(qǐng)求且ID完全相同驗(yàn)證ID重映射的正確性。master在握手期間突然拉低valid這在協(xié)議里是違法的仲裁器應(yīng)該能容忍并記錄錯(cuò)誤。outstanding計(jì)數(shù)達(dá)到上限后master繼續(xù)發(fā)出請(qǐng)求仲裁器必須忽略多余的請(qǐng)求并反壓。某個(gè)slave長(zhǎng)時(shí)間不響應(yīng)仲裁器應(yīng)該能通過超時(shí)機(jī)制釋放總線否則整個(gè)系統(tǒng)會(huì)被一個(gè)slave拖死。上電復(fù)位瞬間仲裁器指針初始值可能隨機(jī)必須確保不會(huì)把grant輸出到?jīng)]有請(qǐng)求的master。這些邊界場(chǎng)景如果只用隨機(jī)約束仿真很難全部覆蓋。我推薦的做法是在驗(yàn)證環(huán)境里直接定向?qū)戇@些case每個(gè)case都配合波形來確認(rèn)。對(duì)于超時(shí)機(jī)制還要額外驗(yàn)證超時(shí)時(shí)間參數(shù)是否可配置方便后期調(diào)試。6. 我對(duì)AXI仲裁器設(shè)計(jì)的一些心得做了幾年AXI相關(guān)的IP集成和調(diào)試我對(duì)仲裁器最大的感觸是它看似簡(jiǎn)單實(shí)則處處是權(quán)衡。你很難設(shè)計(jì)出一個(gè)在所有場(chǎng)景下都最優(yōu)的仲裁器所以好的設(shè)計(jì)者一定是先搞清楚系統(tǒng)的真實(shí)需求再選擇合適的仲裁策略。如果你正在做一個(gè)對(duì)帶寬不敏感的小系統(tǒng)固定優(yōu)先級(jí)仲裁足夠用省資源、時(shí)序好、行為可預(yù)測(cè)。如果你面對(duì)的是多master、多業(yè)務(wù)的SoC那就要認(rèn)真考慮輪詢、加權(quán)和QOS的組合。沒有萬能的仲裁器只有適配具體場(chǎng)景的仲裁器。最后分享一個(gè)調(diào)試技巧遇到AXI總線相關(guān)的性能問題時(shí)不要一上來就看代碼或者仿真先抓一段真實(shí)總線波形。波形能直觀告訴你哪個(gè)master在占總線、哪個(gè)master在等待、仲裁器的grant切換頻率是多少。很多時(shí)候波形的異常一眼就能定位問題比盲猜代碼高效得多。下一篇文章里我打算聊聊AXI的outstanding和ID管理這套機(jī)制和仲裁器配合得好不好直接決定了多master系統(tǒng)的最終性能。到時(shí)候把亂序返回、ID寬度擴(kuò)展、以及和DDR控制器交互的那些坑一起講清楚。