DDR2 IP系统框图
2. IP参数设置
1) 时钟设置
PLL reference clock freqency是参考输入时钟,一般由外部晶振或外部PLL输出提供
Memory clock freqency是DDR时钟,一般CYCLONE IV最快只能支持200M,根据不同的型号和BANK而不同
Controller data rate有Full和Half模式,选择Half模式后,Local interface width会增加一倍
2)选择Memory Presets
根据电路中DDR2的型号选择对应的presets,这里只重点介绍Full rate下地址的设置。
在Full rate下:
local_address is 25 bits wide
local_address[23:11] = row address[13:0]
local_address[10:9] = bank address [1:0]
local_address [8:0] = column address [9:1]
local data宽度是总线data宽度的两倍,所以IP核忽略了column的最低位
3) 设置local参数
Local-to-Memory Address Mapping: 设置地址映射,需要和上面的地址映射说明一致
Local Maximum Burst Count:设置成32,提高读写效率
3. 例化IP核
ddr2_64bit ddr2_64bit_inst (
.local_address(local_address),
.local_write_req(local_write_req),
.local_read_req(local_read_req),
.local_burstbegin(local_burstbegin),
.local_wdata(local_wdata),
.local_be(16'hffff),
.local_size(BURST_LEN),
.global_reset_n(rst_n),
.pll_ref_clk(ref_clk),
.soft_reset_n(rst_n),
.local_ready(local_ready),
.local_rdata(local_rdata),
.local_rdata_valid(local_rdata_valid),
.local_refresh_ack(),
.local_init_done(local_init_done),
.reset_phy_clk_n(),
.phy_clk(phy_clk),
.aux_full_rate_clk(),
.aux_half_rate_clk(),
.reset_request_n(),
.mem_odt(mem_odt),
.mem_cs_n(mem_cs_n),
.mem_cke(mem_cke),
.mem_addr(mem_addr),
.mem_ba(mem_ba),
.mem_ras_n(mem_ras_n),
.mem_cas_n(mem_cas_n),
.mem_we_n(mem_we_n),
.mem_dm(mem_dm),
.mem_clk(mem_clk),
.mem_clk_n(mem_clk_n),
.mem_dq(mem_dq),
.mem_dqs(mem_dqs)
);
4. 设计读写测试模块
//-----------ddr2 read and write operation---------
reg [25 :0] local_address;
reg local_burstbegin;
reg local_read_req;
reg local_write_req;
reg [127 :0] local_wdata;
reg [2:0] local_state;
reg [7:0] local_cnt;
reg [127:0] local_readdata;
parameter IDLE = 0,
IDLE0 = 1,
BURST_WRITE = 2,
IDLE1 = 3,
BURST_READ = 4,
END = 5;
always @(posedge phy_clk)
if(~rst_n)
begin
local_state <= IDLE0;
local_cnt <= 0;
end
else
case(local_state)
IDLE:
begin
if(local_init_done & local_ready)
local_state <= IDLE0;
else
local_state <= IDLE;
local_burstbegin <= 1'b0;
local_write_req <= 1'b0;
local_cnt <= 0;
local_wdata <= 128'h0;
local_address <= 26'd32;
end
IDLE0:
begin
if(local_init_done & local_ready)
local_state <= BURST_WRITE;
else
local_state <= IDLE0;
local_burstbegin <= 1'b0;
local_write_req <= 1'b0;
local_cnt <= local_cnt;
local_wdata <= local_wdata;
local_address <= local_address;
end
BURST_WRITE:
begin
if(local_cnt<=0)
local_burstbegin <= 1'b1;
else
local_burstbegin <= 1'b0;
local_write_req <= 1'b1;
local_wdata <= local_wdata + 1;
local_read_req <= 1'b0;
local_address <= 26'd32;
if(local_cnt>=(BURST_LEN-1))
begin
local_state <= IDLE1;
local_cnt <= 0;
end
else
begin
local_state <= BURST_WRITE;
local_cnt <= local_cnt + 1'b1;
end
end
IDLE1:
begin
if(local_init_done & local_ready)
local_state <= BURST_READ;
else
local_state <= IDLE1;
local_burstbegin <= 1'b0;
local_write_req <= 1'b0;
local_cnt <= local_cnt;
local_address <= 26'h0;
end
BURST_READ:
begin
local_burstbegin <= 1'b1;
local_write_req <= 1'b0;
local_read_req <= 1'b1;
local_cnt <= local_cnt;
local_state <= END;
local_address <= 26'd32;
end
END:
begin
local_burstbegin <= 0;
local_write_req <= 0;
local_read_req <= 0;
local_address <= 0;
if(local_cnt>=8'h7f)
begin
local_state <= IDLE;
local_cnt <= 0;
end
else
begin
local_state <= END;
local_cnt <= local_cnt + 1'b1;
end
if(local_rdata_valid)
local_readdata <= local_rdata;
else
local_readdata <= 0;
end
default:
begin
local_burstbegin <= 1'b0;
local_write_req <= 1'b0;
local_read_req <= 1'b0;
local_cnt <= 0;
local_state <= IDLE0;
local_address <= 26'h0;
end
endcase
5.测试结果
转载于:https://blog.51cto.com/shugenyin/1840396