DDR2 IP核调式记录2

news2024/11/20 6:16:40

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

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 			,    // Clock
	input 					global_reset_n 	,  // Asynchronous reset active low


	output  [ 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; 				// 突发长度 4

	parameter 			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 */;
	    endcase

		always@(posedge phy_clk or negedge rst_n)begin 
		if(!rst_n)
			state <= IDEL;
		else
			case (state)
				IDEL 	:	state <= WRITER;

				WRITER 	: 	if(mem_local_ready)
								state <= WRITING;
							else
								state <= WRITER;

				WRITING : 	if(wdatalen == LEN)
								state <= READR;
							else
								state <= state;
				READR 	: 	if(mem_local_ready)
								state <= READING;
							else
								state <= READR;

				READING : 	if(rdatalen == LEN)
								state <= IDEL;
							else
								state <= state;		
				default : state <= state;
			endcase
		end

		// 写的数据自加1
		always@(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;
		else
			mem_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 ;
		else
			wdatalen <= 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;
		else
			rdatalen <= 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;
		end

endmodule

测试代码

`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.coloradmin.cn/o/971494.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

npm版本升级报错

解决方法&#xff1a; 执行npm install --legacy-peer-deps依赖对等 npm install xxx --legacy-peer-deps命令用于绕过peerDependency里依赖的自动安装&#xff1b;它告诉npm忽略项目中引入的各个依赖模块之间依赖相同但版本不同的问题&#xff0c;以npm v4-v6的方式去继续执行…

OC和Swift混编,导入头文件‘xxx-Swift.h‘ file not found

在OC的项目里加入Swift代码&#xff0c;创建完桥接文件后&#xff0c;需要倒入Swift头文件&#xff0c;头文件的格式为“项目名-Swift.h”。 如下图&#xff0c;我在Xcode上看到我的项目名为YichangPark&#xff0c;导入 #import "YiChangPark-Swift.h" 之后提示 “Y…

手写Mybatis:第15章-返回Insert操作自增索引值

文章目录 一、目标&#xff1a;Insert自增索引值二、设计&#xff1a;Insert自增索引值三、实现&#xff1a;Insert自增索引值3.1 工程结构3.2 Insert自增索引值类图3.3 修改执行器3.3.1 修改执行器接口3.3.2 抽象执行器基类 3.4 键值生成器3.4.1 键值生成器接口3.4.2 不用键值…

使用vs播放.wav文件

本次操作在Windows10平台vs2019完成。 一、准备好.wav资源文件 上网找到自己想要播放的音乐文件&#xff0c;下载到本地后建议放到项目所在文件夹中。 二、添加资源文件 在“解决方案”中右键“资源文件”&#xff0c;点击“添加”&#xff0c;点击“资源”&#xff0c; 选…

【AGC】App Linking首次不能重定向指定页面的问题

【关键字】 AGC、App Linking、重定向 【问题描述】 有开发者反馈app linking未安装应用时&#xff0c;自定义地址可以重定向到apk应用内的任意页面会出现问题。app linking 未安装apk时指定到对应页面时&#xff0c;只拉开应用市场&#xff0c;安装后首次不能跳转到指定页面…

【操作系统】聊聊常见的内存管理方式

CPU 的实模式和保护模式。这两个模式 CPU 对内存的操作方式完全不同。在实模式下&#xff0c;CPU 直接通过物理地址访问内存。在保护模式下&#xff0c;CPU 通过一个地址映射表把虚拟的内存地址转为物理的内存地址&#xff0c;然后再去读取数据。 虚拟内存 在保护模式下&#…

数据结构--6.2关键路径

AOE网&#xff1a; 在一个表示工程的带权有向图中&#xff0c;用顶点表示事件&#xff0c;用有向边上的权值表示活动表示持续时间&#xff0c;这种有向图的边表示活动的网&#xff0c;我们称为AOE网&#xff08;Activity On Edge Network&#xff09;。 我们把AOE网中没有入边的…

Nginx重写功能和反向代理

目录 一、重写功能rewrite 1.1 if指令 1.2 return 1.3 set指令 1.4 break 指令 二、反向代理 2.1动静分离 2.2 缓存功能 2.3 ip穿透 2.4 http反向代理负载均衡 一、重写功能rewrite Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求&#xff0c;此…

Mybatis-plus联表查询 -- mybatis-plus-join

以t_order、t_user、t_product三表联合查询为例&#xff0c;其中t_order表为主表。 0.数据源配置 在springboot项目中&#xff0c;像往常一样正常配置数据源。 1.引入依赖 首先在项目中引入引入依赖坐标&#xff0c;因为mpj中依赖较高版本mybatis-plus中的一些api&#xff0…

【C++】函数参数扩展 ② ( 占位参数 | 占位参数规则 - 必须为占位参数传入实参 | 默认参数与占位参数结合使用 )

文章目录 一、占位参数1、占位参数简介2、占位参数规则 - 必须为占位参数传入实参 二、默认参数与占位参数结合使用1、结合用法2、代码示例 - 占位参数与默认参数结合用法 博客总结 : 默认参数 : 在 声明 函数时 , 为 函数参数 定义一个默认值 ;默认参数规则 : " 默认参数…

JS数组迭代方法实操

数组迭代方法有 1. every() 2.some() 3.foreach() 4.map() 5.filter 逐一操作&#xff0c;并简要区分之。 1 every() every() 方法使用指定的函数测试数组中所有的项&#xff0c;在数组的所有项都满足该条件时&#xff0c;才返回true&#xff0c;否则返回false&#xff1b; …

基于亚马逊云科技打造的游戏AIGC专业版,创梦天地快速上线AI生图服务

生成式人工智能&#xff08;以下简称“生成式AI”&#xff09;的热潮正在全球范围内掀起新一轮的科技革命&#xff0c;释放出巨大的商业价值。各类“AI绘画神器”的涌现&#xff0c;为创意行业带来了翻天覆地的变化。 在游戏领域&#xff0c;生成式AI技术也吸引了玩家们的广泛关…

QT day5

服务器&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化对象server new QTcpServer(this); }Widget::~Widget() {delete ui…

数学建模之层次分析法

目录 1 模型概述2 模型流程2.1 建立递阶层次结构2.2 构造判断矩阵2.3 一致性检验2.4 计算权重2.4.1 算术平均法2.4.2 几何平均法2.4.3 特征值法 2.5 计算各方案的得分 3 编写代码4 模型局限性 1 模型概述 层次分析法(The analytic hierarchy process, 简称AHP)&#xff0c;是建…

9-AJAX-2综合案例

AJAX-综合案例 目录 案例-图书管理图片上传案例-网站换肤案例-个人信息设置 学习目标 今天主要就是练&#xff0c;巩固 axios 的使用 完成案例-图书管理系统&#xff08;增删改查&#xff09;经典业务掌握图片上传的思路完成案例-网站换肤并实现图片地址缓存完成案例-个人信…

Cyber RT学习笔记 --- 1.Cyber RT框架介绍

1.Cyber RT框架介绍 1.1 Cyber RT简介 Apollo Cyber是首个专为自动驾驶定制的高性能且开源的实时通信框架&#xff0c;于2019年与Apollo 3.5开放平台同期发布&#xff0c;它主要解决了自动驾驶系统的高并发、低延迟、高吞吐、任务调度等问题&#xff0c;同时还提供了多种通信…

Docker 使用

简介 Docker是一个开源的容器引擎&#xff0c;它有助于更快地交付应用。 Docker可将应用程序和基础设施层隔离&#xff0c;并且能将基础设施当作程序一样进行管理。使用 Docker可更快地打包、测试以及部署应用程序&#xff0c;并可以缩短从编写到部署运行代码的周期。 Docker…

Web前端开发概述

Web&#xff08;World Wide Web&#xff0c;全球广域网&#xff09;是指一种基于互联网的信息系统&#xff0c;通过超文本链接将全球各地的文档、图像、视频等资源相互关联起来&#xff0c;并通过Web浏览器进行交互浏览和访问。Web的发展使得人们可以方便地获取和共享各种类型的…

GPT引领前沿与应用突破之GPT4科研实践技术与AI绘图

GPT对于每个科研人员已经成为不可或缺的辅助工具&#xff0c;不同的研究领域和项目具有不同的需求。如在科研编程、绘图领域&#xff1a;1、编程建议和示例代码: 无论你使用的编程语言是Python、R、MATLAB还是其他语言&#xff0c;都可以为你提供相关的代码示例。2、数据可视化…