正確理解Avalon MM總線的動態地址尋址Dynamic Addressing

目前Nios已經取消了Native尋址模式(即從設備到主設備寄存器直接映射),全部採用了Dynamic尋址模式,查找了目前存在的一些資料,尤其是某些教程,還在使用Native模式,對Dynamic動態模式避而不談,還有好多資料摸棱兩可,說的模模糊糊,感覺應該是沒喫透這個東西,要麼就是調試程序的使用使用固有的2或者4方法,其實爲什麼這麼做,可能也不知道。下面根據查詢官方手冊,給出我的理解。

以下所說的32bit,16bit表示的都是數據寬度。
所有的寄存器都是8bit的!!
在Master來看,一個地址只對應一個寄存器!!!

Avalon MM 的master是32bit寬度

動態地址對齊方式是將MM從設備的地址空間連續地映射到主設備空間。內存類型的從設備控制器應該採用這種方式。在這種方式下,主設備的每一次讀傳輸(或寫傳輸)對應從設備一次或多次讀傳輸(或寫傳輸)。譬如,主設備數據寬度爲32bit,從設備爲16bit,則主設備每發起一次讀傳輸,從設備將被讀兩次,用於返回32bit數據(由Avalon Interconnect Fabric邏輯插入狀態機實現,用戶無需關心具體實現),同理,每一次寫操作,從設備執行兩次寫入操作。Dynamic對齊方式數據寬度限定爲8*2^n次方,即只能爲8 16 32 64等值
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

Slave端的數據寬度

在軟件編程時,使用IOWR_32DIRECT(數據位寬爲32位)、IOWR_16DIRECT(數據位寬爲16位)、IOWR_8DIRECT(數據位寬爲8位)進行寫操作
在軟件編程時,使用IORD_32DIRECT(數據位寬爲32位)、IORD_16DIRECT(數據位寬爲16位)、IOWR_RDIRECT(數據位寬爲8位)進行寫操作

IOWR_8DIRECT(基地址、地址偏移量、數據),地址偏移量 = 寄存器編號1
IOWR_16DIRECT(基地址、地址偏移量、數據),地址偏移量 = 寄存器編號
2
IOWR_32DIRECT(基地址、地址偏移量、數據),地址偏移量 = 寄存器編號*4

IORD_8DIRECT(基地址、地址偏移量),地址偏移量 = 寄存器編號1
IORD_16DIRECT(基地址、地址偏移量),地址偏移量 = 寄存器編號
2
IORD_32DIRECT(基地址、地址偏移量),地址偏移量 = 寄存器編號*4

這裏引出個問題,這個乘1、2、4是怎麼來的?

8 bit

比如,外設中的數據長度爲256,數據寬度爲8bit。那麼在外設中的數據存放方式爲

地址 數據 (8bit)
0x00 REG[0]
0x01 REG[1]
0x02 REG[2]
REG[…]
0xFF REG[255]

在Dynmatic動態尋址模式下,master讀入到Avalon MM 的時候是這樣的

地址 數據 (32-bit)
0x00 REG[3] REG[2] REG[1] REG[0]
0x04 REG[7] REG[6] REG[5] REG[4]
0x08 REG[11] REG[10] REG[9] REG[8]
REG[…] REG[…] REG[…] REG[…]
0xFC REG[255] REG[254] REG[253] REG[252]

根據上面的表格,當採用指令IORD_32DIRECT(BASE,OFFSET)的時候,讀出的數據是32bit的也就是是4個字節,或者稱爲4個寄存器。有如下規律:

IORD_32DIRECT(BASE,0)  //得到第一組4個寄存器(0-3)數據
IORD_32DIRECT(BASE,4)  //得到第二組4個寄存器(4-7)數據

如果要單獨讀取某一個寄存器,那麼就是用提供的API

IORD_8DIRECT(BASE,0)  //得到第1個寄存器(0)數據
IORD_8DIRECT(BASE,1)  //得到第2個寄存器(1)數據

這才解釋了上面引用的代碼IORD_8DIRECT(基地址、地址偏移量),地址偏移量 = 寄存器編號*1這裏的1是如何來的。

16bit

理解了8bit的之後,16bit數據就需要理解一下原始的數據存放方式中的地址,到底是不是所謂的寄存器地址了,之前說了,寄存器的數據寬度是8bit的,這個是永遠不會變化的,而且master看每個地址只有一個8bit字節。綜合這兩句話,可以知道,其實每個16bit的數據實際上是由兩個寄存器數據組成的,這樣我們就需要重新排列以下原始數據了。

外設中的數據長度爲128,數據寬度爲16bit。那麼在外設中的數據存放方式爲

外設上的地址 寄存器地址 數據 (16bit)
0x00 0x01-0x00 REG[1] REG[0]
0x01 0x03-0x02 REG[3] REG[2]
0x02 0x05-0x04 REG[5] REG[4]
0x…-0x… REG[…] REG[…]
0x7F 0x7F-0x7E REG[255] REG[254]

在Dynmatic動態尋址模式下,master讀入到Avalon MM 的時候是這樣的

地址 數據 (32-bit)
0x00 REG[3] REG[2] REG[1] REG[0]
0x04 REG[7] REG[6] REG[5] REG[4]
0x08 REG[11] REG[10] REG[9] REG[8]
REG[…] REG[…] REG[…] REG[…]
0xFC REG[255] REG[254] REG[253] REG[252]

看沒看到,實際上和8bit的時候是一樣一樣的,這個也就是爲什麼說將Native尋址模式幹掉的原因了,因爲無論外部如何變化,採用動態尋址的模式,到內部的寄存器排列模式是一摸一樣的。這樣就理解了Altera的那句使用Dynamic更加便捷的原因了。
有代碼

IORD_32DIRECT(BASE,0)  //得到第一組2個16bit 4個寄存器(0-3)數據
IORD_32DIRECT(BASE,4)  //得到第二組2個16bit 4個寄存器(4-7)數據

同樣如果要單獨讀取某一個16bit數據(2個寄存器),那麼就是用提供的API

IORD_16DIRECT(BASE,0)    //得到外設地址0x00上的1個16bit 2個寄存器(0-1)數據
IORD_16DIRECT(BASE,2)    //得到外設地址0x01上的1個16bit 2個寄存器(2-3)數據

解釋了上面引用的代碼IORD_16DIRECT(基地址、地址偏移量),地址偏移量 = 寄存器編號*2這裏的2是如何來的。

總結起來就是這樣:
無論外部設備上的地址或者數據寬度如何變化,我(master)從AvalonMM總線上讀取過來的數據都是一片連續的由8bit寄存器組成的內存空間,具體表示的數據是多少位的,通過3種不同的API(8DIRECT、16DIRECT、32DIRECT)來去讀取或者截取就好了,只需要計算好響應的寄存器變量下表就完事兒。

32bit 和64 bit

這樣32bit和64bit,甚至更多,也就很好理解了。這裏面唯獨有一個特殊的就是32bit,因爲32bit是和master一樣的數據寬度,實際上無論是原來的靜態尋址Native模式還是Dynamic動態模式都無所謂了,可以採用原來的Native模式下的APIIORD(BASE, REGNUM) ,主意,這裏的REGNUM看樣子說的是寄存器,實際上這裏的寄存器是32bit的,也就是說是實際寄存器的4倍!!!就是因爲很容易混淆,所以我個人極力不推薦採用原始的API。

尾巴

最後附一個官方的新圖
在這裏插入圖片描述
實在不想吐槽官方,給的圖實在是看的不是通透,注意第二列 是Access,表示的是Master向Avalon MM總線第幾次訪問的次數!!!不是表示的偏移量!!!這個圖的意思就是如果Slave是8bit的數據寬度,那就訪問4次,得到全部32bit數據,如果是16bit,就訪問2次…根本不是表示數據地址排列的,也沒法指導怎麼寫API。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章