DDR2接口主要实现用户数据和实际物理接口之间的连接,实现对大容量数据进行高速缓存。处理高低速传输问题。
首先要了解DDR2工作原理,熟悉所连接的内存颗粒说明书了解适用范围,产生适合硬件的DDR2 IP核源文件,查阅DOC下的内核说明书,了解内核内容结构,然后做出相应的改动,如时钟匹配,需匹配为生成核时工作时钟,针对用户的接口除了时钟之外,主要有三部分接口组成,它们分别是地址命令产生器,写数据FIFO, 读数据FIFO接口。地址产生器主要给你选定的突发长度类型产生相应的地址偏移,例如以4的突发长度读写,在写数据时一个CLK 内DDR2根据时钟边沿跳变次数会产生两次写数据,以长度为4的突发写,就需要给一次地址,DDR2控制器会自动写4次数据,地址偏移依用户给出的地址依次累加(基址+1),所以用户控制写数据,只需每两个CLK给出一个至少偏移为4的地址,写数据如下图一所示,具体详情见ip核文件下DOC里说明书。
图一
DDR2读数据,则不同于DDR2写数据,需要用户在每个CLK都要给出ADDR地址,读取数据地址还是以突发读写长度为偏移,每次加4,具体的时序过程如下图二所示,图中给出他以4为长度突发读连续读出16次数据,地址输入占用4个CLK, 读数据需要至少8个clk周期。
具体实现过程可以参考ip核列化程序,app应用部分example下的ddr2_tb_test等程序及仿真文件观察波形可看出数据传输过程。
以下是一个RGB信号存储的简单地址产生器程序供参考。
//****************************************************************
`timescale 1ns/1ps
module ddr2_tb_addr_gen #
(
// the test module for actual values.
parameter BANK_WIDTH = 3,
parameter COL_WIDTH = 10,
parameter ROW_WIDTH = 14,
parameterone_rgb_cnt=24 //8:0_4_8 28<*3<32//120000-4 //rgb zhong ,R de di zhi fan wen ,EXP: (800*600*8)/32
)
(
input clk,
input rst,
// input rst1,
input addr_ren,
input addr_gen,
input addr_ben,
input wr_addr_en,
//output reg [2:0] app_af_cmd,
output reg [30:0] app_af_addr,
output reg app_af_wren
);
localparam r_star_ad=0;
localparam g_star_ad=41943040;
localparam b_star_ad=134217700;
reg wr_addr_en_r1;
// reg [2:0] af_cmd_r;
reg [30:0] af_addr_r;
reg af_wren_r;
// wire [15:0] ramb_addr;
// wire [35:0] ramb_dout;
reg rst_r
/* synthesis syn_preserve = 1*/;
reg rst_r1
/* synthesis syn_maxfan = 10*/;
reg [30:0] wr_addr_cnt;
reg wr_addr_en_r0;
reg [30:0] wr_addr_allcnt;
// INIP_OO: read 1
// INIP_OO: write 0
//***************************************************************************
// assign ramb_addr = {5'b00000, wr_addr_cnt,5'b00000};
// register backend enables / FIFO enables
// write enable for Command/Address FIFO is generated 2 CC afterWR_ADDR_EN
// (takes 2 CC to come out of test RAM)
always @(posedge clk)
if (rst ) begin
app_af_wren <= 1'b0;
wr_addr_en_r0 <= 1'b0;
wr_addr_en_r1 <= 1'b0;
af_wren_r <= 1'b0;
end else begin
app_af_wren <= wr_addr_en;
end
// address input for RAM
always @ (posedge clk)
if (rst)
begin
wr_addr_cnt <= 0; //8 'h0000_0000;
wr_addr_allcnt<=0; // 9 'h0_0000_0000;
end
else //if (wr_addr_en)
if (wr_addr_en && addr_ren&& !addr_gen && !addr_ben)
begin
if(wr_addr_cnt<one_rgb_cnt) //800*600 R 8 BIT 48_0000*8 //0-R
begin
app_af_addr<=wr_addr_cnt+r_star_ad;
wr_addr_cnt <= wr_addr_cnt + 4;
end
else
begin
wr_addr_cnt <=0;
app_af_addr<=wr_addr_cnt+r_star_ad;
end
end
else
if (wr_addr_en && !addr_ren&& addr_gen && !addr_ben)
begin
if(wr_addr_cnt<one_rgb_cnt) //40-79
begin
app_af_addr<=wr_addr_cnt+g_star_ad;
wr_addr_cnt <=wr_addr_cnt + 4; 41943040; // R-2R
end
else
begin
wr_addr_cnt <=0;
app_af_addr<=wr_addr_cnt+g_star_ad;
end
end
else
if(wr_addr_en && !addr_ren && !addr_gen && addr_ben)
begin
if (wr_addr_cnt<one_rgb_cnt)//80-119
begin
app_af_addr<=wr_addr_cnt+b_star_ad;
wr_addr_cnt <= wr_addr_cnt+ 4; //83886080; //2R-3R
end
else
begin
wr_addr_cnt <=0;
app_af_addr<=wr_addr_cnt+b_star_ad;
end
end
else
app_af_addr<=31'bx;
endmodule