計(jì)全解析:從算法策略到協(xié)議約束與調(diào)試實(shí)戰(zhàn))
AXI總線仲裁器這個(gè)話題說(shuō)實(shí)話是很多做SoC集成和FPGA開(kāi)發(fā)的同事容易忽略又不得不面對(duì)的東西。剛開(kāi)始接觸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é)議理解”系列的第一篇專門(mén)把仲裁器這塊拆開(kāi)講清楚它到底解決什么問(wèn)題、常用的仲裁策略有哪些、AXI協(xié)議給仲裁器設(shè)計(jì)埋了哪些坑、以及我自己在實(shí)際項(xiàng)目里踩過(guò)的雷。適合剛?cè)腴T(mén)AXI的FPGA/IC工程師也適合做了幾年集成但沒(méi)仔細(xì)摳過(guò)仲裁細(xì)節(jié)的朋友。1. 為什么AXI總線需要仲裁器1.1 AXI總線的基本結(jié)構(gòu)與仲裁器位置AXIAdvanced eXtensible Interface是ARM AMBA協(xié)議家族里的高性能總線協(xié)議它的核心特點(diǎn)是通道獨(dú)立讀地址通道AR、讀數(shù)據(jù)通道R、寫(xiě)地址通道AW、寫(xiě)數(shù)據(jù)通道W、寫(xiě)響應(yīng)通道B各自獨(dú)立工作。這種設(shè)計(jì)讓讀和寫(xiě)可以同時(shí)進(jìn)行也讓outstanding未完成傳輸?shù)臄?shù)量可以做得很大從而隱藏內(nèi)存訪問(wèn)延遲。但通道獨(dú)立帶來(lái)一個(gè)直接問(wèn)題多個(gè)master同時(shí)發(fā)起訪問(wèn)時(shí)誰(shuí)先誰(shuí)后比如CPU要讀DDR里的指令DMA要往DDR寫(xiě)一幀圖像數(shù)據(jù)以太網(wǎng)控制器也要讀取描述符這幾個(gè)請(qǐng)求幾乎同時(shí)到達(dá)。從設(shè)備比如DDR控制器只有一個(gè)地址端口同一時(shí)刻只能接收一個(gè)請(qǐng)求這時(shí)候就必須有一個(gè)仲裁器來(lái)決定放行哪個(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)楹芏嘈阅軉?wèn)題歸根結(jié)底是仲裁策略選擇不當(dāng)造成的。1.2 沒(méi)有仲裁器會(huì)發(fā)生什么總線沖突的現(xiàn)場(chǎng)要是沒(méi)有仲裁器多個(gè)master同時(shí)驅(qū)動(dòng)地址總線和數(shù)據(jù)總線結(jié)果就是總線沖突兩個(gè)master的電平互相打架協(xié)議層面完全失效??赡苡腥藭?huì)說(shuō)那讓每個(gè)master分時(shí)使用總線不就行了但問(wèn)題在于AXI是通道獨(dú)立的不同通道的仲裁需要分別做。比如master A的寫(xiě)地址可以仲裁通過(guò)master B的寫(xiě)數(shù)據(jù)也需要仲裁通過(guò)如果兩者割裂處理數(shù)據(jù)通道和地址通道就可能對(duì)不上。還有一個(gè)容易被忽略的點(diǎn)AXI并沒(méi)有規(guī)定仲裁應(yīng)該放在哪個(gè)通道上。按照協(xié)議master發(fā)出請(qǐng)求后slave通過(guò)valid/ready握手來(lái)接收。仲裁器介入的時(shí)機(jī)可以是地址通道決定誰(shuí)的命令先被slave接收也可以是數(shù)據(jù)通道決定誰(shuí)的數(shù)據(jù)先傳輸。更常見(jiàn)的做法是在地址通道上做仲裁因?yàn)榈刂吠ǖ赖恼?qǐng)求頭包含了完整的傳輸信息地址、突發(fā)長(zhǎng)度、ID等仲裁器只需要決定這些請(qǐng)求頭誰(shuí)先通過(guò)數(shù)據(jù)通道就順著走就行了。我之前見(jiàn)過(guò)一個(gè)實(shí)際的項(xiàng)目工程師把仲裁放在了數(shù)據(jù)通道上結(jié)果出現(xiàn)了兩個(gè)master的寫(xiě)數(shù)據(jù)在總線上一半一半交錯(cuò)傳輸?shù)脑幃惉F(xiàn)象協(xié)議仿真能過(guò)但上板之后DDR的數(shù)據(jù)就是錯(cuò)亂的。后來(lái)追查下來(lái)問(wèn)題就出在仲裁位置放錯(cuò)了寫(xiě)數(shù)據(jù)通道一旦被分片寫(xiě)響應(yīng)和寫(xiě)數(shù)據(jù)之間的配對(duì)關(guān)系就亂了。這個(gè)案例后面會(huì)細(xì)說(shuō)。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的訪問(wèn)這種結(jié)構(gòu)簡(jiǎn)單但容易成為性能瓶頸適合對(duì)帶寬要求不高的系統(tǒng)。第三種是交叉開(kāi)關(guān)矩陣Crossbar每個(gè)slave端口都有一個(gè)獨(dú)立的仲裁器多個(gè)master可以同時(shí)訪問(wèn)不同的slave這時(shí)仲裁器分布在交叉開(kāi)關(guān)的每個(gè)輸出端口上。在Xilinx的AXI Interconnect IP里打開(kāi)配置界面就能看到每個(gè)slave端口對(duì)應(yīng)的仲裁策略選項(xiàng)比如Round Robin或者Priority。默認(rèn)的Round Robin通常不會(huì)出大問(wèn)題但如果你有實(shí)時(shí)性要求高的master就必須按優(yōu)先級(jí)來(lái)配否則延遲抖動(dòng)會(huì)非常明顯。這個(gè)選擇需要結(jié)合具體業(yè)務(wù)來(lái)確定不能一張配置單打天下。2. 常見(jiàn)的AXI仲裁算法與選型分析2.1 固定優(yōu)先級(jí)仲裁簡(jiǎn)單但餓死風(fēng)險(xiǎn)高固定優(yōu)先級(jí)仲裁Fixed Priority是最直覺(jué)的做法給每個(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問(wèn)題。舉個(gè)實(shí)際例子CPU和UART的DMA訪問(wèn)同一個(gè)DDR控制器如果CPU永遠(yuǎn)是最高優(yōu)先級(jí)而CPU又持續(xù)有緩存未命中的讀請(qǐng)求UART的DMA可能幾毫秒都拿不到總線。對(duì)于UART這種需要實(shí)時(shí)從FIFO搬運(yùn)數(shù)據(jù)的設(shè)備來(lái)說(shuō)幾毫秒的空窗就意味著FIFO溢出數(shù)據(jù)直接丟失。我之前做過(guò)一個(gè)帶AXI UART16550核的項(xiàng)目默認(rèn)配置里CPU是最高優(yōu)先級(jí)低優(yōu)先級(jí)里掛了一個(gè)UART DMA通道。調(diào)試串口經(jīng)常出現(xiàn)亂碼剛開(kāi)始懷疑是波特率不匹配后來(lái)抓了總線的波形才發(fā)現(xiàn)UART的讀請(qǐng)求經(jīng)常被CPU的突發(fā)讀插隊(duì)DMA服務(wù)間隔不穩(wěn)定FIFO發(fā)生了下溢。改成UART DMA的優(yōu)先級(jí)高于CPU之后問(wèn)題當(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是解決餓死問(wèn)題最直接的策略多個(gè)master的請(qǐng)求排成一個(gè)圈仲裁指針每拍移動(dòng)到下一個(gè)master有請(qǐng)求就放行沒(méi)請(qǐng)求就跳過(guò)。這個(gè)方案保證了所有master在長(zhǎng)期統(tǒng)計(jì)下能獲得大致相等的總線訪問(wèn)機(jī)會(huì)。設(shè)計(jì)上有兩個(gè)變體需要注意。一種是固定順序輪詢指針永遠(yuǎn)按0→1→2→3的順序移動(dòng)無(wú)論當(dāng)前master是否有請(qǐng)求。另一種是跳過(guò)式輪詢指針會(huì)跳到有請(qǐng)求的master減少無(wú)效輪詢周期。后者的效率更高但實(shí)現(xiàn)上需要額外的查找邏輯時(shí)序要稍微緊一點(diǎn)。不過(guò)輪詢仲裁也有它的軟肋它對(duì)延遲不敏感也沒(méi)有優(yōu)先級(jí)概念。如果某個(gè)master對(duì)實(shí)時(shí)性要求很高比如視頻解碼器需要每幀固定的帶寬輪詢給出的只是統(tǒng)計(jì)學(xué)意義上的公平延遲抖動(dòng)依然存在。這時(shí)候就需要加權(quán)輪詢或者QoS機(jī)制來(lái)調(diào)節(jié)。在實(shí)際工程里一個(gè)常見(jiàn)的折中方案是“輪詢?yōu)橹鲀?yōu)先級(jí)為輔”默認(rèn)所有master按輪詢仲裁但每當(dāng)某個(gè)高優(yōu)先級(jí)master連續(xù)等待超過(guò)設(shè)定周期時(shí)臨時(shí)把仲裁結(jié)果切給它。這種自適應(yīng)方案兼顧了公平和實(shí)時(shí)不過(guò)狀態(tài)機(jī)復(fù)雜度會(huì)明顯上升。2.3 加權(quán)輪詢按帶寬需求分配總線時(shí)間加權(quán)輪詢Weighted Round-Robin解決的是“公平但不夠用”的問(wèn)題。比如DMA需要70%的帶寬CPU只需要30%簡(jiǎn)單的輪詢會(huì)各分50%DMA的帶寬就欠了。加權(quán)的思路是給每個(gè)master分配一個(gè)權(quán)重值權(quán)重大的master在每輪仲裁中獲得更多的服務(wù)次數(shù)。實(shí)現(xiàn)上有兩種常見(jià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)帶寬模型來(lái)計(jì)算但在實(shí)際SoC里主master的帶寬需求往往是動(dòng)態(tài)的——比如CPU的DDR訪問(wèn)量隨負(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是誰(shuí)只需要看QOS值就能做仲裁決定。QOS信號(hào)的價(jià)值在于它把“誰(shuí)的請(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ù)操作騰帶寬。不過(guò)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ù)傳輸都通過(guò)valid/ready握手完成。發(fā)起方拉高valid表示數(shù)據(jù)有效接收方拉高ready表示可以接收兩者同時(shí)為高時(shí)傳輸發(fā)生。仲裁器介入后實(shí)際上扮演了“接收方發(fā)起方”的雙重角色對(duì)上游master來(lái)說(shuō)是slave對(duì)下游slave來(lái)說(shuō)是master。仲裁時(shí)機(jī)的選擇直接關(guān)系到一個(gè)問(wèn)題是等master的valid信號(hào)拉高之后再仲裁還是提前預(yù)判我的經(jīng)驗(yàn)是對(duì)于地址通道通常等valid拉高后再仲裁就夠了因?yàn)榈刂吠ǖ赖恼?qǐng)求不是每拍都有的仲裁器本身也要等請(qǐng)求到來(lái)才能做決定。但對(duì)于數(shù)據(jù)通道如果希望做到背靠背傳輸back-to-back預(yù)判是必要的——在最后一拍數(shù)據(jù)還沒(méi)傳完時(shí)就開(kāi)始仲裁下一筆傳輸?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è)特性極大提升了總線利用率但也給仲裁器帶來(lái)了麻煩仲裁器不能只看當(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ù)沒(méi)到上限就允許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ù)就無(wú)法區(qū)分屬于哪個(gè)master。我踩過(guò)一個(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ú)立開(kāi)才徹底解決。3.3 寫(xiě)通道仲裁的特殊性AW、W、B三個(gè)通道的配合很多剛開(kāi)始接觸AXI仲裁的人會(huì)犯一個(gè)錯(cuò)誤只仲裁AW通道忽略了W通道。實(shí)際上寫(xiě)操作涉及三個(gè)通道AW寫(xiě)地址、W寫(xiě)數(shù)據(jù)、B寫(xiě)響應(yīng)。如果AW和W的仲裁策略不一致就會(huì)出現(xiàn)地址通道選了master A數(shù)據(jù)通道卻傳著master B的數(shù)據(jù)結(jié)果這兩個(gè)master的寫(xiě)操作互相串?dāng)_。為了保證寫(xiě)操作的正確性仲裁器通常需要把AW和W通道綁定在同一仲裁域里。也就是說(shuō)當(dāng)仲裁器決定為master A的寫(xiě)操作打開(kāi)閘門(mén)時(shí)它的AW請(qǐng)求和W請(qǐng)求都必須被同時(shí)放行。這帶來(lái)一個(gè)數(shù)據(jù)緩沖的問(wèn)題如果下游slave暫時(shí)無(wú)法接收W數(shù)據(jù)仲裁器要把master A的寫(xiě)數(shù)據(jù)緩存下來(lái)這就涉及FIFO深度設(shè)計(jì)。AW和W還有一個(gè)同步問(wèn)題AXI協(xié)議不要求W數(shù)據(jù)和AW請(qǐng)求嚴(yán)格同拍到達(dá)但要求所有W數(shù)據(jù)必須在對(duì)應(yīng)的AW請(qǐng)求之后到達(dá)。仲裁器需要記錄每個(gè)master的寫(xiě)請(qǐng)求狀態(tài)確保不會(huì)出現(xiàn)AW還沒(méi)放行W數(shù)據(jù)先到的情況。實(shí)際實(shí)現(xiàn)中最簡(jiǎn)單的策略是AW和W按同一個(gè)仲裁結(jié)果走仲裁為誰(shuí)服務(wù)就把兩個(gè)通道的閘門(mén)都打開(kāi)。3.4 多master訪問(wèn)DDR時(shí)的死鎖與屏障處理多master并發(fā)訪問(wèn)DDR時(shí)最頭痛的問(wèn)題是死鎖。考慮一個(gè)場(chǎng)景master A正在對(duì)slave X做讀操作master B正在對(duì)slave Y做寫(xiě)操作而這兩個(gè)slave內(nèi)部又相互依賴。仲裁器如果不加約束理論上就可能互相等待。AXI協(xié)議本身沒(méi)有定義屏障Barrier機(jī)制但AXI4增加了屏障事務(wù)Barrier Transaction的概念當(dāng)一個(gè)master發(fā)出屏障請(qǐng)求時(shí)它要求在此之前所有outstanding的傳輸都完成之后的新傳輸才能開(kāi)始。仲裁器在收到屏障請(qǐng)求后需要暫時(shí)停止對(duì)這個(gè)master放行新請(qǐng)求直到它的所有未完成傳輸全部返回。系統(tǒng)級(jí)死鎖的預(yù)防還需要考慮更宏觀的因素——比如CPU核和DMA之間通過(guò)外設(shè)寄存器的握手邏輯。如果CPU在等待DMA完成中斷而DMA又在等待CPU釋放某個(gè)外設(shè)鎖兩邊都卡在總線訪問(wèn)上系統(tǒng)就死鎖了。這類問(wèn)題通??砍瑫r(shí)計(jì)數(shù)器來(lái)兜底仲裁器里的每筆請(qǐng)求都應(yīng)該維護(hù)一個(gè)超時(shí)標(biāo)志超時(shí)后強(qiáng)制丟棄或上報(bào)。4. 實(shí)操?gòu)牧愦罱ㄒ粋€(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)求如果沒(méi)有再?gòu)淖畹臀婚_(kāi)始找。這個(gè)寫(xiě)法簡(jiǎn)潔高效FPGA綜合后只會(huì)占用很少的LUT。4.2 寫(xiě)數(shù)據(jù)通道的FIFO緩沖與背壓處理地址通道仲裁只是第一步。為了讓寫(xiě)數(shù)據(jù)W通道能夠與AW通道解耦仲裁器內(nèi)部通常需要為每個(gè)master設(shè)置一個(gè)寫(xiě)數(shù)據(jù)FIFO。master的數(shù)據(jù)先寫(xiě)入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è)問(wèn)題我給仲裁器的每個(gè)FIFO都加了一個(gè)almost_full信號(hào)當(dāng)FIFO快滿時(shí)就不再對(duì)該master進(jìn)行仲裁。這個(gè)細(xì)節(jié)在實(shí)際調(diào)試中幫了大忙否則DMA在突發(fā)傳輸中途被插斷恢復(fù)起來(lái)非常影響性能。4.3 讀數(shù)據(jù)返回通道的仲裁與ID重映射讀數(shù)據(jù)通道R的仲裁和寫(xiě)數(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仲裁器通過(guò)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í)序圖來(lái)人工檢查。重點(diǎn)看幾個(gè)信號(hào)arb_grant當(dāng)前仲裁勝利者、ar_ready地址通道握手、以及各master的ar_valid。抓時(shí)序圖時(shí)最容易發(fā)現(xiàn)的問(wèn)題是仲裁切換過(guò)快或過(guò)慢。仲裁切換過(guò)快一個(gè)master還沒(méi)發(fā)完一筆突發(fā)請(qǐng)求就被切走會(huì)導(dǎo)致slave端收到碎片化的請(qǐng)求序列切換太慢則可能在其他master有高優(yōu)先級(jí)請(qǐng)求時(shí)仍然占用總線。一個(gè)常見(jiàn)的時(shí)序圖場(chǎng)景是master A的ar_valid持續(xù)拉高但ar_ready只在某些周期有效。如果仲裁器在ar_ready無(wú)效時(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)試中的常見(jiàn)問(wèn)題與排查技巧5.1 問(wèn)題速查表癥狀可能原因排查方法DMA傳輸數(shù)據(jù)錯(cuò)亂寫(xiě)數(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)求過(guò)于頻繁改用RRQOS混合仲裁或增加權(quán)重讀數(shù)據(jù)返回亂序錯(cuò)亂ID重映射錯(cuò)誤多個(gè)master的ID沒(méi)有隔離檢查仲裁器的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通過(guò)AXI總線訪問(wèn)UART的寄存器FIFO實(shí)際上就是AXI讀寫(xiě)寄存器操作但請(qǐng)求頻率不高——每次就4字節(jié)的讀或?qū)?。系統(tǒng)里還有一個(gè)千兆以太網(wǎng)MAC其DMA會(huì)發(fā)起長(zhǎng)突發(fā)讀和寫(xiě)DDR。一開(kāi)始UART在現(xiàn)代調(diào)試串口上偶爾丟字符沒(méi)太當(dāng)回事直到有一天從FPGA上采集到UART的DMA請(qǐng)求延遲超過(guò)了100微秒才意識(shí)到問(wèn)題嚴(yán)重。排查過(guò)程是這樣的先看仲裁器的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。后來(lái)我改成了加權(quán)輪詢給UART一個(gè)最低權(quán)重確保每個(gè)輪詢周期至少服務(wù)一次。改完之后抓波形UART DMA請(qǐng)求的服務(wù)間隔穩(wěn)定在2微秒以內(nèi)丟字符問(wèn)題徹底消失。這個(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讀寫(xiě)并發(fā)時(shí)的帶寬分配另一個(gè)常見(jiàn)場(chǎng)景是AXI Quad SPIQSPI控制器和CPU同時(shí)訪問(wèn)DDR。QSPI需要周期性讀寫(xiě)Flash速度不快但每次訪問(wèn)的延遲必須穩(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的大塊讀寫(xiě)可以吃滿剩余帶寬而QSPI的訪問(wèn)延遲始終可控。另一種思路是讓QSPI走專用的低延遲路徑繞過(guò)主仲裁器。在SoC里這叫做側(cè)信道sideband專門(mén)給對(duì)延遲敏感但帶寬需求低的控制面通信使用。這個(gè)方案在復(fù)雜的SoC里經(jīng)??吹讲贿^(guò)會(huì)增加布線復(fù)雜度。選擇哪種方案需要綜合評(píng)估系統(tǒng)對(duì)延遲的容忍度和對(duì)布局面積的約束。5.4 驗(yàn)證過(guò)程中值得注意的邊界情況仲裁器的驗(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)該能通過(guò)超時(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都配合波形來(lái)確認(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的組合。沒(méi)有萬(wàn)能的仲裁器只有適配具體場(chǎng)景的仲裁器。最后分享一個(gè)調(diào)試技巧遇到AXI總線相關(guān)的性能問(wèn)題時(shí)不要一上來(lái)就看代碼或者仿真先抓一段真實(shí)總線波形。波形能直觀告訴你哪個(gè)master在占總線、哪個(gè)master在等待、仲裁器的grant切換頻率是多少。很多時(shí)候波形的異常一眼就能定位問(wèn)題比盲猜代碼高效得多。下一篇文章里我打算聊聊AXI的outstanding和ID管理這套機(jī)制和仲裁器配合得好不好直接決定了多master系統(tǒng)的最終性能。到時(shí)候把亂序返回、ID寬度擴(kuò)展、以及和DDR控制器交互的那些坑一起講清楚。