【fpga】ddr3

转载

1、前言

        DDR3 SDRAM 简称 DDR3,是当今较为常见的一种储存器,在计算机及嵌入式产品中得到广泛应用, 特别是应用在涉及到大量数据交互的场合,比如电脑的内存条。DDR3的时序相当复杂,对DDR3 的读写操作大都借助 IP 核来完成。

2、MIG DDR3 IP核的介绍

        MIG(Memory Interface Generators) IP 核是 Xilinx 公司针对 DDR 存储器开发的 IP,里面集成存储器控制模块,实现 DDR 读写操作的 控制流程,下图是 7 系列的 MIG IP 核结构框图。MIG IP 核对外分出了两组接口。左侧是用户接口,就是 用户(FPGA)同 MIG 交互的接口,用户只有充分掌握了这些接口才能操作 MIG。右侧为 DDR 物理芯片 接口,负责产生具体的操作时序,并直接操作芯片管脚。这一侧用户只负责分配正确的管脚,其他不用关心。

        在有了这个IP核后,我们就无需对复杂的DDR3进行操作,只需要根据用户侧的时序逻辑来进行操作即可。

        下面是用户侧的信号接口及说明:

将其中比较常用的与不常用的分开,如下图:

其中的输入/输出是相对于MIG IP核来说的,例如ui_clk就是output给用户侧的用户时钟。

        DDR3 的读或者写都包含写命令操作,其中写操作命令(app_cmd)的值等于 0,读操作 app_cmd 的值 等于 1。首先来看写命令时序,如下图所示。首先检查 app_rdy,为高则表明此时 IP 核命令接收处于准备好 状态,可以接收用户命令,在当前时钟拉高 app_en,同时发送命令(app_cmd)和地址(app_addr),此时命令和地址被写入。

写数据的时序,如下图所示:

写数据的情况有3种:

  1. 写命令与写数据发生在同一时钟周期
  2. 写数据先于写命令发生(不一定是图上的一个时钟周期,因为数据是先写到了FIFO)发生在同一时钟周期
  3. 写数据落后于写命令发生,但不能超过两个时钟周期

结合上图,写时序总结如下:首先需要检查 app_wdf_rdy,该信号为高表明此时 IP 核数据接收处于准备完成状态,可以接收用户发过来的数据,在当前时钟拉高写使能(app_wdf_wren),给出写数据 (app_wdf_data)。这样加上发起的写命令操作就可以成功向 IP 核写数据。

接着来看读数据,如下图所示:

读时序比较简单,发出读命令后,用户只需等待数据有效信号(app_rd_data_valid)拉高,为高表明此 时数据总线上的数据是有效的返回数据。需要注意的是,在发出读命令后,有效读数据要晚若干周期才出现在数据总线上 (延迟的时间不定)。

3、MIG DDR3 IP核的配置

打开 IP Catalog 在搜索栏输入 mig(Memory Interface Generator),双击直接打开

下图是确认工程信息,主要是芯片信息与编译环境以及目标语言,点击 next

 如下图所示,这一页选择“Create Design”,在“Component Name”一栏设置该 IP 元件的名称,再往下选择控制器数量,默认为“1”即可。AXI4 接口不勾选。配置完成点击“Next”。

 如下图所示,这一页主要是让用户选择可以兼容的芯片,本工程默认不勾选,即不需要兼容其他的 FPGA 芯片。配置完成点击“Next”。

如下图所示,这一页选择第一个选项“DDR3 SDRAM”

 

如下图所示:

        Clock Period:DDR3 芯片运行时钟周期,这里选400M,实际传输频率800M(上下沿双触发)

        PHY to Controller Clock Ratio:一般有 4:1 和 2:1 两个选项,当DDR3 芯片运行频率高于350M时,默认选为4:1

        VCCAUX_IO:这是 FPGA 高性能 bank(High Performance bank)的供电电压。它的 设置取决于 MIG 控制器运行的周期/频率。当用户让控制器工作在最快频率的时候,系统 会默认为 1.8V

Memory Type: DDR3 储存器类型选择。选择 Component。

Memory Part: DDR3 芯片的具体型号,我这里选择选择 MT41J128M16XX-125

Memory Voltage:是 DDR3 芯片的电压选择,选 1.5v。

Data Width:数据位宽选择,这里选择 16。

ECC:ECC 校验使能,数据位宽为 72 位的时候才能使用

Data Mask:数据屏蔽管脚使能。勾选它才会产生屏蔽信号,这里勾上

Number of Bank Machines:Bank Machine 的数量是用来对具体的每个或某几个来单独控制的,选择多了控制效率就会高,相应的占用的资源也多,选择 4 个

ORDERING:该信号用来决定 MIG 控制器是否可以对它收到的指令进行重新排序,选择 Normal 则允 许,Strict 则禁止。本实验选择 Normal,从而获得更高效率。

 如下图所示:

        Input Clock Period:MIG IP 核的系统输入时钟周期,该输入时钟是由 FPGA 内部产生的,MIG内部有一个MMCM资源,用来生成用户时钟及DDR3时钟。这个时钟就是输入个MMCM用的

        Read Burst Type and Length:突发类型选择,突发类型有顺序突发和交叉突发两种,选择顺序 突发(Sequential),其突发长度固定为 8。

        Output Driver Impdance Control:输出阻抗控制。选择 RZQ/7。

        RTT:终结电阻,可进行动态控制。选择 RZQ/4。

        Controller Chip Select Pin:片选管脚引出使能。选择 enable,表示把片选信号 cs#引出来,由外部控制

        BANK_ROW_COLUMN:寻址方式选择。选择第二种,即 BANK-ROW-COLUMN的形式

 如下图所示:

        System Clock:MIG IP 核输入时钟。选择“No Buffer”,因为 IP 核的输入系统 时钟是单端时钟,是由内部的 MMCM 产生的,MMCM 所产生的时钟默认添加了 buffer。

        Reference Clock:MIG IP 核参考时钟。同样选择“No Buffer”,将由时钟模块生成。

        System Reset Polarity:复位有效电平选择。选择“ACTIVE LOW”低电平有效。

        Debug Signals Control:该选项用于控制 MIG IP 核是否把一些调试信号引出来,它会自动添加到 ILA,这些信号包括一些 DDR3 芯片的校准状态信息。选择 “OFF”,不需要让 IP 核生产各种调试信号

        Sample Data Depth:采样深度选择。当“Debug Signals Control”选择“OFF”时,所 有采样深度是不可选的

        Internal Vref:内部参考管脚,表示将某些参考管脚当成普通的输入管脚来用。不勾选

        IO Power Reduction:IO 管脚节省功耗设置。选择“ON”

        XADC Instantiation:XADC补偿使能

 继续点击“NEXT”按钮,界面如下图所示,选择默认阻抗。

  

选择第二个,直接读取DDR3的引脚,这样就不用进行配置了。

选择“Read XDC/UCF”,直接导入管脚分配文件

如下图所示,这里软件默认设置,直接点击“Next”

接下来的都是一些信息确认选项,直接点击“Next”,直到最后点击“Generate”生成IP核

4、官方仿真示例

Vivado关于MIG IP核有自带的仿真示例,右击生成的IP核,选择open IP example design,选择好路径后就会生成一个新的工程mig_7series_0_ex

打开工程mig_7series_0_ex,直接执行仿真(这里可能等几分钟)

仿真结果出来后,只保留一些比较有用的信号,并进行分组,如下:

找init_calib_complete拉高后(DDR3初始化完成)的一些局部时序图,如下图:

        蓝线、和黄线处,app_cmd为0,app_en、app_rdy均为高,代表在执行写命令操作;同时app_wdf_data同地址一致,app_wdf_en、app_wdf_rdy均为高,代表在进行写数据操作

 如下图:

        很多个周期的app_rdy拉低,代表MIG没有准备好进行写数据命令,但此时app_wdf_data同地址一致,app_wdf_en、app_wdf_rdy均为高,代表在进行写数据操作。这正是前面章节提到了写数据提前与写命令,因为MIG种有一个FIFO,将要写入的数据存入FIFO,等到写命令有效时,再对FIFO进行读取。这样做的好处是可以很大程度上做到写命令和写数据分离。

  如下图:

         蓝线处,app_cmd为1,app_en、app_rdy均为高,地址app_addr为0x0000200,代表在执行读命令操作。经过若干个周期后,黄线处读取数据有效标志信号app_rd_data_valid拉高,代表成功读取到了一个数据,数据为0x0000200000020000002000000200,与前面写入的一致

### FPGA DDR3控制器设计与实现 #### 设计概述 FPGA中的DDR3控制器设计是一个复杂的工程,涉及多个方面,包括初始化、读写操作及时序控制等。为了提高数据传输效率并满足DDR3严格的时序要求,在实际应用中通常会引入FIFO接口来缓冲数据流[^1]。 #### 初始化过程 在启动阶段,DDR3内存需要经过一系列精确的初始化步骤才能进入正常工作状态。这些步骤由FPGA内部逻辑完成,主要包括模式寄存器设置(MRS),预充电(Precharge All),刷新命令(Refresh Commands)以及退出自刷新(CSR, Exit Self Refresh Mode)。每一步都需要严格遵循JEDEC标准规定的顺序与时延参数。 #### 数据通路架构 对于高效的数据处理而言,合理的设计数据路径至关重要。当涉及到高速存储设备如DDR3时,往往采用双端口RAM结构或者集成外部缓存机制——即所谓的先进先出(FIFO)队列技术。这种做法能够有效缓解由于访问冲突而导致性能下降的问题,并允许异步读/写请求独立运行而不互相干扰。 #### 物理层考虑事项 针对具体硬件平台(Xilinx 7系列为例),除了软件层面之外还需要关注物理连接部分。例如PCB布局布线规则就显得尤为重要;另外关于电源分配网络(PDN)也需要特别小心规划以免造成信号完整性问题(SI issues) 或者电磁兼容性挑战 (EMC concerns)[^2]. 同样值得注意的是某些特定功能单元比如差分输入输出(DCI)可能会影响整体表现因此建议查阅官方文档获取更多细节说明[^2]. ```verilog module ddr3_controller ( input wire clk, input wire reset_n, // User Interface Signals output reg [31:0] data_out, input wire [31:0] data_in, output reg ready_flag, // Physical Layer Connections to DDR3 Memory Device inout wire [15:0] ddr3_dq, ... ); always @(posedge clk or negedge reset_n) begin : init_seq if (!reset_n) begin // Reset logic here... end else case(state) INIT_START: ; MRST_SET: ; PRECHARGE_ALL: ; REFRESH_CMD: ; EXIT_SELF_REFRESH: ; default: state <= INIT_START; endcase end // Example of a simple FIFO implementation within the controller. reg fifo_full,fifo_empty; wire push,pop; assign pop = !fifo_empty && user_request_read; assign push = !fifo_full && new_data_available; always @* begin if(push & ~pop) fifo_count +=1&#39;b1; else if(~push & pop) fifo_count -=1&#39;b1; else; /* No change */ fifo_full = (fifo_count >= MAX_FIFO_DEPTH); fifo_empty= (fifo_count == &#39;b0 ); end endmodule ``` 上述代码片段展示了如何构建基本框架下的DDR3控制器模块定义及其核心状态机用于执行必要的初始化序列。同时还包含了简单的FIFO管理电路作为示范用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值