秦韵FPGA 转载或原创(五)
GW FPGA DDR3 ip介绍(上)
- ip生成介绍
- ip信号介绍
- ip driver 代码简单分析
- 代码分享
- 打开高云云源软件,点击IP generate 选择DDR3 Memary PHY ,配置 : 主要选择时钟比例,支持1:2 和1:4 , 这里的设置与生成的输出clk,以及写入读出数据时钟有关,ddr3的时钟设置为400M,可选择533M。贴一个设置好的图片:(1) type 界面
(2) options 界面
(3) Timing 界面,暂时保持默认。点击ok ,就生成完成了。 - 贴一下IP的接口信号,接单的介绍一下。
地址位宽[27:0] 数据位宽[127:0] ,支持突发模式,此时突发长度设置为64,由手册知,1:4 时钟比例下,突发长度为64,效率为90%。命令介绍:localparam write = 3’b000;
localparam read = 3’b001;
ddr3的刷新,包括ip自刷新和手动刷新,一般情况下,配置ip自刷新。
DDR3_Memory_Interface_Top u_DDR3_Memory_Interface_Top (
.clk(clk_i),
.rst_n(rst_n_i),
.app_burst_number(app_burst_number_i),
.cmd_ready(cmd_ready_o),
.cmd(cmd_i),
.cmd_en(cmd_en_i),
.addr(addr_i),
.wr_data_rdy(wr_data_rdy_o),
.wr_data(wr_data_i),
.wr_data_en(wr_data_en_i),
.wr_data_end(wr_data_end_i),
.wr_data_mask(wr_data_mask_i),
.rd_data(rd_data_o),
.rd_data_valid(rd_data_valid_o),
.rd_data_end(rd_data_end_o),
.sr_req(sr_req_i),
.ref_req(ref_req_i),
.sr_ack(sr_ack_o),
.ref_ack(ref_ack_o),
.init_calib_complete(init_calib_complete_o),
.clk_out(clk_out_o),
.ddr_rst(ddr_rst_o),
.burst(burst_i),
.O_ddr_addr(O_ddr_addr_o),
.O_ddr_ba(O_ddr_ba_o),
.O_ddr_cs_n(O_ddr_cs_n_o),
.O_ddr_ras_n(O_ddr_ras_n_o),
.O_ddr_cas_n(O_ddr_cas_n_o),
.O_ddr_we_n(O_ddr_we_n_o),
.O_ddr_clk(O_ddr_clk_o),
.O_ddr_clk_n(O_ddr_clk_n_o),
.O_ddr_cke(O_ddr_cke_o),
.O_ddr_odt(O_ddr_odt_o),
.O_ddr_reset_n(O_ddr_reset_n_o),
.O_ddr_dqm(O_ddr_dqm_o),
.IO_ddr_dq(IO_ddr_dq_io),
.IO_ddr_dqs(IO_ddr_dqs_io),
.IO_ddr_dqs_n(IO_ddr_dqs_n_io)
);
- 简单介绍一下driver 部分的逻辑,对外的部分分成两部分,1)write :包括地址,数据,使能。
2)read : 包括地址,数据,使能。 对iP部分的引脚,主要是为了对ip进行控制,因此直连到IP顶层。
module ddr3_driver
#(
parameter ADDR_WIDTH = 28,
parameter APP_DATA_WIDTH = 128,
parameter APP_MASK_WIDTH = 16,
parameter BURST_MODE = "8",
parameter USER_REFRESH = "OFF"
)
(
input clk,
input rst,
input init_calib_complete_o,
input app_rdy,
input app_rd_data_valid,
input wr_data_rdy,
input [APP_DATA_WIDTH-1:0] app_rd_data,
output reg app_en,
output reg [2:0] app_cmd,
output reg [ADDR_WIDTH-1:0] app_addr ,
output reg [APP_DATA_WIDTH-1:0] app_wdf_data ,
output reg app_wdf_wren,
output reg app_wdf_end,
output reg [APP_MASK_WIDTH-1:0] app_wdf_mask ,
output reg app_burst,
output reg sr_req,
output reg ref_req,
output [5:0] app_burst_number,
input [17:0] wr_cdr_addr,
input [127:0] wr_cdr_data,
input wr_cdr_en,
output wr_cdr_burst_end,
input [17:0] rd_cdr_addr,
input rd_cdr_en,
output reg [127:0] rd_cdr_data,
output rd_cdr_burst_end
);
- 贴一下driver部分代码,理解一下控制过程:主要完成对ip的控制,完成基本驱动,关于业务层的代码下篇讲解,主要包含8 channal 数据缓存,以及ddr3 内部逻辑的监测logic。
always@(posedge clk or posedge rst) begin
if(rst) begin
app_en <= 1'b0;
app_cmd <= 3'b000;
app_wdf_wren <= 1'b0;
app_wdf_end <= 1'b0;
app_wdf_mask <= {APP_MASK_WIDTH{1'b0}};
app_burst <= 1'b1;
app_addr <= {ADDR_WIDTH{1'b0}};
app_wdf_data <= {APP_DATA_WIDTH{1'b0}};
end
else if((app_rdy ) &&(wrBl_cnt == 'd1) && init_calib_complete) begin
app_en <= 1'b1;
app_cmd <= write ;
app_wdf_wren <= 1'b1;
app_wdf_end <= 1'b1;
app_addr <= reg_addr;
app_wdf_mask <= {APP_MASK_WIDTH{1'b0}};
app_wdf_data <= wr_cdr_data;
app_burst <= 1'b1;
end
else if((app_rdy ) &&(wrBl_cnt >= 'd2)&&(wrBl_cnt <= app_burst_number + 1) && init_calib_complete && wr_data_rdy) begin
app_en <= 1'b0;
app_cmd <= write;
app_wdf_wren <= 1'b1;
app_wdf_end <= 1'b1;
app_addr <= 'd0;
app_wdf_mask <= {APP_MASK_WIDTH{1'b0}};
app_wdf_data <= wr_cdr_data;
app_burst <= 1'b1;
end
else if(app_rdy && rd_cdr_en_r ) begin
app_en <= 1'b1;
app_cmd <= read;
app_wdf_wren <= 1'b0;
app_wdf_end <= 1'b0;
app_wdf_mask <= {APP_MASK_WIDTH{1'b0}};
app_addr <= reg_raddr;
app_wdf_data <= {APP_DATA_WIDTH{1'b0}};
end
else begin
app_en <= 1'b0;
app_cmd <= 3'b000;
app_wdf_wren <= 1'b0;
app_wdf_end <= 1'b0;
app_wdf_mask <= {APP_MASK_WIDTH{1'b0}};
app_addr <= 'd0;
app_wdf_data <= {APP_DATA_WIDTH{1'b0}};
end
end
- 下篇介绍其他部分逻辑,及其框架。
- (这里主要在代码编写,驱动logic分析,以及框架图。如果对芯片原理,协议原理不清楚的推荐补习原理后,参照流程进行开发,后续会更新实际项目,及其项目中的问题简介,不会介绍过多的原理,会出一些关于高云的开发板,主要在18系列,可用于实际项目)。