DDR控制器MIG核的使用

本文介绍了在FPGA设计中使用DDR控制器IP核MIG的必要性和基本原理,特别是针对Xilinx的UltraScale+系列。内容涵盖了DDR内存的工作模式、内部结构,以及MIG如何简化DDR初始化和读写操作。通过示例详细阐述了MIG的用户侧接口、时序设计,以及读写命令的创建,帮助初学者快速掌握MIG的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FPGA的片上存储资源bram简单好用,时序清晰,要不是总容量往往就几十Mb谁愿意用DDR呀······
害,言归正传,因为设计需要存储1477x1800x3 双精度浮点复数这样的大号矩阵,所以只能放到DDR上去进行读写。之前在网上找了好多资料,但发现都没有一个很完整的教程教你怎么使用DDR控制器IP核MIG(Memory Interface Generator),所以写了这篇文章主要希望能帮初学者快速上手MIG的使用以实现DDR读写。
介绍MIG之前,我觉得有必要先对DDR做一个介绍,DDR SDRAM(Double Data Rate Synchronous Dynamic Random Access Memory,实际上还分为DDR SDRAM,DDR2 SDRAM,DDR3 SDRAM,DDR4 SDRAM,主要是数据预取prefetch和工作频率的不同,感兴趣的大家可以自己查),搭眼一看,这玩意本质上不就是数字集成电路里学的DRAM嘛(电容存储,会漏电,时不时需要刷新blablabla······),而double data rate说的是他在clock的上升沿和下降沿都会进行数据读写,设想如果用户逻辑侧的时钟频率和DDR的工作频率之比为1:4的话,用户侧的一个clk, 那么DDR实际上进行了4*2(上下沿)=8次读写操作。
在这里插入图片描述
DDR3的内部是如上图的存储阵列组成,数据存储在单元格中,在检索你想要的数据时,先指定一个行(Row),再指定一个列(Column),我们就可以准确地找到所需要的单元格,这就是内存芯片寻址的基本原理。对于内存,这个单元格可称为存储单元,常见存储单元位宽有4bit,8bit,16bit,那么这个表格(存储阵列)就是逻辑 Bank(Logical Bank),而一颗DDR芯片上有若干个bank,一般内存芯片厂家在芯片上是标明容量的,我们可以看芯片上的标识知道,这个芯片有几个逻辑BANK,每个逻辑bank的位宽是多少,每个逻辑BANK内有多少单元格(CELL),eg.比如64MB和128MB内存条常用的**64Mbit的芯片(注意不是Mb,1byte=8bit,所以除以8才是Mb)**就有如下三种结构形式:
①16 M x 4 (4 M x 4 x 4 banks) [16M X 4]
②8 M x 8 (2 M x 8 x 4 banks) [8M X 8]
③4 M x 16 (1 M x 16 x 4 banks) [4M X 16]
即一颗DDR芯片的单元格数(逻辑bank数 X 每个逻辑bank的单元格数)X 每个单元格的位宽(bit)。
16bit位宽的芯片意味着你给内存一个地址,内存会给你一个16bit的数据到数据线上,但实际中我们的数据往往不止16bit,例如双精度浮点数(64bit),那么就需要用4块DDR芯片拼接成一个64位宽的DDR,只是这4块DDR共用一个地址线,每个取出的16bit数据再拼成一个64bit的数据,那么就相当于每个地址可以存一个64位宽的数据,而这样一个64位宽的数据集合就是一个物理bank,也经常叫Rank。大家可以参考这篇文章说的很详细:

64bit数据存储形式
接下来说说MIG核是干什么的,放一张DDR工作的状态图:
在这里插入图片描述
DDR上电后需要控制其初始化,ZQ校准,激活bank,而后读写等一系列过程,这其中还要配置模式寄存器,控制DDR refresh、precharge,考虑怎么样将8/16bit位宽的DDR芯片拼接成更大位宽等等问题。这对于用户侧是十分不友好的。所以就需要DDR控制器提供一个用户友好的接口,而MIG核做的就是这件事情
在这里插入图片描述
左边是用户侧读写逻辑,经由MIG核生成DDR需要的信号控制读写。所以,我们只需要把关注点放在MIG核的用户侧接口信号,从官方文档里可以找到接口说明。
在这里插入图片描述
在这里插入图片描述
需要重点关注的信号用红框标注出来了,根据英文也能猜出大概是干嘛的,接下来就可以生成IP核了,这里不得不说一下大家FPGA最好选用Xilinx的亲儿子,之前用的一款adm-pcie 7v3,参考资料少,问题多,而且DDR的管脚还要自己去配,属实折腾人······这次用的是ultrascale+系列的亲儿子kcu116,简直不要太舒服哈哈。在这里插入图片描述
在这里插入图片描述
这里说一下系统时钟,因为我的板子时钟源有一个300MHz的差分时钟,所以就刚好用它作为MIG的输入时钟,实际上MIG会利用分频倍频将这个差分时钟变成我们想要的DDR工作频率,第二张图里的memory interface speed指的就是DDR的工作频率,而frequency ratio指的就是DDR工作频率:用户逻辑频率,再加上上下沿传输,意味着用户侧一个clk可以给DDR读写8个数据。reference input就是刚才所说的外接时钟源。底下的data_width指的是我们要存的数据位宽,例如双精度浮点数64,这时候我们可以发现无论是app_rd_data还是app_wdf_data都变成了512位,,刚好和64是8:1的关系,也就是我们所说的用户侧一个clk可以读写8个数据,所以我们在写自己的读写逻辑时,如果是连续地址读写,那么每次的地址数据应该+8。CAS latency指的是DDR在读取时,列地址选中后数据传输放大到I/O口这个过程本身就有的一个延时,相当于我们给了读地址后到得到读数据的延时,这涉及到DDR的工作原理这里不作深究我们可以随便设个值。
在这里插入图片描述
在这里插入图片描述
这里说一下memory address map,大家注意到有row-bank-colum,row-colum-bank,bank-row-column几种数据地址映射机制,就是我们在进行存储时,是按照先填写column,第一行的column写满后跳到下一个bank的第一行去存储,8个bank的第一行都填满后,再跳转到下一行存储,其它几种同理。进一步深究MIG核的代码发现一个有趣的事情,例如row-column-bank的地址映射机制,在这里插入图片描述 这里的addr并不是单纯的row-column-bank的排列顺序,不由得想到一个问题,我们在设计自己的逻辑时,一个app_rd_data或者一个app_wdf_data要占用8个地址所以每次地址都是+8,即+4’b1000,相当于刚好给bank+1从而实现了bank 的跳转,因此Xilinx官方已经帮我们考虑了这些问题我们可以只管给addr+4’b1000其他的不用操心。
处理完这些就可以点击完成生成IP核。等IP核综合完成,这个时候推荐大家直接右键生成example design,因为你只是生成例化了控制器,但还没有和DDR芯片连接,生成example design便可以直接开始设计自己的读写逻辑。打开example design之后可以看到代码结构,只需要在u_example_tb.v里修改即可。在这里插入图片描述

接下来就是读写时序的设计了。

写命令与写地址
在这里插入图片描述
如上图所示①,②,③情况,只有在③时刻app_en和app_rdy同时为高电平app_cmd(命令)和(app_addr)地址才有效,所以当需要app_cmd,app_addr有效时app_en必须保持到app_rdy为高电平才有效。
写时序
在这里插入图片描述
如上图所示①,②,③种情况,写命令和写数据直接存在三种逻辑关系。
1、①表示写命令(app_cmd),写当前地址(app_addr)和写数据(app_wdf_data)以及写控制信号(app_en,app_rdy,app_wdf_rdy,app_wdf_wr

### 关于DDR4 MIG IP信号的问题及解决方案 #### 1. AXI接口信号问题 当遇到AXI接口信号不稳定或无法正常通信的情况时,通常是因为时钟域不匹配或是复位序列未正确执行。确保所有涉及的时钟都已稳定运行,并且所有的复位脉冲都已经完成。如果仍然存在问题,则需检查AXI总线宽度设置是否一致以及地址映射是否有误[^1]。 #### 2. app_wdf_rdy信号持续低电平 `app_wdf_rdy`信号表示写入缓冲区准备好接收新数据的状态。该信号长时间保持低电平可能意味着写入路径存在阻塞或者是由于某些错误条件触发了保护机制。建议按照以下方式排查: - 验证输入的数据流速率不超过系统的最大吞吐量; - 检查是否存在ECC (Error Correction Code) 错误或其他硬件异常报告; - 审视设计中的握手协议逻辑部分,确认没有死锁现象发生; 对于具体的故障定位与修复措施,在Xilinx官方文档中有详细的指导说明可供参考[^2]。 #### 3. 物理层接口同步失败 在初始化阶段未能成功建立与外部DDR4内存颗粒之间的联系可能是由多种因素引起的,比如电源噪声干扰、PCB布局不合理等。为了提高成功率并减少潜在的风险点,应该仔细审查电路板的设计文件,特别是关注供电网络的质量和信号走线长度的一致性。此外,还可以尝试调整一些参数如ODT(On-Die Termination),以优化电气特性表现[^4]。 ```verilog // Verilog代码片段用于配置ODT电阻值 assign ddr4_odt = `DDR4_ODT_RZQ_6; // 设置为RZQ/6模式 ```
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值