当前位置: 首页 > news >正文

DDR2 IP核调式记录2

本文相对简单,只供自己看看就行。从其它的博客找了个代码,然后记录下仿真波形。

1. 功能

        直接使用quartus生成的DDR2 IP核,然后实现循环 -->写入burst长度的数据后读出。

        代码数据的传输是32位,实际使用了两片IC。因此IP核也是32位交互。

2.信号分析

        burst=4,是IC固有的=预取值。而代码中LEN为用户一次想要读取数据的长度的。与local_size和burst_length无关。

        分为4个状态: IDLE、WRITER、WRITING、READR、READING。WRITER和READR状态下,开始读写burst的第一个数据,其余的在WRITING和READING状态读写。

         local_ready:很重要的一个指示信号。要进行读写操作,必须在IP核(ddr2)准备好的情况下进行。因此,需要一直对此信号进行检测判断。

        写入地址(mem_local_addr),一开始为1,当读到的数据长度rdatalen=5时(初始值=1),mem_local_addr <= mem_local_addr + 4;

命令

连续写

连续读

读完写

3. 仿真波形分析

如下图所示:每次先写入连续4个数据,(例如1,2,3,4),然后再依次读出。

读过程及下一次写

4. 附代码

顶层代码:

module ddr2wrtest (input 					clk 			,    // Clockinput 					global_reset_n 	,  // Asynchronous reset active lowoutput  [ 12: 0]		mem_addr 		,	output  [  2: 0] 		mem_ba 			,	output					mem_cas_n 		,	output					mem_cke 		,	inout					mem_clk 		,	inout 					mem_clk_n 		,	output 					mem_cs_n 		,	output 	[  1: 0]		mem_dm 			,	inout	[ 15: 0]		mem_dq 			,	inout	[  1: 0]		mem_dqs 		,	output					mem_odt 		,	output					mem_ras_n 		,	output					mem_we_n 			);parameter 			LEN 	= 8; 				// 突发长度 4parameter 			IDEL 		= 5'b00001;		// 空闲态parameter 			WRITER 		= 5'b00010;		// 准备写parameter 			WRITING 	= 5'b00100;		// 写状态parameter 			READR 	 	= 5'b01000;		// 准备读parameter 			READING 	= 5'b10000;		// 读状态reg	 [  5: 0]		state;
//**********************与IP相连部分********************//reg [ 24: 0]	mem_local_addr		=1	;wire 				mem_local_init_done		;	wire 				local_burstbegin_sig	;								wire [ 31: 0]	mem_local_rdata 		;wire 				mem_local_rdata_valid	;wire 				mem_local_read_req		;wire 				mem_local_ready			;							wire [  3: 0]	mem_local_size			;reg  [ 31: 0]	mem_local_wdata			;wire 				mem_local_write_req		;wire 				phy_clk 				;wire 				reset_phy_clk_n 		;
//*****************************************************//wire 				rst_n 					;reg  [  3: 0] 		rdatalen 				; // 读突发长度计数器reg  [  3: 0] 		wdatalen 				; // 写突发长度计数器reg  [100: 0]		state_name				; // 状态名assign rst_n = reset_phy_clk_n&&mem_local_init_done;assign mem_local_size = LEN;assign local_burstbegin_sig = ((state == WRITER&&mem_local_ready) || (state == READR&&mem_local_ready))?1:0;assign mem_local_write_req  = (state == WRITING)?1:0;assign mem_local_read_req 	= (state == READR&&mem_local_ready)?1:0;ddr2 ddr2_inst(
//==============================《				   》===============================.aux_full_rate_clk 	(						),	//全速率时钟.aux_half_rate_clk 	(						),	//半速率时钟
//==============================《    用户操作信号   》===============================.global_reset_n		(global_reset_n 		),	//全局复位.local_address 		(mem_local_addr			),	//当前操作地址.local_be 			(8'hff					),	//数据掩码.local_burstbegin 	(local_burstbegin_sig	),	//突发起始信号.local_init_done 		(mem_local_init_done	),	//初始化完成信号.local_rdata 			(mem_local_rdata 		),	//读数据总线.local_rdata_valid 	(mem_local_rdata_valid	),	//读有效标志.local_read_req 		(mem_local_read_req		),	//读请求,保持一个时钟周期.local_ready 			(mem_local_ready		),	//接受到请求.local_refresh_ack 	(						),	//自动刷新.local_size 			(mem_local_size			),	//突发长度.local_wdata 			(mem_local_wdata		),	//写数据总线.local_write_req 		(mem_local_write_req	),	//写请求
//==============================《  与DDR2相连的信号  》===============================.mem_addr 			(mem_addr 				),	//地址总线.mem_ba 				(mem_ba					),	//bank地址.mem_cas_n 			(mem_cas_n				),	//行选通.mem_cke 				(mem_cke				),	//时钟使能.mem_clk 				(mem_clk 				),	//操作时钟.mem_clk_n 			(mem_clk_n				),	//反向时钟.mem_cs_n 			(mem_cs_n 				),	//片选信号.mem_dm 				(mem_dm 				),	//DDR2数据屏蔽信号.mem_dq 				(mem_dq 				),	//数据总线.mem_dqs 				(mem_dqs 				),	//数据选取脉冲信号.mem_odt 				(mem_odt 				),	//片内终结信号.mem_ras_n 			(mem_ras_n 				),	//行选通.mem_we_n 			(mem_we_n 				),	//使能
//==============================《    用户操作信号    》===============================.phy_clk 				(phy_clk 				),	//提供给用户的操作时钟.pll_ref_clk 			(clk 					),	//给ddr2的输入时钟.reset_phy_clk_n 		(reset_phy_clk_n 		),	//提供给用户的复位信号.reset_request_n 		(						),	//当PLL锁定后为低电平.soft_reset_n 		(1'b1 					)	//软复位,不包括PLL的复位);always@(*)case (state)IDEL  	:	state_name = "IDEL";WRITER 	:	state_name = "WRITER"		;		WRITING	:	state_name = "WRITING"		;		READR 	:	state_name = "READR"		;			READING	:	state_name = "READING";default : /* default */;endcasealways@(posedge phy_clk or negedge rst_n)begin if(!rst_n)state <= IDEL;elsecase (state)IDEL 	:	state <= WRITER;WRITER 	: 	if(mem_local_ready)state <= WRITING;elsestate <= WRITER;WRITING : 	if(wdatalen == LEN)state <= READR;elsestate <= state;READR 	: 	if(mem_local_ready)state <= READING;elsestate <= READR;READING : 	if(rdatalen == LEN)state <= IDEL;elsestate <= state;		default : state <= state;endcaseend// 写的数据自加1always@(posedge phy_clk or negedge rst_n)begin if(!rst_n)mem_local_wdata <= 1;else if(state == WRITING && mem_local_ready)mem_local_wdata <= mem_local_wdata + 1;elsemem_local_wdata <= mem_local_wdata;end// 当前写的数据突发长度always@(posedge phy_clk or negedge rst_n)begin if(!rst_n) wdatalen <= 1;else if(state == WRITING && mem_local_ready)wdatalen <= wdatalen + 1;else if(state == WRITING && !mem_local_ready)wdatalen <= wdatalen ;elsewdatalen <= 1;end// 当前读的数据突发长度always@(posedge phy_clk or negedge rst_n)begin if(!rst_n) rdatalen <= 1;else if(state == READING && mem_local_rdata_valid)rdatalen <= rdatalen + 1;elserdatalen <= 1;end// 操作地址自加always@(posedge phy_clk or negedge rst_n)begin if(!rst_n)mem_local_addr <= 1;else if(rdatalen == LEN)mem_local_addr <= mem_local_addr + LEN;endendmodule

测试代码

`timescale 1ns/1ps
module test_tb ();reg				clk 		;
reg				global_reset_n;wire  	[ 12: 0]	mem_addr 	;
wire  	[  2: 0] 	mem_ba 		;
wire				mem_cas_n 	;
wire				mem_cke 	;
wire				mem_clk 	;
wire 				mem_clk_n 	;
wire 				mem_cs_n 	;
wire 	[  1: 0]	mem_dm 		;
wire	[ 15: 0]	mem_dq 		;
wire	[  1: 0]	mem_dqs 	;
wire				mem_odt 	;
wire				mem_ras_n 	;
wire				mem_we_n 	;ddr2wrtest u1 (.clk 			(clk 			),    // Clock.global_reset_n (global_reset_n ) ,  // Asynchronous reset active low.mem_addr 		(mem_addr 		),	.mem_ba 		(mem_ba 		),	.mem_cas_n 		(mem_cas_n 		),	.mem_cke 		(mem_cke 		),	.mem_clk 		(mem_clk 		),	.mem_clk_n 		(mem_clk_n 		),	.mem_cs_n 		(mem_cs_n 		),	.mem_dm 		(mem_dm 		),	.mem_dq 		(mem_dq 		),	.mem_dqs 		(mem_dqs 		),	.mem_odt 		(mem_odt 		),	.mem_ras_n 		(mem_ras_n 		),	.mem_we_n 		(mem_we_n 		)	);ddr2_mem_model mem (.mem_dq      (mem_dq),.mem_dqs     (mem_dqs),.mem_dqs_n   (mem_dqs_n),.mem_addr    (mem_addr),.mem_ba      (mem_ba),.mem_clk     (mem_clk),.mem_clk_n   (mem_clk_n),.mem_cke     (mem_cke),.mem_cs_n    (mem_cs_n),.mem_ras_n   (mem_ras_n),.mem_cas_n   (mem_cas_n),.mem_we_n    (mem_we_n),.mem_dm      (mem_dm),.mem_odt     (mem_odt));
always #10 clk = ~clk;
initial begin clk = 0;global_reset_n = 0;@(posedge clk);@(posedge clk);@(posedge clk);@(posedge clk);@(posedge clk);@(posedge clk);@(posedge clk);@(posedge clk);@(posedge clk);global_reset_n = 1;
end
endmodule

http://www.lryc.cn/news/155596.html

相关文章:

  • 【ES6】js 中class的extends、super关键字用法和避坑点
  • mysql排名函数row_number()over(order by)和with * as 的用法
  • linux局域网IP地址冲突检测
  • 远距离WiFi模组方案,实现移动设备之间高效通信,无人机远程图传应用
  • Docker构建Springboot项目,并发布测试
  • flutter架构全面解析
  • QHttpServer
  • 21.3 CSS 背景属性
  • Ansible 常用命令50条
  • ceph源码阅读 erasure-code
  • C++ 之 命名空间
  • MyBatis关系映射
  • DVWA失效的访问控制
  • docker 笔记2 Docker镜像和数据卷
  • java springboot 时间格式序列化 UTC8
  • 攻防世界-Get-the-key.txt
  • MyBatisPlus之DQL编程控制
  • 本地使用GFPGAN进行图像人脸修复
  • Linux--进程概念
  • dex2oat编译模式、触发场景、命令强制执行
  • 深度学习 | TCN时间卷积神经网络模型答疑
  • Linux之修改服务端口号
  • LeetCode笔记:Weekly Contest 361
  • Springboot快速搭建Web API项目
  • 数据结构day06(单向循环链表、双向链表)
  • zabbix -- 新建主机
  • =>符号含义
  • Docker+Jenkins(blueocean)+Gitee构建CICD流水线实战
  • Redis快速入门
  • EasyExcel 修改导出的文件属性