MIG IP控制DDR3读写测试
本文设计思想采用明德扬至简设计法。在高速信号处理场合下,很短时间内就要缓存大量的数据,这时片内存储资源已经远远不够了。DDR SDRAM因其极高的性价比几乎是每一款中高档FPGA开发板的首选外部存储芯片。DDR操作时序非常复杂,之所以在FPGA开发中用途如此广泛,都要得意于MIG IP核。网上关于MIG控制DDR的资料很多,因此本文只讲述个人认为较重要的内容。由于MIG IP核用户接口时序较复杂,这里给出扩展接口模块用于进一步简化接口时序。
先来看看MIG IP核的架构:
了解下存储芯片侧重要接口:
ddr_addr DDR3的行列地址
ddr_ba DDR3的bank地址
ddr_cas_n ddr_ras_n ddr_we_n 命令控制
ddr_ck ddr_ck_n 差分时钟
ddr_dm 数据输入屏蔽
ddr_o_dt 片上终端使能,用于使能和禁止片内终端电阻
ddr_reset_n DDR3复位
ddr_dqs ddr_dqs_n 数据同步信号
ddr_dq 传输数据
之后我们从IP核配置开始说起。Controller Options这页最为重要,其中包括时钟策略和外部DDR芯片参数配置。首先时钟周期选择为400MHz,此时PHY to Controller Clock Ratio只能是4:1,也就是说MIG用户侧时钟为100MHz。下半部分是选择合适的DDR芯片型号和参数,要再三确认无误。
Memory Options这页输入时钟周期选择为200MHz,根据Controller Options页的选项,该时钟经过PLL分频和倍频后的时钟分别作为用户侧时钟100MHz和DDR接口时钟400MHz。
这里有个参考时钟选项,如果Memory Options页PLL输入时钟频率选为200MHz,此处可以直接选择Use System Clock,从而简化接口。
以上是MIG IP核配置过程中较为重要的部分,实际上上述配置也可通过修改工程代码中参数来重定义。IP核配置完成,打开example design工程顶层文件,我们来重点关注下用户侧接口功能和时序。
这是本人写的注释,更具体清晰的说明还是要查看官方文档UG586.接下来看看写数据和读数据的接口时序图(时钟比例4:1,burst length = 8为例):
指令通道:
写数据:
从时序图可以看出,指令地址和数据使用两套时序,彼此相互独立。为了便于设计,直接将两套时序严格对齐(情况1)也可以正常工作。
读数据:
为什么说“时钟比例4:1,burst length = 8为例”?这一点特别关键。此时用户时钟周期是DDR接口时钟周期的4倍,也就是一个用户时钟信号上升沿对应8个DDR时钟边沿。burst length可以理解为MIG连续操作DDR地址的个数,故在4:1时钟比例下,一个用户时钟周期正好对8个地址进行了读/写操作,256bit数据分8次(32bit)写入DDR中。由此分析,在写数据时让app_wdf_end = app_wdf_wren即可,并且读/写操作时地址递增步长为8.
虽然MIG IP核提供了用户接口,但读写指令通道复用且需要实时关注两个rdy信号造成了时序操作上的不方便。为此我们需要对接口进一步封装,保证写操作时只关注:写使能user_wdata_en 写地址user_waddr 写数据user_wdata和写准备就绪信号user_wdata_rdy,读操作时只关注:读使能user_rdata_en 读地址user_raddr 读数据user_rdata 读数据有效user_rdata_vld和读操作准备就绪user_rdata_rdy。
利用扩展接口模块,将读通道和写通道接口分离,并分别例化一个FIFO缓存地址和数据。当读/写指令同时有效时,通过MIG侧的优先级轮换逻辑轮流读取其中一个FIFO,每次选一个FIFO读取直至FIFO为空再重新选择。其工程结构和核心代码如下:
读侧逻辑核心代码:
//读侧-------------------------------------------------------------- always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
rd_flag <= () ;
end
else if(rd_flag == && mig_rdy && mig_wdf_rdy && !rdempty1 && (rdempty0 || (!rdempty0 && priority == )))begin
rd_flag <= ('b01) ;//读取 写指令FIFO
end
else if(rd_flag == && mig_rdy && !rdempty0 && (rdempty1 || (!rdempty1 && priority == )))begin
rd_flag <= ('b10) ;//读取 读指令FIFO
end
else if((rd_flag == 'b01 && rdempty1)||(rd_flag == 2'b10 && rdempty0))
rd_flag <= ;
end //同时非空时轮换优先级
always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
priority <= () ;
end
else if(rd_flag == && !rdempty0 && !rdempty1)begin
priority <= (!priority) ;
end
end
为了方便测试,设计样式生成模块与扩展接口模块用户侧连接,不断向一段地址写入固定数据序列并在一段时间后读回。
`timescale 1ns / 1ps
/*
该模块功能:
周期性向一段地址执行读写操作 产生固定样式待写入数据用户测试目的
测试完毕后删除该模块,开发用户接口 具体为:
1 写从0开始之后的10个用户地址(80个DDR地址):0~9递增序列
2 等待20个时钟周期
3 读取写入的10个用户地址
4 等待20个时钟周期
5 重复上述步骤 说明:
1 每个步骤之间有一个时钟周期空闲
2 由于burst_len = 8 4:1时钟模式下一个用户时钟周期写入数据对应同样时间内8个DDR时钟边沿写入数据,
因此地址递增步长为8
*/
module traffic_gen
#(parameter DATA_WIDTH = ,
ADDR_WIDTH = )
(
input clk ,
input rst_n , output reg gen_wdata_en ,
output reg [ ADDR_WIDTH-:] gen_waddr ,
output reg [ DATA_WIDTH-:] gen_wdata ,
input gen_wdata_rdy ,//写指令和数据通道准备就绪 output reg gen_rdata_en ,
output reg [ ADDR_WIDTH-:] gen_raddr ,
input [ DATA_WIDTH-:] gen_rdata ,
input gen_rdata_vld ,
input gen_rdata_rdy //读指令通道准备就绪
); reg [ (-):] cnt0 ;
wire add_cnt0 ;
wire end_cnt0 ;
reg [ (-):] cnt1 ;
wire add_cnt1 ;
wire end_cnt1 ; reg [ DATA_WIDTH-:] gen_rdata_r ;
reg gen_rdata_vld_r ;
reg com_flag ; wire wri_state;
wire rd_state;
wire com_change_t; //操作周期计数器,计数值为欲操作用户地址段长度+1(需要一个时钟周期空闲)
always @(posedge clk or negedge rst_n) begin
if (rst_n==) begin
cnt0 <= ;
end
else if(add_cnt0) begin
if(end_cnt0)
cnt0 <= ;
else
cnt0 <= cnt0+ ;
end
end
assign add_cnt0 = (com_flag == && gen_wdata_rdy) || (com_flag == && gen_rdata_rdy);
assign end_cnt0 = add_cnt0 && cnt0 == ()- ; //指令标志位 先是0--写 再是1--读
always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
com_flag <= () ;
end
else if(com_change_t)begin
com_flag <= (!com_flag) ;
end
end assign com_change_t = add_cnt0 && cnt0 == - ; //写操作---------------------------------------------
always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
gen_wdata_en <= () ;
end
else if(wri_state)begin
gen_wdata_en <= ('b1) ;
end
else begin
gen_wdata_en <= () ;
end
end assign wri_state = add_cnt0 && cnt0 <= - && com_flag == ;
assign rd_state = add_cnt0 && cnt0 <= - && com_flag == ; always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
gen_wdata <= () ;
end
else begin
gen_wdata <= (cnt0) ;
end
end always@(posedge clk or negedge rst_n)begin
if(rst_n == )
gen_waddr <= ;
else if(wri_state)
gen_waddr <= gen_waddr + 'd8;
else
gen_waddr <= ;
end
//读操作---------------------------------------------- always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
gen_rdata_en <= () ;
end
else if(rd_state)begin
gen_rdata_en <= ('b1) ;
end
else begin
gen_rdata_en <= () ;
end
end always@(posedge clk or negedge rst_n)begin
if(rst_n == )
gen_raddr <= ;
else if(rd_state)
gen_raddr <= gen_raddr + 'd8;
else
gen_raddr <= ;
end always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
gen_rdata_r <= () ;
end
else begin
gen_rdata_r <= (gen_rdata) ;
end
end always @(posedge clk or negedge rst_n )begin
if(rst_n==) begin
gen_rdata_vld_r <= () ;
end
else if(gen_rdata_vld)begin
gen_rdata_vld_r <= ('b1) ;
end
else begin
gen_rdata_vld_r <= () ;
end
end endmodule
将traffic_gen和extend_interface模块例化在MIG的example design中,利用ILA抓取MIG IP核用户接口信号。
向地址8~80写入数据0~9,再从此段地址中读回数据,0~9被正确读出,MIG IP核控制DDR3读写测试完毕。
MIG IP控制DDR3读写测试的更多相关文章
- Xilinx 7系列例化MIG IP core DDR3读写
昨晚找了一下,发现DDR3读写在工程上多是通过例化MIG,调用生成IPcore的HDL Functional Model.我说嘛,自己哪能写出那么繁琐的,不过DDR读写数据可以用到状态机,后期再添砖加 ...
- 基于MIG IP核的DDR3控制器(二)
上一节中,记录到了ddr控制器的整体架构,在本节中,准备把ddr控制器的各个模块完善一下. 可以看到上一节中介绍了DDR控制器的整体架构,因为这几周事情多,又要课设什么的麻烦,今天抽点时间把这个记录完 ...
- 基于MIG IP核的DDR3控制器(一)
最近学习了DDR3控制器的使用,也用着DDR完成了一些简单工作,想着以后一段可能只用封装过后的IP核,可能会忘记DDR3控制器的一些内容,想着把这个DDR控制器的编写过程记录下来,便于我自己以后查看吧 ...
- FPGA上外挂DDR2&DDR3&MIG IP的使用记录
前言 当需要大容量数据存储及处理的时候,FPGA内部自带的存储资源是远远不够的,所以问题来了,怎么使用外带的DDR3? 首要问题在于DDR3是什么?有没有协议?当然只是需要用Xilinx MIG IP ...
- zedboard如何从PL端控制DDR读写(七)
前面已经详细介绍了从PL端如何用AXI总线去控制DDR的读写,并且从AXI_BRESP的返回值来看,我们也是成功写入了的.但是没有通过别的方式来验证写入的数据的话,总是感觉差了点什么. 今天试了一把从 ...
- 回看《例说FPGA》---DDR2控制器集成与读写测试
回看<例说FPGA> ---DDR2控制器集成与读写测试 1.DDR2 IP核的配置 需要弄清楚的选项主要有: PLL reference clock frequency Memory c ...
- 第36章 SDIO—SD卡读写测试
第36章 SDIO—SD卡读写测试 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/f ...
- 第36章 SDIO—SD卡读写测试—零死角玩转STM32-F429系列
第36章 SDIO—SD卡读写测试 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/f ...
- 通过IP控制登录系统
项目中有这么一个需求,就是系统仅仅能在指定ip下登录,能够理解为内部系统,仅仅能够在公司訪问 我的代码是这样写的:入不入流不知道,但能解决这个问题. 获得訪问IP代码: String ip = req ...
随机推荐
- 将项目打包成jar,如何又将jar还原成项目
一.将项目打包成jar 第一步: 选择项目,鼠标右键,选择export ,出现如下 接下来就是点击Next,Next,最后点击Finish 后 会生成jar 二.将jar还原成项目 第一步 用反编译工 ...
- labview生成可执行文件
labview生成可执行文件可以分为两种情况. 第一种,是电脑中有labview软件开发环境的情况 第二种,是电脑中没有安装labview软件开发环境 下面是一个简单的labview代码: 程序解释: ...
- db2服务器端授权
昨天吃饭回来有点晚,没有及时写,今天补上. db2服务器端安装就不说了,网上很多.今天具体说说授权吧.这是个麻烦事. 安装的时候会让你创建数据库.你就根据提 ...
- 利用vmware搭建分布式集群
背景: 我们需要至少3台服务器来实现分布式,鉴于没那么多钱买真机器,从学习和开发的角度看,只有虚拟机一条路了. 软件选择: 虚拟机使用VMware软件,因为主流而且资料比较多,学习成 ...
- 剑指Offer_12_矩阵中的路径(参考问题:马踏棋盘)
题目描述 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵 ...
- 使用NPOI读取Excel数据到DataTable
如今XML文件的存储格式大行其道,可是也不是适用于全部情况,非常多单位的数据交换还是使用Excel的形式.这就使得我们须要读取Excel内的数据.载入到程序中进行处理.可是如何有效率的读取,如何使程序 ...
- UVA - 10249 The Grand Dinner
Description Problem D The Grand Dinner Input: standard input Output: standard output Time Limit: 15 ...
- Python 安装 BeautifulSoup(Win7)
准备材料: 1.Win7,已安装的 Python3.4.1 2.BeautifulSoup4.3.2安装包 安装办法: 1.打开cmd 2,进入BeautifulSoup的解压文件夹 3,执行 pyt ...
- 数学之美?编程之美?数学 + 编程= unbelievable 美!
欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:Rusu 导语 相信大家跟我一样,偶尔会疑惑:曾经年少的时候学习过的那么多的复杂的数学函数,牛逼的化学方程式,各种物理原理.公式,到底有 ...
- Ajax顺序执行
循环中的Ajax 在前后端分离的项目中,Ajax是连接前后端的枢纽. 需求:有一个需要循环发起n次的请求,但是n次循环传参不同,我并不知道n是多少,并且要求能够保证返回顺序.JSONP用同步锁无效 示 ...