当前位置:网站首页>DDR3-基于正点原子达芬奇100Tpro1.0版本
DDR3-基于正点原子达芬奇100Tpro1.0版本
2022-08-07 05:13:00 【FPGA小白758】
1.DDR3硬件设计

2.DDR3引脚作用
| 信号 | 类型 | 作用 |
|---|---|---|
| CK,~CK | Input | 一对差分信号时钟,可在CK的上升沿和下降沿采样 |
| CKE | Input | 时钟使能,操作使能,为低时只能自刷新 |
| CS | Input | 片选信号 |
| RAS,CAS,WE | Input | 指令线 |
| For x8 DM,Forx16 DMU DML | Input | 屏蔽数据 |
| BA0-BA2 | Input | bank地址 |
| A10/AP | Input | 自动刷新的控制 |
| For x8, A0-A14/For x16 A0-A13 | Inpout | 地址线 |
| A12/BC | Input | 突发模式控制线,默认8突发 |
| ODT | Input | 自动的电压校准,使差分时钟保持稳定,低有效 |
| RESET_N | Input | 复位信号 |
| DQ | Input/Output | 数据线 |
| For x8DQS,(DQS_N)/For x8 DQSL,DQSU | Input/output | 数据选择脉冲 |
| For x8,TDQS | Output |
3.DDR3时序
3.1 初始化时序

1.上电时复位信号保持低电平,其他信号随意。复位低电平至少保持200us,CKE要在复位信号拉高之前至少保持10ms的低电平。
2.复位信号失效后需要等待500us,CKE信号开始拉高,在此期间DRAM开始初始化。
3.CKE为高电平且稳定后,需要加载寄存器。
4.配置寄存器时指令是相同的,通过BA0-BA2来控制是配置MR。如MR2是BA2-BA0->010;
5.配置完成后需要ZQCL校准。
3.2DDR3寄存器配置

| 寄存器 | 作用 |
|---|---|
| BL | 突发长度 |
| CL | 突发长度 |
| RBT | 顺序读还是常规读 |
| CAS | CL延迟配置 |
| BL | 突发长度 |
4.程序设计
DDR3 SDRAM程序过于复杂,因此官方提供MIG IP核来简化DDR3 SDRAM的驱动程序开发
4.1 MIG核 接口介绍
读数据接口
| Column 1 | Column 2 |
|---|---|
| app_addr[ADDR_WIDTH-1:0] | DDR3的地址线 |
| app_cmd[2:0] | DDR3指令手册,只有读写两个指令 |
| app_en | MIG核的使能信号 |
| app_rdy | 表示MIG核可以接受指令 |
| app_hi_pri | 优先级指令 |
| app_rd_data[APP_DATA_WIDTH-1:0] | 读出的数据 |
| app_rd_data_end | 最后一次突发,突发结束标志位 |
| app_rd_data_valid | 读数据有效标志 |
| app_sz | 需要保留并置零 |
写数据接口
| Column 1 | Column 2 |
|---|---|
| app_wdf_data[APP_DATA_WIDTH-1:0] | 为写命令提供数据 |
| app_wdf_end | 突发写操作的最后一个时钟周期 |
| app_wdf_mask[APP_DATA_WIDTH-1:0] | 数据掩码 |
| app_wdf_rdy | 写数据允许标志 |
| app_wdf_wren | 写数据使能 |
| app_correct_en_i | 纠错功能 |
| app_sr_req | 保留并且置零 |
| app_sr_active | 保留 |
其他接口
| Column 1 | Column 2 |
|---|---|
| app_ref_req | 刷新请求 |
| app_ref_ack | 刷新请求的应答 |
| app_zq_req | 校准请求 |
| app_zq_ack | 校准请求应答 |
| ui_clk | 用户时钟,由DRAM时钟的四分之一或者二分之一 |
| init_calib_complete | 初始化完成标志 |
| app_ecc_multiple_err[7:0] | 当开启ECC功能并且数据有效时的纠错指示位 |
| ui_clk_sync_rst | UI复位,高电平有效 |
| app_ecc_single_err[7:0] |
4.2 MIG核时序

当app_en和app_rdy同时为高时,地址和写命令才有效
背靠背和非背靠背
地址和命令是否连续。
如上图所示,写数据有三种情形均可以正确写入:
(1)写数据时序和写命令时序发生在同一拍;
(2)写数据时序比写命令时序提前一拍;
(3)写数据时序比写命令时序至多延迟晚两拍;
5.程序源码
//****************************************Copyright (c)***********************************//
//原子哥在线教学平台:www.yuanzige.com
//技术支持:www.openedv.com
//淘宝店铺:http://openedv.taobao.com
//关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2018-2028
//All rights reserved
//----------------------------------------------------------------------------------------
// File name: ddr3_rw_top
// Last modified Date: 2019/8/21 9:56:36
// Last Version: V1.0
// Descriptions: 读写测试实现模块
//----------------------------------------------------------------------------------------
// Created by: 正点原子
// Created date: 2019/8/21 10:55:56
// Version: V1.0
// Descriptions: The original version
//
//****************************************************************************************//
module ddr3_rw (
input ui_clk, //用户时钟
input ui_clk_sync_rst, //复位,高有效
input init_calib_complete, //DDR3初始化完成
input app_rdy, //MIG 命令接收准备好标致
input app_wdf_rdy, //MIG数据接收准备好
input app_rd_data_valid, //读数据有效
input [255:0] app_rd_data, //用户读数据
output reg [27:0] app_addr, //DDR3地址
output app_en, //MIG IP发送命令使能
output app_wdf_wren, //用户写数据使能
output app_wdf_end, //突发写当前时钟最后一个数据
output [2:0] app_cmd, //MIG IP核操作命令,读或者写
output reg [255:0] app_wdf_data, //用户写数据
output reg [1 :0] state, //读写状态
output reg [23:0] rd_addr_cnt, //用户读地址计数
output reg [23:0] wr_addr_cnt, //用户写地址计数
output reg [20:0] rd_cnt, //实际读地址标记
output reg error_flag, //读写错误标志
output reg led //读写测试结果指示灯
);
//parameter define
parameter TEST_LENGTH = 1000;
parameter L_TIME = 25'd25_000_000;
parameter IDLE = 2'd0; //空闲状态
parameter WRITE = 2'd1; //写状态
parameter WAIT = 2'd2; //读到写过度等待
parameter READ = 2'd3; //读状态
//reg define
reg [24:0] led_cnt; //led计数
//wire define
wire error; //读写错误标记
wire rst_n; //复位,低有效
//*****************************************************
//** main code
//*****************************************************
assign rst_n = ~ui_clk_sync_rst;
//读信号有效,且读出的数不是写入的数时,将错误标志位拉高
assign error = (app_rd_data_valid && (rd_cnt!=app_rd_data));
//在写状态MIG IP 命令接收和数据接收都准备好,或者在读状态命令接收准备好,此时拉高使能信号,
assign app_en = ((state == WRITE && (app_rdy && app_wdf_rdy))
||(state == READ && app_rdy)) ? 1'b1:1'b0;
//在写状态,命令接收和数据接收都准备好,此时拉高写使能
assign app_wdf_wren = (state == WRITE && (app_rdy && app_wdf_rdy)) ? 1'b1:1'b0;
//由于DDR3芯片时钟和用户时钟的分频选择4:1,突发长度为8,故两个信号相同
assign app_wdf_end = app_wdf_wren;
//处于读的时候命令值为1,其他时候命令值为0
assign app_cmd = (state == READ) ? 3'd1 :3'd0;
//DDR3读写逻辑实现
always @(posedge ui_clk or negedge rst_n) begin
if((~rst_n)||(error_flag)) begin
state <= IDLE;
app_wdf_data <= 128'd0;
wr_addr_cnt <= 24'd0;
rd_addr_cnt <= 24'd0;
app_addr <= 28'd0;
end
else if(init_calib_complete)begin //MIG IP核初始化完成
case(state)
IDLE:begin
state <= WRITE;
app_wdf_data <= 256'd0;
wr_addr_cnt <= 24'd0;
rd_addr_cnt <= 24'd0;
app_addr <= 28'd0;
end
WRITE:begin
if(wr_addr_cnt == TEST_LENGTH - 1 &&(app_rdy && app_wdf_rdy))
state <= WAIT; //写到设定的长度跳到等待状态
else if(app_rdy && app_wdf_rdy)begin //写条件满足
app_wdf_data <= app_wdf_data + 1; //写数据自加
wr_addr_cnt <= wr_addr_cnt + 1; //写地址自加
app_addr <= app_addr + 8; //DDR3 地址加8
end
else begin //写条件不满足,保持当前值
app_wdf_data <= app_wdf_data;
wr_addr_cnt <= wr_addr_cnt;
app_addr <= app_addr;
end
end
WAIT:begin
state <= READ; //下一个时钟,跳到读状态
rd_addr_cnt <= 24'd0; //读地址复位
app_addr <= 28'd0; //DDR3读从地址0开始
end
READ:begin //读到设定的地址长度
if(rd_addr_cnt == TEST_LENGTH - 1 && app_rdy)
state <= IDLE; //则跳到空闲状态
else if(app_rdy)begin //若MIG已经准备好,则开始读
rd_addr_cnt <= rd_addr_cnt + 1'd1; //用户地址每次加一
app_addr <= app_addr + 8; //DDR3地址加8
end
else begin //若MIG没准备好,则保持原值
rd_addr_cnt <= rd_addr_cnt;
app_addr <= app_addr;
end
end
default:begin
state <= IDLE;
app_wdf_data <= 256'd0;
wr_addr_cnt <= 24'd0;
rd_addr_cnt <= 24'd0;
app_addr <= 28'd0;
end
endcase
end
end
//对DDR3实际读数据个数编号计数
always @(posedge ui_clk or negedge rst_n) begin
if(~rst_n)
rd_cnt <= 0; //若计数到读写长度,且读有效,地址计数器则置0
else if(app_rd_data_valid && rd_cnt == TEST_LENGTH - 1)
rd_cnt <= 0; //其他条件只要读有效,每个时钟自增1
else if (app_rd_data_valid )
rd_cnt <= rd_cnt + 1;
end
//寄存状态标志位
always @(posedge ui_clk or negedge rst_n) begin
if(~rst_n)
error_flag <= 0;
else if(error)
error_flag <= 1;
end
//led指示效果控制
always @(posedge ui_clk or negedge rst_n) begin
if((~rst_n) || (~init_calib_complete )) begin
led_cnt <= 25'd0;
led <= 1'b0;
end
else begin
if(~error_flag) //读写测试正确
led <= 1'b1; //led灯常亮
else begin //读写测试错误
led_cnt <= led_cnt + 25'd1;
if(led_cnt == L_TIME - 1'b1) begin
led_cnt <= 25'd0;
led <= ~led; //led灯闪烁
end
end
end
end
endmodule
边栏推荐
- 批量存库架构
- ArrayList的扩容机制是如何实现的?
- Redis 三个特殊数据类型之Geospatail、Hyperloglog、bitMaps
- DG-IoT日志系统
- 谭浩强第五版第三章课后习题
- FileInputStream与BufferedInputStream有哪些区别?
- Linear algebra study notes 4-3: Solving homogeneous linear equations Ax=0, elimination method, row minimum echelon matrix RRFE
- 循环栅栏 CycleBarrier 理解到深入
- phpoffice/phpspreadsheet的使用(export篇)
- BPAAS化建设实践-基本流程篇
猜你喜欢

一周活动速递|深入浅出第8期;Meetup成都站报名进行中

IDE开发工具的使用

dgiot-dtu实现PLC数据采集上云实时查看

理想汽车×OceanBase:当造车新势力遇上数据库新势力
![[Graduation Project] Automatic gas station refueling system based on STM32 - Internet of Things, microcontroller, embedded](/img/29/ec3a7b2406d96bbf1de9b21c8a633d.png)
[Graduation Project] Automatic gas station refueling system based on STM32 - Internet of Things, microcontroller, embedded

隔离DCDC电源模块和非隔离DCDC电源模块不同之处

DIN11 FHVI大功率非隔离转换器 输入信号等比例转换放大 驱动能力加强

2021-01-29

CentOs通过yum在线安装Mysql

推荐抓包工具
随机推荐
uniapp的map地图组件介绍
RT_thread的IIC设备学习笔记
洛谷P1200 你的飞碟在这儿Your Ride Is Here
实现串口通信数据帧打包与解析,串口通信可靠传输,屡试不爽的数据封包与状态机数据解析程序
PTA L1-049 天梯赛座位分配 (20 分)
2021-01-23
PHP配置请求头允许跨域、拦截OPTIONS请求、接收POST请求参数
把back-ground-color改为以驼峰命名法则形式backGroundColor
转速信号变送模块 频率转电压电流信号变换器
字符串反转
phpoffice/phpspreadsheet的使用(export篇)
谭浩强C语言第五版课后习题第二章(复习)
DOS常用命令
端到端的基于深度学习的网络入侵检测方法
Redis 常用数据类型之 hash(哈希)
移动端预览(双指缩放移动)富文本编辑器上传的图片
Redis 事务说明与 watch 命令监控事务
下标之和的问题
什么是负载均衡
NSSCTF Round#4 Web WP