XILINX中DDR3 IP核的使用

  1. 前言

最近一直在查找关于DDR3的资料,网上也有很多介绍,这篇主要是记录我的学习过程,以防后期遗忘。本篇主要是针对如何运用XILINX的MIG核,因个人能力有限,对DDR3的硬件外围电路和原理只是大概的一个认知,如有错误还望指正。

  1. 确定芯片的速率和位宽

例如:

DDR3芯片为型号为:MT41K256M16XX-125

FPGA型号为:XC7K325TFFG900-2

1、下图为镁光的DDR3数据手册,主要解释DDR3的数据位宽、容量大小和速度等级

256M16:其中16代表芯片位宽,芯片总的容量为:256M字节*16bit=512M字节

2、查看FPGA中支持DDR3的最大数据速率为1866Mb/s,大多时候都是1600Mb/s。因为DDR3是双边沿采样,所以对应频率为1600/2=800Mhz

3、带宽

DDR3速率是800MHz,因为上下边沿采样,所以速率是2*800=1600MT/S,速率就是1600Mbit/s,因为DDR3是16bit,所以总的带宽为16*1600Mbit/s=3.125GByte/s

  1. IP核的一些关键时钟配置

1、

 

上图中1是由输入的system clock通过MIG中的PLL倍频得到的,通过端口

.ddr3_ck_n (ddr3_ck_n), 

.ddr3_ck_p (ddr3_ck_p),

输出给DDR3芯片,这个时钟是DDR3接口的实际速率400MHz。

上图中2是用户时钟的接口,显示的比利4:1也就是实际接口的速率的1/4,100MHz;

.ui_clk (ddr_ui_clk),

上图中3是DDR3中型号的选择,位宽的选择和电压选择。

  1. 输入管脚时钟配置

 

图中1的位置是选择输入时钟,是根据实际的硬件选择的。

对应端口为,选择的是差分输入

.sys_clk_p (sys_clk_p), 

.sys_clk_n (sys_clk_n),

图中2的位置是选择突发类型选择,一般选择顺序突发

  1. 输入时钟和参考时钟的类型选择

 

图中1的位置选择系统时钟的类型,根据实际电路选择,这里选择差分时钟,

图中2是选择参考,如果系统时钟配置的是200MHz,那么这里的参考时钟可以选择use system clock。

  1. MIG的时序图和管脚
  1. 管脚说明
// Application interface ports

.app_addr                       (app_addr),   // 写数据地址

.app_cmd                        (app_cmd),   // DDR3指令 写:3‘b000;读:3’b001;

.app_en                         (app_en),   // 指令写使能

.app_wdf_data                   (app_wdf_data),   // 写数据

.app_wdf_end                    (app_wdf_end),   // 写数据结束标志

.app_wdf_wren                   (app_wdf_wren),   // 写数据使能

.app_rd_data                    (app_rd_data),   // 读数据

.app_rd_data_end                (app_rd_data_end),  // 读数据结束标志

.app_rd_data_valid              (app_rd_data_valid),// 读数据有效标志

.app_rdy                        (app_rdy),   // 指令准备信号

.app_wdf_rdy                    (app_wdf_rdy),   // 写数据准备信号

对于用户层,只需要知道如何去控制DDR3怎么读写数据,只需要控制以上信号即可。

  1. 写指令和写数据时序图

 

从上图可知,只有当app_rdy为高的时候,app_cmd、app_addr以及app_en才有效。

 

由上图可知,当写指令有效的时候,写数据可以有三种模式给出:

1:第一种是对齐模式,也是大家常用的模式

2:第二种是提前写指令一个周期写入数据

3:第三种是当写指令给出以后,延迟2个周期给出数据

但是在实际情况中我们需要考虑信号app_rdy和app_wdf_rdy的有效性,所以采用以上模式有点儿困难,再次前提下我们需要知道一个事情,那就是写指令和写数据其实是相互独立的,其实就是写数据是写在一个FIFO中,当给出一个写指令,就会从fifo中读出一个数据给DDR3,所以在实际设计中,可以先考虑将写数据先写入,在等待app_rdy为高的时候给出写指令。如下图所示:

其实虽然app_rdy为低,但是这个时候可以先将数据100写进去,等待app_rdy拉高之后就将地址写进去,这个时候写的数据也是有效的。

  1. 读数据时序图

其实读数据时序很简单,MIG和会将数据的有效标志和数据从IP中输出出来,只需要提前给出读数据的地址就行。

 

如上图所示,提前给出读数据指令和数据地址,等待一个不固定的时钟周期,IP核就可以出来数据和数据有效标志。

5、程序设计

本次主要是验证读写DDR3,最后做仿真

  1. 状态图

 

 

  1. 写数据部分的主要代码
WRITE_1:begin
	app_cmd				<=	3'b000;
	app_en				<=	1;
	app_addr			<=	wr_addr_cnt;
	wr_addr_cnt			<=	wr_addr_cnt + 8;
	app_wdf_wren		<=	1;
	app_wdf_end			<=	1;
	app_wdf_data		<=	100;
	DDR3_STATE			<=	WRITE_2;
	wr_ddr3_cnt			<=	wr_ddr3_cnt + 1;						
end
WRITE_2:begin
	if(app_rdy && app_wdf_rdy)begin
		if(wr_ddr3_cnt	>=	WRITE_SIZE)begin
			wr_ddr3_cnt			<=	16'b0;
			app_addr			<=	wr_addr_cnt;
			wr_addr_cnt			<=	wr_addr_cnt + 8;
			app_wdf_wren		<=	0;
			app_wdf_end			<=	0;
			app_en 				<=  0;
			app_wdf_data		<=	app_wdf_data + 1;
			DDR3_STATE			<=	NOP;
		end else begin
			app_addr			<=	wr_addr_cnt;
			wr_addr_cnt			<=	wr_addr_cnt + 8;
			app_en 				<=  1;
			app_wdf_wren		<=	1;
			app_wdf_end			<=	1;
			app_wdf_data		<=	app_wdf_data + 1;
			wr_ddr3_cnt			<=	wr_ddr3_cnt + 1;
			DDR3_STATE			<=	WRITE_2;	
		end
	end else if(app_rdy == 1 && app_wdf_rdy ==0)begin
		app_en					<=	0;
	end else if(app_rdy == 0 && app_wdf_rdy == 1) begin
		app_wdf_wren			<=	0;
		app_wdf_end				<=	0;
	end				
end
  1. 读书主要部分代码
READ:	begin
	app_cmd				<=	3'b001;
	app_en				<=	1;
	app_addr			<=	rd_addr_cnt;
	rd_addr_cnt			<=	rd_addr_cnt + 8;
	DDR_RD_CNT			<=	DDR_RD_CNT  + 1;
	DDR3_STATE			<=	READ_0;	
end

	READ_0: begin
		if(app_rdy == 1) begin
			if(DDR_RD_CNT >= WRITE_SIZE)
				begin
				DDR_RD_CNT			<=	16'b0;
				app_en				<=	0;
				DDR3_STATE			<=	NOP_0;
				end
			else begin
				app_addr			<=	rd_addr_cnt;
				rd_addr_cnt			<=	rd_addr_cnt + 8;
				DDR_RD_CNT			<=	DDR_RD_CNT  + 1;
			end
		end
	end

  1. 仿真模型

 

 

图中的DDR3的例子模块是在DDR3中的仿真模块中复制过即可使用,具体模块位置和名字如下:

 

 

首先是打开DDR3中的例子工程,找到其中的仿真文件,打开其子目录找到如下模块:

 

 

具体的例化模型如下图,双击顶层的模块sim_tb_top,找到下图中的位置

 

 

本次工程例化的是16bit的DDR3,可以参照如下进行例化

 

ddr3_model u_comp_ddr3

        (

         .rst_n   (ddr3_reset_n),

         .ck      (ddr3_ck_p),

         .ck_n    (ddr3_ck_n),

         .cke     (ddr3_cke),

         .cs_n    (ddr3_cs_n),

         .ras_n   (ddr3_ras_n),

         .cas_n   (ddr3_cas_n),

         .we_n    (ddr3_we_n),

         .dm_tdqs (ddr3_dm),

         .ba      (ddr3_ba),

         .addr    (ddr3_addr),

         .dq      (ddr3_dq),

         .dqs     (ddr3_dqs_p),

         .dqs_n   (ddr3_dqs_n),

         .tdqs_n  (),

         .odt     (ddr3_odt)

        );

多位宽的可以查找其它博主进行设计。

5、仿真结果查看

 

 

上图是写数据的时序,可以看到我们往地址0里面写的数据是100,地址8里面写的是101

我们查看读数据部分,

 

 

查看上图我们给出了读数据的指令,地址从0开始加;

 

 

从上图中可以看到读出的第一个数据是100,后面依次验证正确。

6、设计心得

因为这是我第一次写的博客,有很多问题,如果有误,还望指正。DDR3使我们开发设计中经常用到的,所以学会使用它,对我们的帮助很大,前期我也查看了其它博主使用的对齐模式,我自己也测试过,不知道为什么最后仿真总是读不出数据,最后才使用这种模式,大家只需要知道,写指令和写数据其实是两个分开的,没有多大关系,可以先写数据在给指令。这个大概就分享到这里。本篇设计是参考https://blog.csdn.net/m0_52840978/article/details/121304187这个博主的DDR3设计。说的很详细很透彻。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
FPGA调用多个DDR3 IP核的方法与调用单个IP核类似。首先,你需要明确每个IP核的配置参数,包括宽度和深度等。然后,你可以使用Xilinx提供的现成IP核来调用和修改参数。你可以通过学习如何调用和配置IP核来提高开发效率,并减少项目的错误。在调用多个DDR3 IP核时,你需要为每个IP核分配不同的实例名,并根据需要进行参数配置。例如,你可以使用PHY to Controller Clock Ratio参数来设置每个IP核的时钟比例,以确保每个IP核的时钟频率正确。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [FPGA——调用DDR的IP核(MIG核)](https://blog.csdn.net/weixin_46188211/article/details/124092984)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [【FPGA】七、IP核的调用](https://blog.csdn.net/weixin_62912626/article/details/128305143)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Xilinx FPGA DDR3设计(三)DDR3 IP核详解及读写测试](https://blog.csdn.net/gslscyx/article/details/130694959)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值