RISC-V MCU中文社区

【分享】 小白也能学会的DDR存储拓展教程【2021 hbirdv2最新版】

发表于 全国大学生集成电路创新创业大赛 2021-07-19 21:13:44
1
4019
9

大家好,我们是 第五届集创赛 CICC1061 好家伙团队。在这篇帖子中,我将基于GitHub上一个完全开源的E203_hbirdv1的DDR拓展工程为例,来完成从E203_hbirdv1到我们第五届集创赛E203_hbirdv2平台的移植。


一、下载大佬的开源项目


项目链接如下:https://github.com/xiaoerlang0359/E203plus


该项目遵循 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的方法


2.E203软核提高CPU时钟频率方法


3.E203工程源码时钟树解析


4.E203_NICE软件demo_nice源码解读












喜欢9
用户评论 (1)
  • fan

    2021-07-20 01:04:44 fan 1#

    如果对文章中的方法有不同意见,欢迎私聊探讨。(Q 1172 9706 35)

fan

fan 实名认证

懒的都不写签名

积分
问答
粉丝
关注
  • RV-STAR 开发板
  • RISC-V处理器设计系列课程
  • 培养RISC-V大学土壤 共建RISC-V教育生态
RV-STAR 开发板