Board logo

标题: CME-M5 外部存储器接口(EMIF)总线使用指南 [打印本页]

作者: porereading    时间: 2013-8-27 17:45     标题: CME-M5 外部存储器接口(EMIF)总线使用指南

关键字:京微雅格 8051 FPGA
一、EMIF总线概述
外部存储器总线(EMIF, External Memory Interface)总线是京微雅格(CME)的8051硬核与FPGA之间的并行8位总线接口,主要的信号有6个,分别为:

memaddr[22:0]:23位地址总线,对应8M地址空间;
memdatao[7:0]:8位数据输出总线;
memdatai[7:0]:8位数据输入总线;
memrd:总线读信号;
memwr:总线写信号;
memack:总线应答信号;

与EMIF操作时序有关的8051的内部寄存器为CKCON寄存器,一般8051的初始化程序需要在主函数的初始化更改该寄存器的初始化值,以实现最快的总线访问效率。

1、EMIF总线相关的MCU寄存器:CKCON
CKCON主要作用是设置存储器地址总线memaddr[22:0]和读写memwr/ memerd信号的宽度,已实现对不同外设时序的操作,若宽度仍不够,也可以通过memack实现硬件延时,理论上可以实现任意宽度的地址总线地址和读写信号。

CKCON寄存器的默认值为:0x71

通过设置CKCON的第4-6位,可以改变CPU的运行效率,最小值是001,不可设置为000;当设置为111,运行的效率最慢;所以推荐客户在CPU开始运行就改变4-6位的值为001,以使CPU运行的效率最快。


通过设置CKCON的第0-2位,可以改变EMIF总线的memrd,memwr,memaddr的宽度,最小值是000,对应memrd,memwr,memaddr的宽度为1个时钟周期;当设置为111时,对应memrd,memwr,memaddr的宽度为8个时钟周期;所以推荐客户在CPU开始运行就改变4-6位的值为000,以使EMIF总线访问的效率最快。

所以推荐用户在8051主程序程序一开始就改变CKCON的值为0x10。

2、基于Data Banking的总线地址扩展规则:
CME的8051处理器为冯诺依曼结构,即程序总线和数据总线统一编址。EMIF地址总线的地址位为23位,对应8M Bytes的地址空间。8051是通过Data Banking的方式实现地址总线的扩展。8051每个bank的地址空间为32K Bytes,共有256个bank。地址空间的分布如下图所示,这里仅对外部数据存储空间做介绍:


与外部数据存储空间有关的寄存器为:
D_PAGESEL(默认初始值为0x01,即指向Bank 1地址空间)

因为D_PAGESEL为8位寄存器,所以刚好对应256个bank。D_PAGESEL的值对应地址总线上的memaddr[22:15]的值,即地址总线的高8位地址总线。注意:D_PAGESEL的值不可为0,因为当为0时,将会与Common Bank的地址空间重叠(0-7FFFF)。

3、逻辑地址空间与物理地址空间的对应关系
逻辑地址空间(Logical Address): CME 8051每个bank的低16位逻辑地址的空间范围为0x8000-0xFFFF,该值和C编译器里面的地址定义相同。

物理地址(Physical Address):也叫实际地址或绝对地址,是出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果。

逻辑地址空间:

memaddr[22:0]

memaddr[22:15]:该物理地址段的值由D_PAGESEL寄存器的值决定,范围为1-255,默认初始化值为0x01;
memaddr[14:0]:该物理地址段由C编译器里面的变量分配的地址决定,注意:需拿C编译器里面定义的地址(0x8000-0xFFFF)减去偏移地址0x8000,即0x8000对应的物理地址实际是0x0000,0xFFFF对应的物理地址为0x7FFF。

Keil C51编译器支持的外部变量定义方法:

代码片段1:
unsigned char xdata PORTA  _at_  0x9000;//对应低16位物理地址:0x1000
unsigned char xdata DDRA   _at_  0x9001;//对应低16位物理地址:0x1001
unsigned char xdata PORTB  _at_  0xa000;//对应低16位物理地址:0x2000
unsigned char xdata DDRB   _at_  0xa001;//对应低16位物理地址:0x2001

或者如下定义:

代码片段2:
#define   PORTA   XBYTE[0x9000]
二、EMIF总线时序
1、EMIF总线同步写时序:
CKCON[2:0] = 000,图中mempsrd, mempswr为MCU内部信号,用户不用考虑,memack恒为1:


3、EMIF总线同步读时序:
CKCON[2:0] = 000,图中mempsrd, mempswr为MCU内部信号,用户不用考虑,memack恒为1:
三、EMIF编程示例
1、FPGA主要代码片段,EMIF总线同步读写:
//8051
MyMcu u_MyMcu
(
       .clkcpu (clk_sys),      //8051
       .resetn (rst_ncfg_n),      
       .swd   (1'b0),
       .port0i (),
       .port1i (),
       .port2i          (),
       .port3i          (),
       .port0o         (),
       .port1o         (),
       .port2o         (),
       .port3o         (port3o),
       .memaddr    (memaddr),
       .memdatao   (memdatao),
       .memdatai   (memdatai),
       .memack     (1’b1),
       .memwr      (memwr),
       .memrd      (memrd)
);

always @(posedge clk_sys or negedge rst_ncfg_n)
begin
       if(~rst_ncfg_n)
              test_cs _d1 <= 1'b0;
       else
              test_cs _d1 <= gpio_cs;
end
assign   memdatai = test_cs_d1 ? sta_rdata : 8'h00;
assign    test_cs =( memaddr [22:15] == 8'h04 && memaddr [14:12] == 3'h01) ? 1'b1 : 1'b0;
always @(posedge clk_sys or negedge rst_ncfg_n)
begin
       if(~rst_ncfg_n)
       begin
              test_reg0 <=8’h00;
              test_reg1 <= 8'h00;
       test_reg2 <= 8'h00;
       end
       else
       begin
              if(test_cs)begin
                     case(memaddr[7:0])
                     8'h00:begin
              if(memwr)
                              test0_reg <= memdatao;
                            if(memrd)
                              sta_rdata <= test0_reg;
                     end
                     8'h01:begin
                            if(memwr)
                              test1_reg <= memdatao;
                            if(memrd)
                              sta_rdata <= test1_reg;
                     end
8'h02:begin
                            if(memwr)
                              test2_reg <= memdatao;
                            if(memrd)
                              sta_rdata <= test2_reg;
                     end

                     default: ;
                     endcase
              end
       end
end

2、Keil C51主要程序片段:
UINT8 xdata test[2]   _at_  0x9000;

void main(void)
{     
       Unsigned char tmp;
       CKCON = 0x10;   
           D_PAGESEL = 0x4;//设置bank寄存器,memaddr[22:15]=0x04
           test[0] = 0x00;//对test0_reg写操作,test[0]物理地址:0x021000
           test[1] = 0x01;//对test1_reg写操作,test[1]物理地址:0x021001
           test[2] = 0x02;//对test2_reg写操作,test[2]物理地址:0x021002
           D_PAGESEL = 0x1;//更改回默认值,已实现对外部RAM的操作!
       while(1)
       {   
                D_PAGESEL = 0x4;
                tmp = test[1];//对test1_reg读操作
                if(tmp == 0x01){
                            D_PAGESEL = 0x1;
                            P0 =0x0f;
                            delay(1000);
                }
       }           
}




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0