一、DDR3概述
1.简介
工作电压(1.5V
),240
线接口,支持8bit
预读取,工作频率在133MHz
即可实现总线1066MHz
的总线频率。频率从400\533\667\800MHz
起跳等。芯片封装方式FBGA
。
2.接口
引脚包括:
- 电源、地、配置信号 ;
- 控制信号:
CS_N ODT
(阻抗匹配使能)CKE
(时钟使能)reset_n
(复位信号)DQM RAS\CAS\WE TDQ\TDQS DQ\DQS
- 时钟信号:差分时钟
ck_p
/ck_n
- 地址信号:
CS、BA0、BA1、BA2、A0~A9、A10
(对所有Bank预充电时拉高)、A11、A12、A13
- 数据信号:
DQ0~DQ15
3.模式寄存器
模式寄存器分为MR0
、MR1
、MR2
和MR4
。
- MR0用来存储DDR3的不同操作模式的数据:包括突发长度、读取突发种类、
CAS
长度、测试模式、DLL
复位等。 - MR1用来存储是否使能
DLL
、输出驱动长度、Rtt_Nom
、额外长度、写电平使能等。 - MR2用来存储控制更新的特性,
Rtt_WR
阻抗,和CAS
写长度。 - MR3用来控制
MPR
。
4.新增功能
-
ZQ校准功能 :
ZQ
是一个新增的引脚,接有一个240
欧姆的低公差参考电阻。 -
ODT阻抗匹配使能 :可通过读写
DDR3
内部的MR1
寄存器,来控制DDR3 SDRAM
中各个信号内部终端电阻的连接或者断开。ODT
终端电阻的电阻值RTT
可通过模式寄存器MR1
的A9,A6,A2
来进行设置,设置的真值表为: -
数据电平标准:
SSTL_15
-
**预取位宽(**Prefetch width):
8bit
-
突发长度:由于DDR3的预取为
8bit
,所以突发传输周期(Burst Length,BL
)也固定为8
,BL=4
也是常用的,DDR3为此增加了一个4bit Burst Chop
(突发突变)模式,即由一个BL=4的读取操作加上一个BL=4
的写入操作来合成一个BL=8的数据突发传输,届时可通过A12
地址线来控制这一突发模式; -
寻址时序(
Timing
):DDR3则在5~11
之间,且附加延迟(AL)的设计也有所变化,DDR3
时AL
有三种选项,分别是0、CL-1
和CL-2
。另外,DDR3还新增加了一个时序参数-写入延迟(CWD
),这一参数将根据具体的工作频率而定。 -
CAS Latency
(CL):5,6,7,8,9
时钟周期 -
tRCD
,RAS to CAS Delay
,行选通到列激活最小延时,即行选通周期; -
tRP
,RAS
预充电时间; -
tRAS
,激活预充电延时; -
CMD
,命令速率,芯片激活向存储器发送第一个数据的时间。 -
两个参考电压:在
DDR3
系统中,对于内存系统工作非常重要的参考电压信号VREF将分为两个信号,即为命令与地址信号服务的VREFCA
和为数据总线服务的VREFDQ
,这将有效地提高系统数据总线的信噪等级。 -
点对点连接(
Point-to-Point
,P2P
):大大地减轻了地址/命令/控制与数据总线的负载。面向64位构架的DDR3显然在频率和速度上拥有更多的优势,此外,由于DDR3所采用的根据温度自动自刷新、局部自刷新等其它一些功能。 -
JEDEC标准(
JESD79-3
)
规定的DDR3芯片以及内存条相关参数:
-
DQS
(数据选取脉冲),它的功能主要用来在一个时钟周期内准确的区分出每个传输周期,并便于接收方准确接收数据。
写时序
读时序
5.SDRAM与DDR速度对比:
DDR3
与DDR
一样是双倍数据传输速率。
二、DDR3接口模块IP核调用
三、DDR3读写控制
通过控制模块,实现数据突发读写,将摄像头OV5640
传过来的数据从慢时钟域到快时钟域传输数据,再从SDRAM
按帧为单位,从快时钟域到慢时钟域发送数据,通过HDMI
显示到屏幕上。
对于跨时钟域数据的传输采用异步FIFO
缓存,然后通过乒乓操作,控制读写区域。先将SDRAM
的Bank1
用于写数据,同时读取Bank3
的数据输出显示,当读写都完成后,在交换读写地址,并保证屏幕上输出的图像都是完整的一帧。
因此,对于读取侧数据没有读完之前,写侧就丢弃当前帧。文章来源:https://www.toymoban.com/news/detail-619962.html
1.读写仲裁
通过这种乒乓操作保证数据的有效传输。文章来源地址https://www.toymoban.com/news/detail-619962.html
/************************读写优先级仲裁*****************************/
//rd_flag ;//读请求标志
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
rd_flag <= 0;
end
else if(rfifo_usedw <= `RD_LT)begin
rd_flag <= 1'b1;
end
else if(rfifo_usedw > `RD_UT)begin
rd_flag <= 1'b0;
end
end
//wr_flag ;//写请求标志
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
wr_flag <= 0;
end
else if(wfifo_usedw >= `USER_BL)begin
wr_flag <= 1'b1;
end
else begin
wr_flag <= 1'b0;
end
end
//flag_sel ;//标记上一次操作
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
flag_sel <= 0;
end
else if(read2done)begin
flag_sel <= 1;
end
else if(write2done)begin
flag_sel <= 0;
end
end
//prior_flag ;//优先级标志 0:写优先级高 1:读优先级高 仲裁读、写的优先级
always @(posedge clk or negedge rst_n)begin
if(!rst_n)begin
prior_flag <= 0;
end
else if(wr_flag && (flag_sel || (~flag_sel && ~rd_flag)))begin //突发写优先级高
prior_flag <= 1'b0;
end
else if(rd_flag && (~flag_sel || (flag_sel && ~wr_flag)))begin //突发读优先级高
prior_flag <= 1'b1;
end
end
2.OV5640的数据写入DDR3的操作
/*********************** wrfifo 写数据 ************************/
//控制像素数据帧 写入 或 丢帧
always @(posedge clk_in or negedge rst_n)begin
if(~rst_n)begin
wr_data_flag <= 1'b0;
end
else if(~wr_data_flag & ~wr_finish_r[1] & din_sop)begin//可以向wrfifo写数据
wr_data_flag <= 1'b1;
end
else if(wr_data_flag & din_eop)begin//不可以向wrfifo写入数据
wr_data_flag <= 1'b0;
end
end
always @(posedge clk_in or negedge rst_n)begin //把wr_finish从wrfifo的读侧同步到写侧
if(~rst_n)begin
wr_finish_r <= 0;
end
else begin
wr_finish_r <= {wr_finish_r[0],wr_finish};
end
end
/****************************************************************/
//burst_write
always @(posedge clk or negedge rst_n)begin
if(~rst_n)begin
burst_write <= 1'b0;
end
else begin
burst_write <= idle2write;
end
end
//burst_read
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
burst_read <= 1'b0;
end
else begin
burst_read <= idle2read;
end
end
//avl_read
always @(posedge clk or negedge rst_n)begin
if(~rst_n)begin
avl_read <= 1'b0;
end
else if(idle2read)begin
avl_read <= 1'b1;
end
else if(avl_read & avl_ready)begin
avl_read <= 1'b0;
end
end
always @(posedge clk or negedge rst_n)begin
if(rst_n==1'b0)begin
avl_write <= 1'b0;
end
else if(idle2write)begin
avl_write <= 1'b1;
end
else if(write2done)begin
avl_write <= 1'b0;
end
end
//rd_data rd_data_vld 输出给hdmi接口
always @(posedge clk_out or negedge rst_n)begin
if(~rst_n)begin
rd_data <= 0;
rd_data_vld <= 1'b0;
end
else begin
rd_data <= rfifo_q;
rd_data_vld <= rfifo_rdreq;
end
end
wrfifo u_wr_fifo(
/*input */.aclr (~rst_n ),
/*input [129:0] */.data (wfifo_wrdata ),
/*input */.rdclk (clk ),
/*input */.rdreq (wfifo_rdreq ),
/*input */.wrclk (clk_in ),
/*input */.wrreq (wfifo_wrreq ),
/*output [129:0] */.q (wfifo_q ),
/*output */.rdempty (wfifo_empty ),
/*output [8:0] */.rdusedw (wfifo_usedw ),
/*output */.wrfull (wfifo_full )
);
assign wfifo_wrdata = {din_eop,din_sop,din};
assign wfifo_wrreq = ~wfifo_full & din_vld & ((~wr_finish_r[1] & din_sop) | wr_data_flag);
assign wfifo_rdreq = state_c == WRITE && avl_ready;
3.地址设计
// wr_addr rd_addr
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
wr_addr <= 0;
end
else if(add_wr_addr) begin
if(end_wr_addr)
wr_addr <= 0;
else
wr_addr <= wr_addr + (`USER_BL << 4);
end
end
assign add_wr_addr = write2done;
assign end_wr_addr = add_wr_addr && wr_addr == (`BURST_MAX << 1)- (`USER_BL << 4);
always @(posedge clk or negedge rst_n) begin
if (rst_n==0) begin
rd_addr <= 0;
end
else if(add_rd_addr) begin
if(end_rd_addr)
rd_addr <= 0;
else
rd_addr <= rd_addr + (`USER_BL << 4);
end
end
assign add_rd_addr = read2done;
assign end_rd_addr = add_rd_addr && rd_addr == (`BURST_MAX << 1)- (`USER_BL << 4);
//wr_finish 一帧数据全部写到SDRAM
always @(posedge clk or negedge rst_n)begin
if(~rst_n)begin
wr_finish <= 1'b0;
end
else if(~wr_finish & wfifo_q[129])begin //写完 从wrfifo读出eop
wr_finish <= 1'b1;
end
else if(wr_finish && end_rd_addr)begin //读完
wr_finish <= 1'b0;
end
end
4.乒乓操作
//change_bank ;//切换bank
always @(posedge clk or negedge rst_n)begin
if(~rst_n)begin
change_bank <= 1'b0;
end
else begin
change_bank <= wr_finish && end_rd_addr;
end
end
5.读侧FIFO
rdfifo u_rd_fifo(
/*input */.aclr (~rst_n ),
/*input [127:0] */.data (rfifo_wrdata ),
/*input */.rdclk (clk_out ),
/*input */.rdreq (rfifo_rdreq ),
/*input */.wrclk (clk ),
/*input */.wrreq (rfifo_wrreq ),
/*output [15:0] */.q (rfifo_q ),
/*output */.rdempty(rfifo_empty ),
/*output */.wrfull (rfifo_full ),
/*output [8:0] */.wrusedw(rfifo_usedw )
);
assign rfifo_wrdata = avl_rdata;
assign rfifo_rdreq = ~rfifo_empty & rd_req;
assign rfifo_wrreq = avl_rdata_valid & ~rfifo_full;
6.ddr3_controller模块
assign initial_done = rst_n & local_init_done & local_cal_success;
//模块例化
ddr3_rw_ctrl u_ctrl(
/*input */.clk (afi_clk ),//ddr3侧时钟
/*input */.clk_in (clk_in ),//摄像头数据输入侧时钟
/*input */.clk_out (clk_out ),//HDMI数据输出侧时钟
/*input */.rst_n (rst_n ),
//user interface
/*input */.rd_req (rd_req ),//hdmi_driver读取数据请求
/*input [127:0] */.din (din ),//摄像头写入mem的数据
/*inpput */.din_sop (din_sop ),
/*input */.din_eop (din_eop ),
/*input */.din_vld (din_vld ),
/*output [15:0] */.dout (dout ),//发送到显示器的数据
/*output */.dout_vld (dout_vld ),
//ddr3_interface interface
/*output */.avl_ready (avl_ready ),//avl.waitrequest_n
/*input */.avl_burstbegin (avl_burstbegin ),//.beginbursttransfer
/*input [25:0] */.avl_addr (avl_addr ),//.address
/*output */.avl_rdata_valid (avl_rdata_valid ),//.readdatavalid
/*output [127:0] */.avl_rdata (avl_rdata ),//.readdata
/*input [127:0] */.avl_wdata (avl_wdata ),//.writedata
/*input [15:0] */.avl_be (avl_byteenable ),//.byteenable
/*input */.avl_read_req (avl_read_req ),//.read
/*input */.avl_write_req (avl_write_req ),//.write
/*input [8:0] */.avl_size (avl_size ) //.burstcount
);
ddr3_interface u_dddr3_intf(
/*input wire */.pll_ref_clk (clk ),//给ip内部PLL的参考时钟
/*input wire */.global_reset_n (rst_n ),//global_reset.reset_n
/*input wire */.soft_reset_n (1'b1 ),//soft_reset.reset_n
/*output wire */.afi_clk (afi_clk ),//afi_clk.clk
/*output wire */.afi_half_clk ( ),//afi_half_clk.clk
/*output wire */.afi_reset_n ( ),//afi_reset.reset_n
/*output wire */.afi_reset_export_n ( ),//afi_reset_export.
/*output wire [14:0] */.mem_a (mem_addr ),//memory.mem_a
/*output wire [2:0] */.mem_ba (mem_bank ),//.mem_ba
/*output wire [0:0] */.mem_ck (mem_ck_p ),//.mem_ck
/*output wire [0:0] */.mem_ck_n (mem_ck_n ),//.mem_ck_n
/*output wire [0:0] */.mem_cke (mem_cke ),//.mem_cke
/*output wire [0:0] */.mem_cs_n (mem_cs_n ),//.mem_cs_n
/*output wire [3:0] */.mem_dm (mem_dqm ),//.mem_dm
/*output wire [0:0] */.mem_ras_n (mem_rasn ),//.mem_ras_n
/*output wire [0:0] */.mem_cas_n (mem_casn ),//.mem_cas_n
/*output wire [0:0] */.mem_we_n (mem_wen ),//.mem_we_n
/*output wire */.mem_reset_n (mem_rest_n ),//.mem_reset_n
/*inout wire [31:0] */.mem_dq (mem_dq ),//.mem_dq
/*inout wire [3:0] */.mem_dqs (mem_dqs_p ),//.mem_dqs
/*inout wire [3:0] */.mem_dqs_n (mem_dqs_n ),//.mem_dqs_n
/*output wire [0:0] */.mem_odt (mem_odt ),//.mem_odt
/*output wire */.avl_ready (avl_ready ),//avl.waitrequest_n
/*input wire */.avl_burstbegin (avl_burstbegin ),//.beginbursttransfer
/*input wire [25:0] */.avl_addr (avl_addr ),//.address
/*output wire */.avl_rdata_valid (avl_rdata_valid ),//.readdatavalid
/*output wire [127:0] */.avl_rdata (avl_rdata ),//.readdata
/*input wire [127:0] */.avl_wdata (avl_wdata ),//.writedata
/*input wire [15:0] */.avl_be (avl_byteenable ),//.byteenable
/*input wire */.avl_read_req (avl_read_req ),//.read
/*input wire */.avl_write_req (avl_write_req ),//.write
/*input wire [8:0] */.avl_size (avl_size ),//.burstcount
/*output wire */.local_init_done (local_init_done ),//local_init_done
/*output wire */.local_cal_success (local_cal_success ),//local_cal_success
/*output wire */.local_cal_fail (local_cal_fail ),//.local_cal_fail
/*input wire */.oct_rzqin (mem_rzq ) //oct.rzqin
//PLL未设置sharing模式,所以这些信号未使能
//output wire pll_mem_clk, //pll_sharing.pll_mem_clk
//output wire pll_write_clk, //.pll_write_clk
//output wire pll_locked, //.pll_locked
//output wire pll_write_clk_pre_phy_clk, //.pll_write_clk_pre_phy_clk
//output wire pll_addr_cmd_clk, //.pll_addr_cmd_clk
//output wire pll_avl_clk, //.pll_avl_clk
//output wire pll_config_clk, //.pll_config_clk
//output wire pll_mem_phy_clk, //.pll_mem_phy_clk
//output wire afi_phy_clk, //.afi_phy_clk
//output wire pll_avl_phy_clk //.pll_avl_phy_clk
);
到了这里,关于DDR3基础和数据读取的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!