回看《例说FPGA》---DDR2控制器集成与读写测试
回看《例说FPGA》
---DDR2控制器集成与读写测试
1.DDR2 IP核的配置
需要弄清楚的选项主要有:
PLL reference clock frequency
Memory clock frequency
Controller data rate
对于DDR2 芯片的选型,可以在Memory Presets 里面选择,如果没有符合的器件,可以任意选中一个器件,点击modify parameters 按钮,在 preset Editor 里面进行参数配置。

2.片上RAM的配置

需要设置的选项有:
输出数据的位宽
存储器的深度
双时钟或单时钟
双时钟意味着输入输出采用不同的时钟:

在regs/clken/byte enable/aclrs选项卡中,需要设置的是:
Which ports should be registered? ‘ q output port’,如果选中,则在输出端加上一个触发器,输出数据时候,就会用clock信号打节拍。如果不选中,则:
3.数据源产生模块
实验的整体框图如下图所示:

数据源产生模块实现的功能为:
每秒定时DDR2数据写入控制;
每秒定时DDR2数据读出控制;
将读出的数据写入片上RAM中(RAM IP核在此模块中进行实例化);
此模块主要用来与DDR2 controller IP核进行通信,首先需要对DDR2 controller的信号多一些了解:
module ddr2_contral (
local_address,
local_write_req,
local_read_req,
local_burstbegin,
local_wdata,
local_be,
local_size,
global_reset_n,
pll_ref_clk,
soft_reset_n,
local_ready,
local_rdata,
local_rdata_valid,
local_refresh_ack,
local_init_done,
reset_phy_clk_n,
mem_odt,
mem_cs_n,
mem_cke,
mem_addr,
mem_ba,
mem_ras_n,
mem_cas_n,
mem_we_n,
mem_dm,
phy_clk,
aux_full_rate_clk,
aux_half_rate_clk,
reset_request_n,
mem_clk,
mem_clk_n,
mem_dq,
mem_dqs); input [:] local_address;
input local_write_req;
input local_read_req;
input local_burstbegin;
input [:] local_wdata;
input [:] local_be;
input [:] local_size;
input global_reset_n;
input pll_ref_clk;
input soft_reset_n;
output local_ready;
output [:] local_rdata;
output local_rdata_valid;
output local_refresh_ack;
output local_init_done;
output reset_phy_clk_n;
output [:] mem_odt;
output [:] mem_cs_n;
output [:] mem_cke;
output [:] mem_addr;
output [:] mem_ba;
output mem_ras_n;
output mem_cas_n;
output mem_we_n;
output [:] mem_dm;
output phy_clk;
output aux_full_rate_clk;
output aux_half_rate_clk;
output reset_request_n;
inout [:] mem_clk;
inout [:] mem_clk_n;
inout [:] mem_dq;
inout [:] mem_dqs;
ddr2 controller模块的接口可以分为三类:
第一类:系统接口,包含系统或PLL的复位,时钟等接口;
第二类:以local开头的接口,是DDR2 IP核与用户逻辑间的接口;(数据源产生模块主要用到的就是这类接口信号,需要弄懂这些信号的操作时序)
第三类:以mem开头的接口,是DDR2 IP核与FPGA外部DDR2芯片的接口;(只需要做引脚锁定,编程基本用不到)
关于使用DDR2 IP核用户外部逻辑操作loca信号的时序图如下:

在遇到local_ready拉低的读操作,下列信号必须保持到local_ready拉高为止:
local_read_req;
local_size;
local_addr;

写数据的时候,整个过程中,必须保持local_write_req信号一直有效。


逻辑代码:
module data_source(
clk, //75MHz
rst_n,
local_address,
local_write_req,
local_read_req,
local_wdata,
local_ready,
local_rdata,
local_rdata_valid,
local_init_done
); // 1/75MHz = 13.33ns;
input clk;
input rst_n;
output [:]local_address;
output local_write_req;
output local_read_req;
output [:]local_wdata;
input local_ready;
input [:]local_rdata;
input local_rdata_valid;
input local_init_done; reg[:] scnt;
reg[:] times; //计数器,当local_init_done有效时,计数器scnt开始计数
always @(posedge clk or negedge rst_n)
if(!rst_n) scnt <= 'd0;
else if(local_init_done) scnt <= scnt+'b1; wire timer_wrreq = (scnt == 'h00_001_000); // 55us
wire timer_rdreq = (scnt == 'h00_005_000); // 273us //每当timer_rdreq有效时,计数器times增加1,此模块用来计数读取数据的个数
always @(posedge clk or negedge rst_n)
if(!rst_n) times <= 'd0;
else if(timer_rdreq) times <= times+'b1; //状态机
parameter SIDLE = 'd0;
parameter SWRDB = 'd1;
parameter SRDDB = 'd2;
parameter SSTOP = 'd3; reg[:] cstate;
reg[:] num; always @(posedge clk or negedge rst_n)
if(!rst_n) cstate <= SIDLE;
else begin
case(cstate)
SIDLE: begin //控制状态机的跳转,timer_wrreq有效,则跳转到SWRDB,timer_rdreq有效,则跳转到SRDDB
if(timer_wrreq) cstate <= SWRDB;
else if(timer_rdreq) cstate <= SRDDB;
else cstate <= SIDLE;
end
SWRDB: begin //如果写入255个数据,并且local_ready有效,则状态结束
if((num == 'd255) && local_ready) cstate <= SSTOP;
else cstate <= SWRDB;
end
SRDDB: begin ////如果读取255个数据,并且local_ready有效,则状态结束
if((num == 'd255) && local_ready) cstate <= SSTOP;
else cstate <= SRDDB;
end
SSTOP: cstate <= SIDLE;
default: cstate <= SIDLE;
endcase
end always @(posedge clk or negedge rst_n)
if(!rst_n) num <= 'd0;
else if((cstate == SWRDB) || (cstate == SRDDB)) begin //如果状态处在SWRDB或者是SRDDB时,进入下一个判断阶段
if(local_ready) num <= num+'b1; //如果local_ready有效时,num开始计数
else ;
end
else num <= 'd0; assign local_address = (cstate == SWRDB) ? {'h0a55,2'd1,num[:]}:{'h0a55,2'd1,num[:]}; //地址采用num这个寄存器来进行地址偏移
assign local_wdata = {times,{num[:],'b00},times,{num[5:0],2'b01},times,{num[:],'b10},times,{num[5:0],2'b11}};
assign local_write_req = (cstate == SWRDB); //当状态机处在SWRDB时,发出写请求
assign local_read_req = (cstate == SRDDB); //当状态机处在SRDDB时,发出读请求 reg[:] ram_addr;
always @(posedge clk or negedge rst_n)
if(!rst_n) ram_addr <= 'd0;
else if(timer_rdreq) ram_addr <= 'd0; //当timer_rdreq读数请求有效时,ram_addr清零,即读数据请求到来时,ram_addr指向第一个地址
else if(local_rdata_valid) ram_addr <= ram_addr+'b1; //当local_rdata_valid信号有效时候,片上ram_addr开始偏移
else ; //此ram只写入,不输出
ram_1port u1 (
.address(ram_addr),
.clock(clk),
.data(local_rdata),
.wren(local_rdata_valid),
.q()
); endmodule
综合结果,RTL图:


回看《例说FPGA》---DDR2控制器集成与读写测试的更多相关文章
- Vue 2.5 发布了:15篇前端热文回看
Vue 2.5 发布了:15篇前端热文回看 2017-11-02 前端大全 (点击上方公众号,可快速关注) 本文精选了「前端大全」2017 年 10 月的 15 篇热门文章.其中有职场分享.技术分享和 ...
- Altera DDR2控制器学习笔记
Altera DDR2控制器使用IP的方式实现,一般很少自己写控制器代码. ddr22 ddr22_inst ( .aux_full_rate_clk (mem_aux_full_rate_clk), ...
- 【RPA之家转载RPA创新产业峰会回看】机器人流程自动化专利态势报告
[RPA之家转载RPA创新产业峰会回看]机器人流程自动化专利态势报告 自动化的一个专利情况的监测,就是全球监测的情况.今天我可能给大家汇报的主要是三个方面,第一个方面就是讲一下全球投资智能化的专利的一 ...
- CNTV视频回看下载地址
这其实不是新方法了,这个方法早在五六年前大家就在用,至今也没失效.但是五六年前那时候这个方法可以下载到过去三个月内CNTV直播过的视频,而现在只能下到一个星期的.之所以要下载回看版本,是因为比栏目版本 ...
- 利用Nginx搭建RTMP视频直播,点播服务器,ffmpeg推流,回看
一.环境和工具 ubuntu 14.04 desktop 不用server的原因是一部分的演示用到了linux视频播放和直播软件,自己还要装桌面,麻烦. 不建议使用 最新的16TLS,我一开始 ...
- 6 大主流 Web 框架优缺点对比:15篇前端热文回看
摘自:http://blog.csdn.net/VhWfR2u02Q/article/details/78993079 注:以下文章,点击标题即可阅读 <6 大主流 Web 框架优缺点对比> ...
- 2020 .NET 开发者峰会顺利在苏州落幕,相关数据很喜人以及线上直播回看汇总
在2019年上海中国.NET开发者大会的基础上,2020年12月19-20日 继续以"开源.共享.创新" 为主题的第二届中国 .NET 开发者峰会(.NET Conf China ...
- 2021 .NET 开发者峰会顺利在网上落幕,线上直播回看汇总
.NET Conf China 2021 是面向开发人员的社区峰会,基于 .NET Conf 2021的活动,庆祝 .NET 6 的发布和回顾过去一年来 .NET 在中国的发展成果展示,它是由中国各地 ...
- 基于FPGA的DDR3多端口读写存储管理系统设计
基于FPGA的DDR3多端口读写存储管理系统设计 文章出处:电子技术设计 发布时间: 2015/03/12 | 1747 次阅读 每天新产品 时刻新体验专业薄膜开关打样工厂,12小时加急出货 机载 ...
随机推荐
- Spring+CXF+Maven发布Webservice
使用CXF发布WebService简单又快速,还可以与Spring集成,当Web容器启动时一起发布WebService服务.本例是简单的客户端给服务端发送订单信息,服务端返回订单转为json的字符串. ...
- Python urllib.quote
转: 编码:urllib.quote(string[, safe]),除了三个符号“_.-”外,将所有符号编码,后面的参数safe是不编码的字符, 使用的时候如果不设置的话,会将斜杠,冒号,等号,问号 ...
- 字符串(text)格式的html代码文本转为DOM对象
/*字符串转dom对象*/ window.strimgTurnDom = function(txt) { try //Internet Explorer { xmlDoc=new ActiveXObj ...
- L3-019 代码排版 (30 分)
某编程大赛中设计有一个挑战环节,选手可以查看其他选手的代码,发现错误后,提交一组测试数据将对手挑落马下.为了减小被挑战的几率,有些选手会故意将代码写得很难看懂,比如把所有回车去掉,提交所有内容都在一行 ...
- 模块化,AMD规范
模块化:代码量比较大,可能会有几个人同时写一个页面,同样写在一个文件里面,可能会有冲突,模块化可以解决代码的冲突(匿名函数调用,自己调用自己,就是立即执行函数) 团队的分工更加的明确 异步的执行: A ...
- Vim+Ctags+Cscope安装
对比了下,感觉还是Vim比较专业. 一:使用说明: ‘/’查找忽略大小写,比如需要查找“book”,当输入/b的时候会自动找到第一个以"b"开头的单词 实现C程序的缩减 查询中自由 ...
- Xenserver之HA实现-NFS的实现
环境: 在vm上安装好一台Xenserver服务器,一台centos7虚拟机(用来做NFS存储,因为实现HA需要共享存储),网络连接方式为桥接模式 echo '- - -'>> /sys/ ...
- 事务 — Redis 设计与实现
非事务状态下的命令以单个命令为单位执行,前一个命令和后一个命令的客户端不一定是同一个: 事务状态则是以一个事务为单位,执行事务队列中的所有命令:除非当前事务执行完毕,否则服务器不会中断事务,也不会执行 ...
- LOJ 2553 「CTSC2018」暴力写挂——边分治+虚树
题目:https://loj.ac/problem/2553 第一棵树上的贡献就是链并,转化成 ( dep[ x ] + dep[ y ] + dis( x, y ) ) / 2 ,就可以在第一棵树上 ...
- dojo:如何用MultiSelect实现类似ListBox风格的FromTo功能
欲实现的功能如下图: 主要要解决的问题包括两个方面: 一个是MultiSelet初始化的工作,一个是FromTo功能按钮的实现.这主要是因为MultiSelect控件是存储无关的,并不像Select或 ...