DDR4读写控制模块
module ddr4_control#(
parameter MEM_DATA_BITS = 512 ,
parameter ADDR_BITS = 26 ,
parameter BUSRT_BITS = 10 ,//突发的位宽长度
parameter BURST_LEN = 5
)
(
input i_sys_clk ,
input i_sys_rst ,
input i_wr_data_rdy ,
output reg [MEM_DATA_BITS-1:0] o_wr_data ,
output reg o_wr_ddr4_req ,
input i_rd_data_vaild ,
input [MEM_DATA_BITS-1:0] i_rd_ddr4_data ,
output reg o_rd_ddr4_req ,
output [BUSRT_BITS-1:0] o_wr_burst_length ,
output [BUSRT_BITS-1:0] o_rd_burst_length ,
output reg [ADDR_BITS-1:0] o_wr_base_ddr4_addr ,
output reg [ADDR_BITS-1:0] o_rd_base_ddr4_addr ,
input i_wr_finished ,
input i_rd_finished
);
localparam IDLE = 3'b000 ;
localparam WRITE = 3'b001 ;
localparam READ = 3'b011 ;
reg [11:0] wr_data_count ;
reg [11:0] rd_data_count ;
reg [2:0] current_state ;
reg [2:0] next_state ;
assign o_wr_burst_length = BURST_LEN;
assign o_rd_burst_length = BURST_LEN;
always @(posedge i_sys_clk or posedge i_sys_rst) begin
if(i_sys_rst) begin
current_state <= IDLE;
end
else begin
current_state <= next_state;
end
end
always @(*) begin
case(current_state)
IDLE: begin
next_state = WRITE;
end
WRITE: begin
if(i_wr_finished) begin
next_state = READ;
end
else begin
next_state = WRITE;
end
end
READ: begin
if(i_rd_finished) begin
next_state = IDLE;
end
else begin
next_state = READ;
end
end
default:begin
next_state = IDLE;
end
endcase
end
always @(posedge i_sys_clk or posedge i_sys_rst) begin
if(i_sys_rst) begin
o_wr_ddr4_req <= 1'd0;
o_rd_ddr4_req <= 1'd0;
end
else if( current_state == IDLE || (current_state == READ && i_rd_finished))begin
o_wr_ddr4_req <= 1'd1;
o_rd_ddr4_req <= 1'd0;
end
else if( current_state == WRITE && i_wr_finished)begin
o_wr_ddr4_req <= 1'd0;
o_rd_ddr4_req <= 1'd1;
end
else begin
o_wr_ddr4_req <= o_wr_ddr4_req;
o_rd_ddr4_req <= o_rd_ddr4_req;
end
end
always @(posedge i_sys_clk or posedge i_sys_rst) begin
if(i_sys_rst) begin
wr_data_count <= 12'd0;
end
else if(current_state == WRITE && wr_data_count == BURST_LEN - 12'd1 || current_state == IDLE ) begin
wr_data_count <= 12'd0;
end
else if(current_state == WRITE && i_wr_data_rdy ) begin
wr_data_count <= wr_data_count + 12'd1;
end
else begin
wr_data_count <= wr_data_count;
end
end
always @(posedge i_sys_clk or posedge i_sys_rst) begin
if(i_sys_rst) begin
o_wr_data <= {MEM_DATA_BITS{1'd0}};
end
else if(current_state == WRITE && i_wr_data_rdy ) begin
o_wr_data <= o_wr_data + 'd10;
end
else begin
wr_data_count <= wr_data_count;
end
end
always @(posedge i_sys_clk or posedge i_sys_rst) begin
if(i_sys_rst) begin
rd_data_count <= 12'd0;
end
else if(current_state == READ && rd_data_count == BURST_LEN - 12'd1 || current_state == IDLE ) begin
rd_data_count <= 12'd0;
end
else if(current_state == READ && i_rd_data_vaild ) begin
rd_data_count <= rd_data_count + 12'd1;
end
else begin
rd_data_count <= rd_data_count;
end
end
always @(posedge i_sys_clk or posedge i_sys_rst) begin
if(i_sys_rst) begin
o_rd_base_ddr4_addr <= {ADDR_BITS{1'd0}};
o_wr_base_ddr4_addr <= {ADDR_BITS{1'd0}};
end
else if(i_rd_finished ) begin
o_rd_base_ddr4_addr <= o_rd_base_ddr4_addr + BURST_LEN;
o_wr_base_ddr4_addr <= o_wr_base_ddr4_addr + BURST_LEN;
end
else begin
o_rd_base_ddr4_addr <= o_rd_base_ddr4_addr;
o_wr_base_ddr4_addr <= o_wr_base_ddr4_addr;
end
end
endmodule
DDR4 app接口控制
module ddr4_app
#(
parameter ADDR_BITS = 26 ,
parameter MEM_DATA_BITS = 512 ,
parameter APP_ADDR_BITS = 29 ,
parameter BURST_BITS = 10 //突发长度的位宽
)
(
input i_sys_clk ,
input i_sys_rst ,
output o_wr_data_rdy ,
input [MEM_DATA_BITS-1:0] i_wr_data ,
input i_wr_ddr4_req ,
output o_rd_data_vaild ,
output [MEM_DATA_BITS-1:0] o_rd_ddr4_data ,
input i_rd_ddr4_req ,
input [BURST_BITS-1:0] i_wr_burst_length ,
input [BURST_BITS-1:0] i_rd_burst_length ,
input [BURST_BITS-1:0] i_wr_base_ddr4_addr ,
input [BURST_BITS-1:0] i_rd_base_ddr4_addr ,
output reg o_wr_finished ,
output reg o_rd_finished ,
//DDR phy接口的信号
output o_c0_init_calib_complete ,
input i_c0_sys_clk_p ,
input i_c0_sys_clk_n ,
output o_c0_ddr4_act_n ,
output [16:0] o_c0_ddr4_adr ,
output [1:0] o_c0_ddr4_ba ,
output [0:0] o_c0_ddr4_bg ,
output [0:0] o_c0_ddr4_cke ,
output [0:0] o_c0_ddr4_odt ,
output [0:0] o_c0_ddr4_cs_n ,
output [0:0] o_c0_ddr4_ck_t ,
output [0:0] o_c0_ddr4_ck_c ,
output o_c0_ddr4_reset_n ,
inout [7:0] io_c0_ddr4_dm_dbi_n ,
inout [63:0] io_c0_ddr4_dq ,
inout [7:0] io_c0_ddr4_dqs_t ,
inout [7:0] io_c0_ddr4_dqs_c ,
output o_ddr4_clk ,
output o_ddr4_rst
);
localparam IDLE = 3'b000 ;
localparam WRITE = 3'b001 ;
localparam READ = 3'b011 ;
localparam READ_WAIT = 3'b010 ;
wire [APP_ADDR_BITS-1:0] app_addr ;
wire [2:0] app_cmd ;
wire app_en ;
wire [MEM_DATA_BITS-1:0] app_wdf_data ;
wire app_wdf_end ;
wire [MEM_DATA_BITS/8-1:0] app_wdf_mask ;
wire app_wdf_wren ;
wire [MEM_DATA_BITS-1:0] app_rd_data ;
wire app_rd_data_end ;
wire app_rd_data_valid ;
wire app_rdy ;
wire app_wdf_rdy ;
wire c0_ddr4_ui_clk ;
wire c0_ddr4_ui_clk_sync_rst ;
wire [BURST_BITS + 12 -1 : 0 ] wr_burst_addr ;// burst_addr = base_addr + offset_addr
wire [BURST_BITS + 12 -1 : 0 ] rd_burst_addr ;
reg [2:0] app_cmd_r ;
reg app_en_r ;
// reg [MEM_DATA_BITS/8-1:0] app_wdf_mask_r ;
reg app_wdf_wren_r ;
reg [MEM_DATA_BITS-1:0] app_rd_data_r ;
reg app_rd_data_end_r ;
reg [MEM_DATA_BITS-1:0] app_wdf_data_r ;
// reg app_rd_data_valid_r ;
// reg app_rdy_r ;
// reg app_wdf_rdy_r ;
reg [2:0] current_state ;
reg [2:0] next_state ;
reg [11:0] wr_data_count ;
reg [11:0] wr_addr_count ;
reg [11:0] rd_data_count ;
reg [11:0] rd_addr_count ;
//******************************************assign*****************************************************
// assign o_ddr4_clk = c0_ddr4_ui_clk;
// assign o_ddr4_rst = c0_ddr4_ui_clk_sync_rst;
assign wr_burst_addr = (wr_addr_count + i_wr_base_ddr4_addr) << 3;
assign rd_burst_addr = (rd_addr_count + i_rd_base_ddr4_addr) << 3;
assign app_cmd = app_cmd_r;
assign app_en = app_en_r;
assign o_wr_data_rdy = app_wdf_rdy && (current_state == WRITE)&&app_en;
assign o_rd_data_vaild = app_rd_data_valid;
assign o_rd_ddr4_data = app_rd_data;
// assign app_wdf_wren = app_en & app_wdf_rdy;
assign app_wdf_wren = app_wdf_wren_r;
assign app_addr = (current_state == WRITE) ? wr_burst_addr:
(current_state == READ) ? rd_burst_addr: {APP_ADDR_BITS{1'd0}};
assign app_wdf_data = i_wr_data;
assign app_wdf_mask = {MEM_DATA_BITS/8{1'b0}};
assign app_wdf_end = app_wdf_wren;
//*****************************************************************************************************
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
app_wdf_data_r <= {MEM_DATA_BITS{1'd0}};
end
else begin
app_wdf_data_r <= i_wr_data;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
current_state <= IDLE;
end
else begin
current_state <= next_state;
end
end
always @(*)begin
if (o_c0_init_calib_complete)
case(current_state)
IDLE: begin
if (i_wr_ddr4_req) begin
next_state = WRITE;
end
else if (i_rd_ddr4_req) begin
next_state = READ;
end
else begin
next_state = IDLE;
end
end
WRITE: begin
if(o_wr_finished) begin
next_state = IDLE;
end
else begin
next_state = WRITE;
end
end
READ: begin
if(rd_addr_count == i_rd_burst_length - 'd1 ) begin
next_state = READ_WAIT;
end
else if(o_rd_finished) begin
next_state = IDLE;
end
else begin
next_state = READ;
end
end
READ_WAIT: begin
if (o_rd_finished) begin
next_state = IDLE;
end
else begin
next_state = READ_WAIT;
end
end
default:begin
next_state = IDLE;
end
endcase
else begin
next_state = IDLE;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
app_cmd_r <= 3'd0;
end
else if (current_state == WRITE )begin
app_cmd_r <= 3'd0;
end
else if (current_state == READ )begin
app_cmd_r <= 3'd1;
end
else begin
app_cmd_r <= app_cmd_r;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
app_wdf_wren_r <= 1'd0;
end
// else if ((current_state == WRITE && o_wr_finished) ||(current_state == READ &&o_rd_finished ) ) begin
else if ((current_state == WRITE && o_wr_finished)) begin
app_wdf_wren_r <= 1'd0;
end
else if ((current_state == WRITE) && app_rdy && app_wdf_rdy )begin
app_wdf_wren_r <= 1'd1;
end
else begin
app_wdf_wren_r <= app_wdf_wren_r;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
app_en_r <= 1'd0;
end
// else if ((current_state == WRITE && o_wr_finished) ||(current_state == READ &&o_rd_finished ) ) begin
else if ((current_state == WRITE && o_wr_finished) || rd_addr_count == i_rd_burst_length - 1) begin
app_en_r <= 1'd0;
end
else if ((current_state == WRITE || current_state == READ) && app_rdy )begin
app_en_r <= 1'd1;
end
else begin
app_en_r <= app_en_r;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
wr_data_count <= 12'd0;
end
else if (current_state == WRITE && wr_data_count == i_wr_burst_length - 12'd1 )begin
wr_data_count <= 12'd0;
end
else if (current_state == WRITE && app_rdy && app_wdf_rdy && app_en_r) begin
wr_data_count <= wr_data_count + 12'd1;
end
else begin
wr_data_count <= wr_data_count;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
wr_addr_count <= 12'd0;
end
else if (current_state == WRITE && wr_data_count == i_wr_burst_length - 12'd1 )begin
wr_addr_count <= 12'd0;
end
else if (current_state == WRITE && app_rdy && app_wdf_rdy && app_en_r) begin
wr_addr_count <= wr_addr_count + 12'd1;
end
else begin
wr_addr_count <= wr_addr_count;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
o_wr_finished <= 1'd0;
end
else if (current_state == WRITE && (wr_data_count == i_wr_burst_length - 12'd2 ))begin
o_wr_finished <= 1'd1;
end
else begin
o_wr_finished <= 1'd0;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
rd_addr_count <= 12'd0;
end
else if (current_state == READ &&rd_addr_count == i_rd_burst_length - 'd1 )begin
rd_addr_count <= 12'd0;
end
else if (current_state == READ && app_rdy && app_en_r) begin
rd_addr_count <= rd_addr_count + 12'd1;
end
else begin
rd_addr_count <= rd_addr_count;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
rd_data_count <= 12'd0;
end
else if ((rd_data_count == i_rd_burst_length -1'd1) && app_rd_data_valid) begin
rd_data_count <= 12'd0;
end
else if ((current_state == READ || current_state == READ_WAIT) && app_rd_data_valid )begin
rd_data_count <= rd_data_count + 12'd1;
end
else begin
rd_data_count <= rd_data_count;
end
end
always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
if(o_ddr4_rst) begin
o_rd_finished <= 1'd0;
end
else if (( current_state == READ || current_state == READ_WAIT) && (rd_data_count == i_rd_burst_length - 12'd1 ) && app_rd_data_valid)begin
o_rd_finished <= 1'd1;
end
else begin
o_rd_finished <= 1'd0;
end
end
ddr4_0 u_ddr4
(
.sys_rst (i_sys_rst ),
.c0_sys_clk_p (i_c0_sys_clk_p ),
.c0_sys_clk_n (i_c0_sys_clk_n ),
.c0_init_calib_complete (o_c0_init_calib_complete ),
.c0_ddr4_act_n (o_c0_ddr4_act_n ),
.c0_ddr4_adr (o_c0_ddr4_adr ),
.c0_ddr4_ba (o_c0_ddr4_ba ),
.c0_ddr4_bg (o_c0_ddr4_bg ),
.c0_ddr4_cke (o_c0_ddr4_cke ),
.c0_ddr4_odt (o_c0_ddr4_odt ),
.c0_ddr4_cs_n (o_c0_ddr4_cs_n ),
.c0_ddr4_ck_t (o_c0_ddr4_ck_t ),
.c0_ddr4_ck_c (o_c0_ddr4_ck_c ),
.c0_ddr4_reset_n (o_c0_ddr4_reset_n ),
.c0_ddr4_dm_dbi_n (io_c0_ddr4_dm_dbi_n),
.c0_ddr4_dq (io_c0_ddr4_dq ),
.c0_ddr4_dqs_c (io_c0_ddr4_dqs_c ),
.c0_ddr4_dqs_t (io_c0_ddr4_dqs_t ),
.c0_ddr4_ui_clk (o_ddr4_clk ),
.c0_ddr4_ui_clk_sync_rst (o_ddr4_rst ),
.dbg_clk (dbg_clk ),
.c0_ddr4_app_addr (app_addr ),
.c0_ddr4_app_cmd (app_cmd ),
.c0_ddr4_app_en (app_en ),
.c0_ddr4_app_hi_pri (1'b0 ),
.c0_ddr4_app_wdf_data (app_wdf_data ),
.c0_ddr4_app_wdf_end (app_wdf_end ),
.c0_ddr4_app_wdf_mask (app_wdf_mask ),
.c0_ddr4_app_wdf_wren (app_wdf_wren ),
.c0_ddr4_app_rd_data (app_rd_data ),
.c0_ddr4_app_rd_data_end (app_rd_data_end ),
.c0_ddr4_app_rd_data_valid (app_rd_data_valid ),
.c0_ddr4_app_rdy (app_rdy ),
.c0_ddr4_app_wdf_rdy (app_wdf_rdy ),
// Debug Port
.dbg_bus (dbg_bus )
);
endmodule
时序设计图:
DDR4_control
DDR4_APP