秦韵FPGA 转载或原创(十) -------Intel FPGA
DDR2 ip信号简介
wire clk_x1;
QY_DDR2_ip u_QY_DDR2_ip(
.pll_ref_clk (clk_x1 ),
.phy_clk (phy_clk ),
.global_reset_n (global_reset_n ),
.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 (local_be ),
.local_size (local_size ),
.soft_reset_n (soft_reset_n ),
.local_ready (local_ready ),
.local_rdata (local_rdata ),
.local_rdata_valid (local_rdata_valid ),
.local_init_done (local_init_done ),
.reset_phy_clk_n (reset_phy_clk_n ),
.mem_odt (qy_mem_odt ),
.mem_cs_n (qy_mem_cs_n ),
.mem_cke (qy_mem_cke ),
.mem_addr (qy_mem_addr ),
.mem_ba (qy_mem_ba ),
.mem_ras_n (qy_mem_ras_n ),
.mem_cas_n (qy_mem_cas_n ),
.mem_we_n (qy_mem_we_n ),
.mem_dm (qy_mem_dm ),
.mem_clk (qy_mem_clk ),
.mem_clk_n (qy_mem_clk_n ),
.mem_dq (qy_mem_dq ),
.mem_dqs (qy_mem_dqs )
);`
- 简单的用户端口介绍,使用这些逻辑就可以操作ddr2 ip,该ip采用的半速率模式,有兴趣的可以测试full-rate模式。
DDR2 ip控制逻辑思路简介
- 配置pll,产生50Mhz信号clk_x1,和locked 的信号,global_reset_n = reset_n & leocked;
- 完成读写逻辑,在写代码之前,大概的画出代码的逻辑框架,包括状态机的状态图,简单的介绍一下读写ddr2的状态,在真正的逻辑开始之前,首先要做的是等待ddr2 ip 初始化完成,即local_init_done = 1’b1;
- 完成了初始化,就进入了仲裁状态,即在local_ready信号为高的情况下,等待写请求信号,或者读请求信号,进入写请求状态或者读请求状态,为第二个状态。
- 直接从请求状态进入写数据或者读数据状态,完成数据的写或者读,这里就基本完成了读或者写,可以加一个或者两个end状态,也可以不加,直接进入仲裁状态,等待下一次请求。
- 到这里ddr2 ip的控制逻辑就完成了,有需要的就在封装一层,将控制接口封装成类fifo接口,容易控制,也容易理解。
DDR2 ip代码浏览
parameter QY_INIT = 4'h0;
parameter QY_ARBIR = 4'h1;
parameter QY_WRITE_REQ = 4'h2;
parameter QY_WRITE = 4'h3;
parameter QY_WRITE_END = 4'h4;
parameter QY_READ_REQ = 4'h5;
parameter QY_READ = 4'h6;
parameter QY_READ_END = 4'h7;
parameter QY_OVER = 4'H8;
reg [3:0] qy_state_cs;
reg [3:0] qy_state_ns;
reg [3:0] Write_count;
reg [3:0] Read_count;
always@(posedge clk or negedge reset_n)
if(!reset_n)
qy_state_cs <= QY_INIT;
else
qy_state_cs <= qy_state_ns;
always@(*) begin
case(qy_state_cs)
QY_INIT : if(local_init_done)
qy_state_ns = QY_ARBIR;
else
qy_state_ns = QY_INIT;
QY_ARBIR : if(qy_write_req && local_ready)
qy_state_ns = QY_WRITE_REQ;
else if(qy_read_req && local_ready)
qy_state_ns = QY_READ_REQ;
else
qy_state_ns = QY_ARBIR;
QY_WRITE_REQ : qy_state_ns = QY_WRITE;
QY_WRITE : if(Write_count < local_size)
qy_state_ns = QY_WRITE;
else
qy_state_ns = QY_WRITE_END;
QY_WRITE_END : qy_state_ns = QY_ARBIR;
QY_READ_REQ : qy_state_ns = QY_READ;
QY_READ : if(Read_count < local_size)
qy_state_ns = QY_READ;
else
qy_state_ns = QY_READ_END;
QY_READ_END : qy_state_ns = QY_ARBIR;
default : qy_state_ns = QY_INIT;
endcase
end
always@(posedge clk or negedge reset_n)
if(!reset_n) begin
local_write_req <= 1'b0;
local_read_req <= 1'b0;
local_burstbegin <= 1'b0;
local_address <= 24'd0;
Write_count <= 4'd0;
Read_count <= 4'h0;
local_wdata <= 64'd0;
qy_read_data <= 64'd0;
qy_write_brustend <= 1'b0;
qy_read_brustend <= 1'b0;
end
else if(qy_state_cs == QY_INIT)begin
local_write_req <= 1'b0;
local_read_req <= 1'b0;
local_burstbegin <= 1'b0;
local_address <= 24'd0;
Write_count <= 4'd0;
Read_count <= 4'h0;
end
else if(qy_state_cs == QY_WRITE_REQ && local_ready) begin
local_write_req <= 1'b1;
local_read_req <= 1'b0;
local_burstbegin <= 1'b1;
local_address <= qy_write_init_addr;
Write_count <= 4'd1;
Read_count <= 4'h0;
end
else if(qy_state_cs == QY_WRITE && local_ready ) begin
local_write_req <= 1'b1;
local_burstbegin <= 1'b0;
local_wdata <= qy_write_data;
local_address <= local_address + local_size;
Write_count <= Write_count + 1'b1;
end
else if(qy_state_cs == QY_WRITE_END ) begin
local_write_req <= 1'b0;
local_burstbegin <= 1'b0;
local_wdata <= local_wdata;
local_address <= 25'd0 ;
Write_count <= 4'd0;
qy_write_brustend <= 1'b1;
qy_read_brustend <= 1'b0;
end
else if(qy_state_cs == QY_READ_REQ && local_ready) begin
local_write_req <= 1'b0;
local_read_req <= 1'b1;
local_burstbegin <= 1'b1;
local_address <= qy_read_init_addr;
Write_count <= 4'd0;
Read_count <= 4'h1;
end
else if(qy_state_cs == QY_READ && local_ready ) begin
local_read_req <= 1'b1;
local_burstbegin <= 1'b0;
if(local_rdata_valid) begin
local_address <= local_address + local_size;
Read_count <= Read_count + 1'b1;
qy_read_data <= local_rdata;
end
else begin
local_address <= 25'd0;
Read_count <= 4'd1;
qy_read_data <= 63'd0;
end
end
else if(qy_state_cs == QY_READ_END ) begin
local_write_req <= 1'b0;
local_burstbegin <= 1'b0;
local_read_req <= 1'b0;
local_address <= 25'd0 ;
Read_count <= 4'h0;
qy_write_brustend <= 1'b0;
qy_read_brustend <= 1'b1;
end
else begin
qy_write_brustend <= 1'b0;
qy_read_brustend <= 1'b0;
end