上篇文章給大家介紹了APB協(xié)議相關(guān)的知識點,本篇文章通過一個實際的APB slave的設(shè)計幫助大家鞏固對APB的掌握。
APB slave設(shè)計Spec

其框圖如上圖所示,這里提一嘴,大家在做數(shù)字IC設(shè)計的時候,都應(yīng)該像這樣規(guī)劃好各個模塊的連接關(guān)系,確定好以后再寫代碼。該模塊是一個基于APB協(xié)議完成寄存器配置或讀取的設(shè)計實例。設(shè)計相對比較簡單,但不失為一個很好的學(xué)習(xí)資料。
上面APB相關(guān)的信號都介紹過,這里不再重復(fù)介紹,其中的ECOREVNUM的意思是ECO revision number,如果沒有用到ARM的ECO的話,將該信號固定為全0即可。
右邊這個slave_reg實際上就對應(yīng)我們自己設(shè)計的IP的寄存器配置部分。這一部分的接口是native interface,也就是沒有考慮通用性的原生接口。想要通過APB總線對其進(jìn)行配置,就需要通過slave_interface這個模塊進(jìn)行協(xié)議轉(zhuǎn)換,進(jìn)而完成APB協(xié)議的傳輸。我們經(jīng)常能夠看到的apb2reg模塊,實際上也是做了這件事。該APB slave有以下的特點:
- 不支持反壓
- 不支持錯誤傳輸
- 支持4個RW類型的寄存器
- 支持12個RO類型寄存器
- 支持字節(jié)選通信號
APB slave設(shè)計代碼
apb_slave_interface代碼
下面是slave_interface的關(guān)鍵代碼邏輯。我們對其進(jìn)行分析:- 首先由于不支持反壓和錯誤傳輸,因此將pready固定為1,pslverr固定為0。
- APB傳輸進(jìn)來的paddr可以直接賦給addr,作為讀寫的地址。
- read_en需要在psel為1且pwrite為0的時候拉高。這實際上是希望在整個讀傳輸過程中都讓read_en信號有效。讀者可能就想問了,讀應(yīng)該對應(yīng)著兩個階段嗎?不需要判斷嗎?實際上讀的話,master那邊自己控制好就行了,對于slave而言完全可以在第一拍和第二拍都把rdata提供好,這個是沒有關(guān)系的。
- write_en則對應(yīng)著setup phase,實際上在這個場景中修改write_en的邏輯讓該信號對應(yīng)著access phase也是可以的,其它的信號直接賦值就可以,應(yīng)該很好理解。
// APB interface assign pready = 1'b1; //always ready. Can be customized to support waitstate if required. assign pslverr = 1'b0; //always OKAY. Can be customized to support error response if required. // register read and write signal assign addr = paddr; assign read_en = psel & (~pwrite); // assert for whole apb read transfer assign write_en = psel & (~penable) & pwrite; // assert for 1st cycle of write transfer // It is also possible to change the design to perform the write in the 2nd // APB cycle. E.g. // assign write_en = psel & penable & pwrite; // However, if the design generate waitstate, this expression will result // in write_en being asserted for multiple cycles. assign byte_strobe = pstrb; assign wdata = pwdata; assign prdata = rdata;
apb_slave_reg代碼
其關(guān)鍵邏輯如下所示,我們對其進(jìn)行分析:- 首先由于分為RW寄存器和RO寄存器。這里確定寫地址是否在規(guī)定區(qū)間,同時寫使能是否有效,以及byte_strobe信號,來決定要不要寫,寫哪個字節(jié)。
- 讀的話就比較簡單了,當(dāng)讀使能有效,根據(jù)地址信號決定rdata。實際上這就是個MUX選擇邏輯。根據(jù)read_en加地址從多個寄存器的Q端選出某一個來。
// Address decoding for write operations
assign wr_sel[0] = ((addr[(ADDRWIDTH-1):2]==10'b0000000000)&(write_en)) ? 1'b1: 1'b0;
assign wr_sel[1] = ((addr[(ADDRWIDTH-1):2]==10'b0000000001)&(write_en)) ? 1'b1: 1'b0;
assign wr_sel[2] = ((addr[(ADDRWIDTH-1):2]==10'b0000000010)&(write_en)) ? 1'b1: 1'b0;
assign wr_sel[3] = ((addr[(ADDRWIDTH-1):2]==10'b0000000011)&(write_en)) ? 1'b1: 1'b0;
// register write, byte enable
// Data register: data0
always @(posedge pclk or negedge presetn)
begin
if (~presetn)
begin
data0 <= {32{1'b0}}; // Reset data 0 to 0x00000000
end
else if (wr_sel[0])
begin
if (byte_strobe[0])
data0[ 7: 0] <= wdata[ 7: 0];
if (byte_strobe[1])
data0[15: 8] <= wdata[15: 8];
if (byte_strobe[2])
data0[23:16] <= wdata[23:16];
if (byte_strobe[3])
data0[31:24] <= wdata[31:24];
end
end
// register read
always @ (read_en or addr or data0 or data1 or data2 or data3 or ecorevnum)
begin
case (read_en)
1'b1:
begin
if (addr[11:4] == 8'h00) begin
case(addr[3:2])
2'b00: rdata = data0;
2'b01: rdata = data1;
2'b10: rdata = data2;
2'b11: rdata = data3;
default: rdata = {32{1'bx}};
endcase
end
else if (addr[11:6] == 6'h3F) begin
case(addr[5:2])
// Peripheral IDs and Component IDs.
// AHB example slave has part number of 818
4'b0100: rdata = ARM_CMSDK_APB4_EG_SLAVE_PID4; // 0xFD0 : PID 4
4'b0101: rdata = ARM_CMSDK_APB4_EG_SLAVE_PID5; // 0xFD4 : PID 5
4'b0110: rdata = ARM_CMSDK_APB4_EG_SLAVE_PID6; // 0xFD8 : PID 6
4'b0111: rdata = ARM_CMSDK_APB4_EG_SLAVE_PID7; // 0xFDC : PID 7
4'b1000: rdata = ARM_CMSDK_APB4_EG_SLAVE_PID0; // 0xFE0 : PID 0 APB Example slave part number[7:0]
4'b1001: rdata = ARM_CMSDK_APB4_EG_SLAVE_PID1; // 0xFE4 : PID 1 [7:4] jep106_id_3_0. [3:0] part number [11:8]
4'b1010: rdata = ARM_CMSDK_APB4_EG_SLAVE_PID2; // 0xFE8 : PID 2 [7:4] revision, [3] jedec_used. [2:0] jep106_id_6_4
4'b1011: rdata ={ARM_CMSDK_APB4_EG_SLAVE_PID3[31:8], ecorevnum[3:0], 4'h0};
// 0xFEC : PID 3 [7:4] ECO rev number, [3:0] modification number
4'b1100: rdata = ARM_CMSDK_APB4_EG_SLAVE_CID0; // 0xFF0 : CID 0
4'b1101: rdata = ARM_CMSDK_APB4_EG_SLAVE_CID1; // 0xFF4 : CID 1 PrimeCell class
4'b1110: rdata = ARM_CMSDK_APB4_EG_SLAVE_CID2; // 0xFF8 : CID 2
4'b1111: rdata = ARM_CMSDK_APB4_EG_SLAVE_CID3; // 0xFFC : CID 3
// Note : Customer changing the design should modify
// - jep106 value (www.jedec.org)
// - part number (customer define)
// - Optional revision and modification number (e.g. rXpY)
4'b0000, 4'b0001,4'b0010,4'b0011: rdata = {32'h00000000}; // default
default: rdata = {32{1'bx}}; // x propagation
endcase
end
else begin
rdata = {32'h00000000}; // default
end
end
1'b0:
begin
rdata = {32{1'b0}};
end
default:
begin
rdata = {32{1'bx}};
end
endcase
end
APB slave mux設(shè)計
這里再給大家介紹一下APB slave mux的概念,如下圖所示,基于APB slave mux我們可以快速地將多個apb slave連接在上面。在實際的設(shè)計當(dāng)中都是采用這樣的方式,連接多個slave的。一般我們管這種模塊叫做interconnect,顧名思義,將不同的模塊連接起來。而APB的interconnect只能連接一個master,因此繼續(xù)管他叫interconnect感覺差了點意思。所以一般就叫它slave mux了。


- 根據(jù)PSEL是否有效以及DECODE4BIT的值,完成16選1,PSEL0~PSEL15有一個或者0個拉高。
-
PREADYm默認(rèn)為1,當(dāng)PSEL為1的時候,根據(jù)譯碼結(jié)果選擇相應(yīng)的PREADY信號(當(dāng)端口沒有使能的時候
en[x] == 0
, 對應(yīng)的PREADYx
信號不會被選擇)。 - PSLVERR和PRDATA,選中誰就取誰的。
assign PSEL0 = PSEL & dec[ 0] & en[ 0];
assign PSEL1 = PSEL & dec[ 1] & en[ 1];
assign PSEL2 = PSEL & dec[ 2] & en[ 2];
//省略3~15
assign PREADY = ~PSEL |
( dec[ 0] & (PREADY0 | ~en[ 0]) ) |
( dec[ 1] & (PREADY1 | ~en[ 1]) ) |
( dec[ 2] & (PREADY2 | ~en[ 2]) ) |
//省略3~15
assign PSLVERR = ( PSEL0 & PSLVERR0 ) |
( PSEL1 & PSLVERR1 ) |
( PSEL2 & PSLVERR2 ) |
//省略3~15
assign PRDATA = ( {32{PSEL0 }} & PRDATA0 ) |
( {32{PSEL1 }} & PRDATA1 ) |
( {32{PSEL2 }} & PRDATA2 ) |
//省略3~15
這套代碼的缺點或者說優(yōu)點是,它是用組合邏輯做的,邏輯非常的簡單。實際上就是多選1,一般來說APB的時鐘頻率很低,所以增加了一定的組合邏輯級數(shù)也不會出現(xiàn)時鐘違例。這樣做還可以節(jié)省一個時鐘周期,大家也可以用時序邏輯去做,思路是類似的。還有一個問題就是這個模塊沒有PENABLE信號,這個其實挺致命,大家可以手動加上,跟PSEL的邏輯基本是一模一樣的,非常簡單。
-
寄存器
+關(guān)注
關(guān)注
31文章
5421瀏覽量
123371 -
AMBA總線
+關(guān)注
關(guān)注
0文章
35瀏覽量
9778
原文標(biāo)題:深入理解AMBA總線 — APB slave設(shè)計
文章出處:【微信號:IC修真院,微信公眾號:IC修真院】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
ARM總線協(xié)議AMBA中AHB、APB的區(qū)別與聯(lián)系
AMBA、APB、AHB簡介
AMBA AHB總線與APB總線資料合集
分享一個APB slave的verilog實例
AMBA中的APB總線協(xié)議詳解
基于AMBA APB總線NandFlash控制器的設(shè)計
基于AMBA總線介紹?

介紹AMBA2.0總線

數(shù)字IC驗證:ARM總線協(xié)議AMBA中AHB、APB的簡介、區(qū)別與聯(lián)系

AMBA總線—apb簡介

關(guān)于AMBA APB總線的知識點介紹

AMBA總線中APB interconnect的介紹

評論