大家好,我们是 第五届集创赛 CICC1061 好家伙团队。在这篇帖子中,我将基于GitHub上一个完全开源的E203_hbirdv1的DDR拓展工程为例,来完成从E203_hbirdv1到我们第五届集创赛E203_hbirdv2平台的移植。
该项目遵循 Apache License 2.0开源协议,允许商业和非商业使用,具体协议权限如下图:(使用大佬源码的同学自觉去GIT给ta点一颗星星)
二、工程解析
阅读该项目源码,我们很容易发现,xiaoerlang0359大佬的项目,并不是基于E203_hbirdV2版本的,而是hbirdv1版本。并不能直接拿到我们的工程中使用。另外,他们的开发板和我们的也有很大区别。我们的MCU200T或者DDR200T开发板都是赛灵思的XC7A200T系列,他们的开发板FPGA型号也和我们今年比赛用板有很大的不同。这些地方都需要我们仔仔细细地阅读源码去做平台的移植工作。
三、平台移植
关于DDR的拓展工程都在yrtl文件夹内,打开文件夹。阅读readme说明文档,我们能够知道,原作者采用了vivado MIG IP来控制开发板上的DDR3,由于芯来科技的E203平台系统片内总线是icb总线,所以我们需要做跨时钟域和跨总线协议的“桥梁”。所幸的是,大佬的开源工程已经为我们提供了一个解决方案:通过时钟的整数倍频率关系完成DDR native interface到系统icb总线的桥接转换器。这个模块就是项目中的icb_bridge.v模块。
我们将这个模块加入自己的工程(不要忘了注释原作者的版权信息,这是引用的其他人的代码!!!!),然后根据大佬的README说明,在顶层例化对应自己开发板上DDR芯片的MIG控制器,将DDR控制器的DDR通道引出到IO,并根据自己开发板的原理图,完成DDR到FPGA IO bank的引脚分配和约束。
芯来科技的DDR200T原理图链接如下:https://www.nucleisys.com/upload/files/fpga/doc/Nuclei_DDR200T.pdf
我以DDR200T开发板为例,展示我们使用的开发板的DDR引脚约束配置如下:
当MIG IP和DDR都连接完毕后,我们将MIG控制通道的wire都从system.v顶层逐层往下接,接到lsu单元和lsu_ctrl单元为止。每层都要仔细和GitHub的工程源码仔细比对,并修改到自己的项目中去。
关于MIG的配置可以参考自己的DDR芯片手册进行适配,也可以参考芯来科技论坛的其他大佬的无私分享!
仔细比对!!!仔细比对!!!仔细比对!!!
(**提示:defines.v文件也需要修改)
四、修改时钟的mmcm IP
由于MIG模块需要系统时钟和参考时钟,我们需要在原本的mmcm模块之前再加一层mmcm用于产生MIG模块使用的系统时钟。
阅读readme说明文档,我们很容易知道,我们需要一个166.667MHZ的inputclk,以及一个200MHZ的refclk,给MIG模块输入。这个按照一般的mmcm配置方法便可以自行完成。难度不是很大。
配置完成以后,我们的E203_hbirdv2项目中就应该至少有以下4个IP核:(mmcm名字也不一定和我的一样)
五、使用vivado嵌入式逻辑分析仪ILA检查DDR是否初始化成功
创建ILA,将原始输入时钟CLK100MHZ作为逻辑分析仪的ILA采样时钟,将DDR接口的“init_calib_complete”线放进ila的探针probe中。
综合,实现完成以后,上板。将bitstream文件和debug文件都烧写进开发板。然后在弹出的ila面板中调整探针“init_calib_complete”的触发方式为 " R: from 0 to 1" ,按下开发板上的MCU_RST按键,观察init_calib_complete有没有成功被拉到高电平。
如果DDR连接正常,并且上电初始化成功,这根wire应该在初始化后,被拉至高电平。
如下图所示:我们的DDR成功被上电复位初始化:
***注:关于vivado自带的嵌入式逻辑分析仪ila的使用可以直接百度,网上一堆图文教程,本人在此不再赘述。
六、通过nuclei studio软件读写测试
我们使用了芯来科技的nuclei studio IDE进行了软件读写测试。测试函数编写如下:
MAIN主函数如下:
内存读写子函数定义如下:
void read_mem( int *startp, int range) //input *start-addr and data-number to read
{
int *p = startp;
printf("********************LIST BEGIN*********************");
for(int i=0; i < range-1 ; i++ )
{
printf("\n%d",*p);
p=p+1;
}
printf("*********************LIST END***********************");
}
void read_wrtest( int *startp, int range) //input *start-addr and data-number to read
{
int *p = startp;
printf("\n********************write BEGIN*********************\n");
for(int i=0; i < range-1 ; i++ )
{
*p = i;
p=p+1;
printf(".");
}
printf("\n*********************write END***********************\n\n");
}
在main函数中调用这两个函数,测试DDR地址空间的读写。测试结果如下:
至此,我们成功完成了DDR拓展工程的平台移植!!!!!!!
跪谢前人、大佬们的无私的开源精神!!(手动@xiaoerlang大佬)再次感谢大佬!!!没有他们的开源项目,本人也不可能能在如此短的时间里,掌握DDR的用法。
由于笔者本人也是FPGA的小白,也是这最近一星期才调通了DDR模块和ILA嵌入式逻辑分析仪,本人也有很多东西没有完全学懂,欢迎大佬对本人拙作的任何批评和指正!!
****PS:对本文的任何错误还请大佬不吝赐教,直接在下方评论区中指出,以免以讹传讹造成不好的影响!!!
************************************************END*****************************************************
下面是我们集创赛CICC1061好家伙队的其他几篇技术分享,有兴趣的小伙伴可以参考:
1.Windows系统下用vivado将电路烧写到MCU200T板载FLASH的方法