之前老李問過大家想看哪方面的知識(shí),有不少同學(xué)提議老李寫寫總線,特別是AMBA的總線,所以老李決定從這期開始開始一個(gè)AMBA總線介紹的系列文章。AMBA總線主要包括三種最常見的協(xié)議APB, AHB, AXI,它們的復(fù)雜度、性能和設(shè)計(jì)難度都是遞增的。在網(wǎng)上介紹三種協(xié)議的文章有不少,絕大多數(shù)都是把ARM的協(xié)議文檔翻譯一下,但是很少有人來系統(tǒng)介紹總線中的不同功能模塊的設(shè)計(jì),特別是微架構(gòu)層面的設(shè)計(jì)邏輯。所以老李決定要提供給大家一些不一樣的內(nèi)容,在介紹協(xié)議基本內(nèi)容的基礎(chǔ)上,加入一些總線模塊的設(shè)計(jì)介紹,目的是讓大家有個(gè)更加直觀和具體的理解。當(dāng)然老李的水平也有限,有不少內(nèi)容也需要學(xué)習(xí),有不足的地方也歡迎大家批評(píng)指正。
咱們首先來介紹AMBA(Advanced Microcontroller Bus Architecture)家族中最簡(jiǎn)單的協(xié)議APB -- Advanced Peripheral Bus。其實(shí)整個(gè)AMBA家族的協(xié)議也都有些年頭了,1998年的時(shí)候就發(fā)布了ABMA2, 2003年發(fā)布了ABMA3 APB 1.0版,2010年發(fā)布了AMBA 3 APB的2.0版。因?yàn)锳MBA2太過久遠(yuǎn),現(xiàn)在主流的SoC里絕大多數(shù)IP都支持的是AMBA3 的APB。之后老李的介紹也是基于ABMA 3的APB1.0。
廢話不多說,先說APB能干啥,對(duì)于Bus,最核心的功能就是讀和寫,搞清楚有哪些控制信號(hào)和讀寫時(shí)序是最基本的。APB的協(xié)議非常簡(jiǎn)單,控制信號(hào)也很少,咱們直接上時(shí)序圖理解。
寫時(shí)序
這里先插一句,AMBA把它的三個(gè)協(xié)議APB, AHB, 和AXI的信號(hào)命名都很有規(guī)范,APB的信號(hào)都是以P開頭,AHB的信號(hào)都是以H開頭,AXI的信號(hào)卻不是以X開頭,而是以A開頭,這種命名方式幾乎成為了在設(shè)計(jì)AMBA總線模塊時(shí)候的潛規(guī)則,雖然ARM沒有規(guī)定你一定要用這種方式命名你的信號(hào),但是在大家設(shè)計(jì)不同模塊和接口的時(shí)候,大家基本都遵循這種命名規(guī)則,這樣IP的使用者一眼就明白信號(hào)的用途,方便你我方便大家。
PCLK是總線時(shí)鐘,在上面的圖中,Master驅(qū)動(dòng)的是PADDR, PWRITE, PSEL, PENABLE, PWDATA,而Slave只驅(qū)動(dòng)PREADY。PADDR是transaction的地址,PWRITE用來區(qū)分是write還是read,如果是write transaction就是1,是read就是0。PWDATA就是write transaction的數(shù)據(jù)。PWDATA只在write transaction起作用。
然后就是非常重要的PSEL, PENABLE以及PREADY信號(hào),這3個(gè)信號(hào)之間的關(guān)系標(biāo)志著一次transaction的開始和結(jié)束:
PSEL從0變?yōu)?,表明要開始一個(gè)新的transaction。
PSEL為1的第一個(gè)周期,PENABLE要為0,然后在下一個(gè)周期變?yōu)?。
當(dāng)Slave可以確保在下一個(gè)時(shí)鐘沿接受到PWDATA時(shí),就可以把PREADY變?yōu)?。
當(dāng)Master看到PREADY為1后,就可以在下一個(gè)時(shí)鐘沿把PSEL,PENABLE拉為0,結(jié)束transaction。
注意:
PWDATA,PADDR, PWRITE需要在PSEL為高一直到PREADY為高期間都保持穩(wěn)定。
PENABLE必須要在PSEL為高的第一個(gè)周期為0(稱為setup phase),第二個(gè)周期為1,直到PREADY為1(稱為access phase)。
如果Master想要在PREADY為高之后下一個(gè)沿立刻開始新的transaction,可以不拉低PSEL,而使得PSEL繼續(xù)為1,但是一定要把PENABLE拉低。
然后再來看看讀的時(shí)序,其中PSEL, PENABLE, PADDR, PREADY都一致,區(qū)別只在于PWRITE要為0, 以及是由Slave來返回PRDATA,注意要和PREADY在同一個(gè)周期返回。
我們看到,APB的讀和寫不能同時(shí)進(jìn)行,每一個(gè)transaction要么是讀,要么是寫,由PWRITE來控制。每一個(gè)transaction至少需要2個(gè)周期。這兩點(diǎn)導(dǎo)致了APB在AMBA三兄弟中是最低性能的,但是好處是協(xié)議簡(jiǎn)單,Master和Slave的設(shè)計(jì)都只需要很少的邏輯。甚至在Spec里ARM都幫你畫好了狀態(tài)機(jī)(至于AHB和AXI, ARM的Spec就沒有幫你畫狀態(tài)機(jī)了,你得自己設(shè)計(jì))。
APB通常是作為Peripheral IP的寄存器讀寫總線接口,有些IP可能年頭很久,速度很慢,所以即使給了一個(gè)周期去setup,也不能夠在第二個(gè)周期確保完成讀或?qū)?,所以slave可以選擇在沒有準(zhǔn)備好的時(shí)候不assert PREADY,插入wait cycle。咱們?cè)俜艃蓚€(gè)有wait state的時(shí)序圖。
有wait state的寫時(shí)序圖
有wait state的讀時(shí)序圖
這和valid/ready協(xié)議有點(diǎn)類似,即slave不返回PREADY,那么master就要保證PSEL, PENABLE, PADDR, PWRITE,PWDATA穩(wěn)定,直到PREADY為1。
另外還有個(gè)信號(hào)PSLVERR (apb slave error),用于從slave向master返回transaction錯(cuò)誤,這個(gè)錯(cuò)誤可以由slave自己來定義,比如是非法地址訪問,也可以是訪問timeout了,slave無法在timeout到來之前返回有效的值,那么就可以返回PREADY和PSLVERR來通知master,并且避免總線鎖死。
AMB3 APB2.0又加了2個(gè)信號(hào),PPROT和PPROB,這其實(shí)是把AHB和AXI中關(guān)于總線transaction的保護(hù)和寫操作中的按字節(jié)部分寫入的功能引入APB,咱們就不過多介紹。到AHB和AXI的時(shí)候再講。
關(guān)于APB總線協(xié)議部分就這么多,老李覺得簡(jiǎn)單到可以給剛學(xué)數(shù)字電路設(shè)計(jì)這門課的本科生拿來當(dāng)做一個(gè)小作業(yè),然后讓大家設(shè)計(jì)一個(gè)master和slave應(yīng)該都是不錯(cuò)的嘗試。
協(xié)議介紹完了,我們今天來介紹一個(gè)小模塊:APB Slice。先說說Slice的作用,在SoC中,如果Master和Slave的距離比較遠(yuǎn),那么它們之間的bus信號(hào)要滿足timing就可能有點(diǎn)困難,比如我們上面看到的PSEL, PENABLE, PADDR, PWRITE這些信號(hào)從Master出來,要去很遠(yuǎn)的Slave,那么中間就要加很多的buffer,這引入的buffer delay就可能導(dǎo)致我們希望的timing不滿足。這個(gè)時(shí)候就需要插入slice,給每個(gè)控制信號(hào)在中間加一級(jí)寄存器,把較長(zhǎng)的走線縮短。當(dāng)然插入的slice依然要保持bus的協(xié)議標(biāo)準(zhǔn)。簡(jiǎn)單來說,一個(gè)slice就是下面中間的那個(gè)模塊,站在APB slave的角度,APB slice是它的master,從Slice出來的控制信號(hào)需要滿足APB的協(xié)議要求。
這里面我們一個(gè)信號(hào)一個(gè)信號(hào)來看,先來看最關(guān)鍵的PSEL
always_ff @(posedge PCLK)
if(!PRESETn)
out_PSEL <= 1'b0;
else if(out_PENABLE && out_PREADY)
out_PSEL <= 1'b0;
else if(in_PSEL && !in_PENABLE)
out_PSEL <= 1'b1;
思路很簡(jiǎn)單,當(dāng)APB slave返回了PREADY,那么transaction結(jié)束,需要out_PSEL變?yōu)?。而當(dāng)APB master拉起了in_PSEL且in_PENABLE為0時(shí),標(biāo)志一個(gè)新的transaction開始,需要將out_PSEL拉高。
再來看PENABLE,類似的,當(dāng)out_PSEL為1的時(shí)候,還是分setup phase和access phase,當(dāng)access phase并out_PREADY為1的時(shí)候,out_PENABLE要拉回0,out_PREADY為0的時(shí)候PENABLE要保持為1。在setup phase則需要把PENABLE拉為1。
always_ff @(posedge PCLK) begin
if(!PRESETn)
out_PENABLE <= 1'b0;
else if(out_PSEL)
if(out_PENABLE && out_PREADY)
out_PENABLE <= 1'b0;
else if(!out_PENABLE)
out_PENABLE <= 1'b1;
end
反過來,對(duì)于in_PREADY和in_PSLVERR,APB slice則作為APB Master的slave來返回。只有當(dāng)APB slave返回了PREADY和PSLVERR之后,APB slice才能assert in_PREADY。
always_ff @(posedge PCLK) begin
if(!PRESETn)
in_PREADY <= 1'b0;
else if(in_PREADY)
in_PREADY <= 1'b0;
else if(out_PREADY && out_PENABLE)
in_PREADY <= 1'b1;
end
always_ff @(posedge PCLK) begin
if(!PRESETn)
in_PSLVERR <= 1'b0;
else if(in_PREADY)
in_PSLVERR <= 1'b0;
else if(out_PREADY && out_PENABLE)
in_PSLVERR <= out_PSLVERR;
end
而對(duì)于剩下的PADDR, PWRITE以及PRDATA,由于slice的setup phase比master的setup phase晚一拍,那么只需啊在master的setup phase的時(shí)候寄存它們的值就行。
always_ff @(posedge PCLK)
if(in_PSEL && !in_PENABLE) begin
out_PADDR <= in_PADDR;
out_PWRITE <= in_PWRITE;
if(in_PWRITE)
out_PWDATA <= in_PWDATA;
end
always_ff @(posedge PCLK)
if(out_PENABLE && out_PREADY && !out_PWRITE)
in_PRDATA <= out_PRDATA;
我們引入的這個(gè)slice的握手是雙向的,對(duì)于每一個(gè)從master發(fā)出的transaction,只有當(dāng)slave返回了out_PREADY之后slice才會(huì)返回給master in_PREADY,也就是說,slice的引入使得從master的角度看出去的延時(shí)增加了一個(gè)周期,換句話說插入了一個(gè)氣泡。這個(gè)我們之前提到過的valid/ready 的ping pong buffer可以避免氣泡還是有不同的。但是由于APB通常來說是低速總線,對(duì)于transaction多一個(gè)周期少一個(gè)周期其實(shí)不太關(guān)心。真正需要關(guān)心性能和訪問延遲的地方一般也不會(huì)使用APB來作為總線。所以這里引入一個(gè)周期的氣泡完全可以接受。
下一篇開始老李會(huì)再帶領(lǐng)大家看看當(dāng)一個(gè)Master要訪問多個(gè)slave或者多個(gè)master要同時(shí)訪問一個(gè)slave時(shí)我們需要什么樣的APB模塊來疏導(dǎo)各個(gè)transaction避免沖突。
-
AMBA
+關(guān)注
關(guān)注
0文章
68瀏覽量
14940 -
AHB
+關(guān)注
關(guān)注
0文章
18瀏覽量
9755 -
AXI總線
+關(guān)注
關(guān)注
0文章
66瀏覽量
14244
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論