EMIF转AXI-Lite接口

  最近想用DSP对FPGA里的IP进行配置,感觉没有什么特别好的办法。如果能像Zynq一样直接有能够配置外设的AXI-Lite接口就好了。EMIF是DSP的外部存储器访问接口,支持对存储器的同步或异步访问。在我现有的条件下,利用EMIF接口配置FPGA内部的寄存器是一个可行的方案。Gitee链接

整体方案

  EMIF接口相比于AXI-Lite少了握手的过程。不能仅通过简单的同步/异步访问完成寄存器的读写。整体方案如下图:
在这里插入图片描述

  • 写命令需要缓存地址和数据,因为不知道AW和W通道什么时候才会握手。
  • 读命令需要有两步才能完成,首先缓存地址,将地址发送到AR通道,等R通道返回数据之后,DSP再次读数据才能得到真正的结果。
  • 缓存读命令的地址可以采用与缓存写地址用的不同的FIFO,但我采用的方案是读写地址都用同一个FIFO缓存,并且读命令的第一步是向要读的地址写任意数据(这个数据被丢弃),用来缓存写地址。
  • 读写地址的区分额外用了一根地址线,因此DSP在FPGA上实际的访存空间只有逻辑地址的一半。

EMIF地址映射

  FT-M6678的EMIF每个片选有64MB的空间,而一般外设的控制寄存器可能只有几kB。我们不需要把整块EMIF地址空间都映射到AXI-Lite接口上,而且很可能我们需要将这64MB的空间分成几部分,分别对应到不同的IP的配置空间中。
  通过设置EMIF Base Address,来确定EMIF的高位地址线的值,从而以不同的高位地址线区分不同的AXI-Lite空间。
在这里插入图片描述
  上图是这个IP的配置界面,需要用户配置需要访问的AXI-Lite接口的基地址和对应的空间大小。

实验测试

  实例化一块4kB的Block RAM和一个AXI BRAM控制器,对BRAM进行读写测试。
在这里插入图片描述
  地址分配信息:
在这里插入图片描述
  DSP将EMIF接口配置为同步32bit访问模式,在连续的字地址上依次写入10个从0递增的32bit数据。然后再将刚刚写入的数据读出,可以看到结果正确。
在这里插入图片描述
  下图是在测试过程中,FPGA端抓到的波形,与设计一致。
在这里插入图片描述

  DSP端测试代码:

// main.c
#include "periConfig.h"

#define LOOP (10)

int main(void) {

    int i;
    Uint32 RdBack[LOOP];

    gpioConfig();
    emifConfig(8); // ratio = 16, eclk = 62.5MHz

    for(i = 0; i<LOOP; ++i){
        writeReg(i * 4, i);
    }

    for(i = 0; i<LOOP; ++i){
        RdBack[i] = readReg(i * 4);
    }

    return 0;
}
// periConfig.h
#ifndef _PERICONFIG_H_
#define _PERICONFIG_H_

#ifdef __cplusplus
extern "C"{
#endif

#include <stdint.h>
#include <csl_gpio.h>

#define EMIF2AXIL_BASE (0x7C000000)
#define AXIL_SPACE_SIZE (0x1000)

void gpioConfig();
void emifConfig(int nEclkRatio);

static inline Bool isRdFifoEmpty(){
    return CSL_gpioGetInputBit(CSL_GPIO_PIN4); 
}

static inline Bool isAddrFifoFull(){
    return CSL_gpioGetInputBit(CSL_GPIO_PIN5);
}

static inline Bool isBusy(){
    return CSL_gpioGetInputBit(CSL_GPIO_PIN6);
}

static inline void writeReg(Uint32 offset, Uint32 val){
    // wait when addr_fifo is full
    while(CSL_gpioGetInputBit(CSL_GPIO_PIN5));
    // write reg
    *((Uint32 *)(EMIF2AXIL_BASE + offset)) = val;
}

static inline Uint32 readReg(Uint32 offset){
    // wait when addr_fifo is full
    while(CSL_gpioGetInputBit(CSL_GPIO_PIN5));
    // write address to read
    *((Uint32 *)(EMIF2AXIL_BASE + offset + AXIL_SPACE_SIZE)) = 0;
    // wait for data ready
    while(CSL_gpioGetInputBit(CSL_GPIO_PIN4));
    // read data
    return *((Uint32 *)(EMIF2AXIL_BASE));
}

#ifdef __cplusplus
}
#endif

#endif
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小裘HUST

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值