NIOS II与存储类外设连接时的问题

  1. 一篇博文:CPU与flash连接时地址线如何连接
  2. 问题:为何16Bits数据线,却连了地址线0
  3. 释疑:奇妙的Avalon总线
  4. 补充:Avalon总线概述

1、一篇博文:CPU与flash连接时地址线如何连接

  Flash与S3C44B0X连接时地址线为什么要偏移一位

  文中介绍的是,32位CPU内每个地址对应的一个字节,当访问32Bits的flash时没有问题,地址一一对应。那么当访问16Bits或者8Bits的外设时呢?
  16Bits外设时:CPU地址线A1连接外设的A0,CPU地址线A0悬空;
  8Bits外设时:CPU地址线A2连接外设的A0,CPU地址线A0、A1悬空。
  简单说这是因为外设的一个地址对应的不是一个字节,而是相应的数据线位数。这就需要有一层Memory Controller,其实现的功能以16Bits外设说明:
  当工程师编程访问(意味着CPU地址)地址0的int32数据时,Memory Controller就进行两次读或写,先是外设地址0(CPU地址0)的16Bits数据,然后外设地址1(CPU地址2)的16Bits数据,组合后提供给使用者。当工程师编程访问地址4的int32数据时,就是外设地址2、3的数据组合。当工程师编程访问地址2的int16数据时,就是外设地址1的数据。
  在看《嵌入式C文章精华》时遇到了此问题,学习此文后感觉茅塞顿开。

2、问题:为何16Bits数据线,却连了地址线0
  在接手的一个FPGA的开发项目中使用了512K的SRAM,数据线16位,地址线18位。
  电路设计中全部地址线都连了,包括A0。Verilog模块作为Memory Controller,并没有做相应处理。
  为什么还能跑的正常呢?
  难道是将错就错而变对?(这个常见,有些设计故意把地址线顺序反过来,读写能对应起来就OK,防止被盗版)
  由于NIOS II的软件程序中,访问的数据位数不是确定的,有8Bits、16Bits、32Bits,肯定会出错。
  为什么能跑呢?
3、释疑:奇妙的Avalon总线
  FPGA开发中verilog写的SRAM模块,经过Avalon总线与NIOS II CPU交互。那么Memory Controller的功能就是在Avalon总线中实现的。
  查阅altera提供的技术文档:《Avalon Interface Specification》
  可以找到如下表格:


  当从接口数据位数为16Bits时,从侧的地址自动按照数据位数计算地址。

  哈哈,那么关键点就是这里。疑惑迎刃而解。

4、补充:Avalon总线概述

  详情可查阅上面提供的链接。

  • Avalon Memory Mapped Interface (Avalon-MM)
  • Avalon Conduit Interface:可连接FPGA引脚,也可以相互连接(当然输入对输出)
  • Avalon Tri-State Conduit Interface (Avalon-TC) :注意经过三态桥后,就以字节为单位编址了,如本文第1点所述,连接外设时A0或A0、A1就不能接了
  • Avalon Streaming Interface (Avalon-ST):适合大数据量直接传输
  • Avalon Interrupt Interface:中断
  • Avalon Clock Interface
  • Avalon Reset Interface

  一种常用的模式是NIOS II CPU作为Avalon-MM的主接口,verilog模块写的外设为从接口。在目录“*:\altera\10.1\nios2eds\components\altera_nios2\HAL\inc”下有<io.h><alt_types.h>等。其中<io.h>有如下宏定义: 

1 #define __IO_CALC_ADDRESS_NATIVE(BASE, REGNUM) \
2 ((void *)(((alt_u8*)BASE) + ((REGNUM) * (SYSTEM_BUS_WIDTH/8))))
3  #define IORD(BASE, REGNUM) \
4  __builtin_ldwio (__IO_CALC_ADDRESS_NATIVE ((BASE), (REGNUM)))
5  #define IOWR(BASE, REGNUM, DATA) \
6  __builtin_stwio (__IO_CALC_ADDRESS_NATIVE ((BASE), (REGNUM)), (DATA))

    以上是静态地址对齐。操作的地址会直接给到verilog模块。

 1 #define __IO_CALC_ADDRESS_DYNAMIC(BASE, OFFSET) ((void *)(((alt_u8*)BASE) + (OFFSET)))
 2 #define IORD_32DIRECT(BASE, OFFSET) \
 3 __builtin_ldwio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)))
 4 #define IORD_16DIRECT(BASE, OFFSET) \
 5 __builtin_ldhuio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)))
 6 #define IORD_8DIRECT(BASE, OFFSET) \
 7 __builtin_ldbuio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)))
 8 
 9 #define IOWR_32DIRECT(BASE, OFFSET, DATA) \
10 __builtin_stwio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))
11 #define IOWR_16DIRECT(BASE, OFFSET, DATA) \
12 __builtin_sthio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))
13 #define IOWR_8DIRECT(BASE, OFFSET, DATA) \
14 __builtin_stbio (__IO_CALC_ADDRESS_DYNAMIC ((BASE), (OFFSET)), (DATA))

  以上是动态地址对齐,此时的Avalon总线就是Memory Controller的合格完成者。

posted @ 2015-09-17 21:18  梧桐亮  阅读(1166)  评论(0编辑  收藏  举报