正确理解Avalon MM总线的动态地址寻址Dynamic Addressing

目前Nios已经取消了Native寻址模式(即从设备到主设备寄存器直接映射),全部采用了Dynamic寻址模式,查找了目前存在的一些资料,尤其是某些教程,还在使用Native模式,对Dynamic动态模式避而不谈,还有好多资料摸棱两可,说的模模糊糊,感觉应该是没吃透这个东西,要么就是调试程序的使用使用固有的2或者4方法,其实为什么这么做,可能也不知道。下面根据查询官方手册,给出我的理解。

以下所说的32bit,16bit表示的都是数据宽度。
所有的寄存器都是8bit的!!
在Master来看,一个地址只对应一个寄存器!!!

1. Avalon MM 的master是32bit宽度

动态地址对齐方式是将MM从设备的地址空间连续地映射到主设备空间。内存类型的从设备控制器应该采用这种方式。在这种方式下,主设备的每一次读传输(或写传输)对应从设备一次或多次读传输(或写传输)。譬如,主设备数据宽度为32bit,从设备为16bit,则主设备每发起一次读传输,从设备将被读两次,用于返回32bit数据(由Avalon Interconnect Fabric逻辑插入状态机实现,用户无需关心具体实现),同理,每一次写操作,从设备执行两次写入操作。Dynamic对齐方式数据宽度限定为8*2^n次方,即只能为8 16 32 64等值
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 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是怎么来的?

2.1 8 bit

比如,外设中的数据长度为256,数据宽度为8bit。那么在外设中的数据存放方式为

地址数据 (8bit)
0x00REG[0]
0x01REG[1]
0x02REG[2]
REG[…]
0xFFREG[255]

在Dynmatic动态寻址模式下,master读入到Avalon MM 的时候是这样的

地址数据 (32-bit)
0x00REG[3] REG[2] REG[1] REG[0]
0x04REG[7] REG[6] REG[5] REG[4]
0x08REG[11] REG[10] REG[9] REG[8]
REG[…] REG[…] REG[…] REG[…]
0xFCREG[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是如何来的。

2.2 16bit

理解了8bit的之后,16bit数据就需要理解一下原始的数据存放方式中的地址,到底是不是所谓的寄存器地址了,之前说了,寄存器的数据宽度是8bit的,这个是永远不会变化的,而且master看每个地址只有一个8bit字节。综合这两句话,可以知道,其实每个16bit的数据实际上是由两个寄存器数据组成的,这样我们就需要重新排列以下原始数据了。

外设中的数据长度为128,数据宽度为16bit。那么在外设中的数据存放方式为

外设上的地址寄存器地址数据 (16bit)
0x000x01-0x00REG[1] REG[0]
0x010x03-0x02REG[3] REG[2]
0x020x05-0x04REG[5] REG[4]
0x…-0x…REG[…] REG[…]
0x7F0x7F-0x7EREG[255] REG[254]

在Dynmatic动态寻址模式下,master读入到Avalon MM 的时候是这样的

地址数据 (32-bit)
0x00REG[3] REG[2] REG[1] REG[0]
0x04REG[7] REG[6] REG[5] REG[4]
0x08REG[11] REG[10] REG[9] REG[8]
REG[…] REG[…] REG[…] REG[…]
0xFCREG[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)来去读取或者截取就好了,只需要计算好响应的寄存器变量下表就完事儿。

2.3 32bit 和64 bit

这样32bit和64bit,甚至更多,也就很好理解了。这里面唯独有一个特殊的就是32bit,因为32bit是和master一样的数据宽度,实际上无论是原来的静态寻址Native模式还是Dynamic动态模式都无所谓了,可以采用原来的Native模式下的APIIORD(BASE, REGNUM) ,主意,这里的REGNUM看样子说的是寄存器,实际上这里的寄存器是32bit的,也就是说是实际寄存器的4倍!!!就是因为很容易混淆,所以我个人极力不推荐采用原始的API。

3. 尾巴

最后附一个官方的新图
在这里插入图片描述
实在不想吐槽官方,给的图实在是看的不是通透,注意第二列 是Access,表示的是Master向Avalon MM总线第几次访问的次数!!!不是表示的偏移量!!!这个图的意思就是如果Slave是8bit的数据宽度,那就访问4次,得到全部32bit数据,如果是16bit,就访问2次…根本不是表示数据地址排列的,也没法指导怎么写API。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值