ddr3调试经验分享(三)——KC705_MIG_app接口设计
网上有位大神写了《xilinx平台DDR3设计教程之XX篇》,一共五篇。稍微百度一下就能出来。最后也给出了具体的app接口的控制方式,只是没有code而已。这里做个小笔记,表示自己的实现方案
ddr3_app_ctrl 是app控制器
wdata_in 仅仅是将 16bit的有效数据转换成64bit数据,然后在存入到FIFO中。额,之所以不用16bit位宽进 512位宽出的FIFO,是因为xilinx的FIFO如果设定为512bit出最小输入位宽是64bit。没办法,所以多了这个小模块。
xilinx_fifo2ddr 当然就是一个fifo了。异步 64bit进 512bit出 ,深度够存自己的东西就好。
// ********************************************************* ddr3_app_ctrl ddr3_app_ctrl( .clk_in (~clk), .rst_n (!sys_rst), .v_bling (v_bling), // ----------app interface .app_ini (init_calib_complete), .app_rdy (app_rdy), .app_wdf_rdy (app_wdf_rdy), //output .app_cmd (app_cmd), .app_wdf_mask (app_wdf_mask), .ddr_addr (app_addr), .app_en (app_en), .app_wdf_wren (app_wdf_wren), .app_wdf_end (app_wdf_end), // ----------wr fifo interface .wr_fifo_wcnt (wr_data_count), .wr_ddr_en (wr_ddr_en) ); // **************************************************** wdata_in wdata_in( .clk (v_clk), .rst_n (!sys_rst), .data_valid (val_flag), //1:数据有效标志位 .data_in (val_data), //有效数据 16bit .wr_clk (wr_clk), .wr_en (wr_en), .wr_data (wr_data) //64bit ); // ---------------------------------------------------- xilinx_fifo2ddr fifo_data2ddr( .rst (sys_rst), .wr_clk (wr_clk), .rd_clk (clk), .din (wr_data), //(63 DOWNTO 0); .wr_en (wr_en), .rd_en (wr_ddr_en), .dout (app_wdf_data), //(511 DOWNTO 0); .full (fifo_full), .empty (wr_empty), .rd_data_count() , //(5 DOWNTO 0); .wr_data_count(wr_data_count) //(8 DOWNTO 0) );
2,现在来看看 app控制模块
我的实现要求是存一行,读一行。一行1920*16bit个数据,写到FIFO中就有480 个64bit的数据。
v_bling :我需要这个信号,是想在 bt1120格式 的图像数据在blank期换bank存储。所以在 48~62 之间就是在干这个换bank的事情。但是62行是替换了61行,项目中是运行61行。62行是为了仿真的。
MIG中输入时钟是差分200M,经过MIG中倍频到800M ,又因为ddr是双沿触发,所以数据传输速率为1600M
1 `define FIFO_ADD_CNT 480 // 1920*16/64=480 2 `define DDR_ADD_CNT 60 // 1920*2byte/8=60 3 // ******************************** 4 module ddr3_app_ctrl ( 5 clk_in, 6 rst_n, 7 v_bling, 8 // ----------app interface 9 app_ini, 10 app_rdy, 11 app_wdf_rdy, 12 //output 13 app_cmd , 14 app_wdf_mask, 15 ddr_addr, 16 app_en, 17 app_wdf_wren, 18 app_wdf_end, 19 // ----------wr fifo interface 20 wr_fifo_wcnt , 21 wr_ddr_en, 22 //-----------rd fifo interface 23 // rd_fifo_rcnt 24 ); 25 input clk_in , rst_n ; 26 input v_bling ; 27 // app interface 28 input app_ini ; 29 input app_rdy; //read enable active high 30 input app_wdf_rdy; //write enable active high 31 output reg [2:0] app_cmd ; //000 write 001 read 32 output [63:0] app_wdf_mask ; 33 output reg [27:0] ddr_addr ; //rank+bank+row+column=1+3+14+10=28 34 output reg app_en ; //address enable active high 35 output reg app_wdf_wren ; 36 output app_wdf_end ; //write data enable active high 37 // wr fifo interface 38 input [8:0] wr_fifo_wcnt ; 39 output wr_ddr_en; 40 // rd fifo interface 41 // input [8:0] rd_fifo_rcnt ; 42 // *************************************************** 43 assign app_wdf_mask = 64'd0 ; 44 assign app_wdf_end = app_wdf_wren ; 45 // *************************************************** 46 // ddr bank change when v_bling negedge. read ddr must be finish when v 47 // blank over. 48 reg v_reg ; 49 wire v_neg ; 50 always @(posedge clk_in or negedge rst_n) 51 if(!rst_n) v_reg <= 1'd0 ; 52 else v_reg <= v_bling ; 53 assign v_neg = v_reg&(!v_bling); 54 // --- generate write bank and read bank -------------- 55 reg [2:0] value; 56 wire [3:0] wr_bank ,rd_bank ; 57 always @(posedge clk_in or negedge rst_n) //must have rst_n signal 58 if(!rst_n) value <=3'b100; 59 else if (v_neg) value <= {value[1:0],value[2]}; 60 assign wr_bank={2'b00,value[1:0]}; //0000 0001 0010 0000 61 //assign rd_bank={2'b00,value[2:1]}; //0010 0000 0001 0010 62 assign rd_bank={2'b00,value[1:0]}; //0010 0000 0001 0010 //for test 63 // ***************************************************** 64 reg wr_ddr3_en,rd_ddr3_en ; 65 reg [20:0] wr_ddr_addr, rd_ddr_addr; 66 wire rd_ddr_en ; 67 wire [27:0] wr_addr, rd_addr; 68 // ----------------------------------- 69 reg [4:0] ctrl_sta ; 70 reg [6:0] add_cnt ; 71 always@(posedge clk_in or negedge rst_n) 72 if(!rst_n) begin 73 rd_ddr3_en <= 1'd0 ; 74 wr_ddr3_en <= 1'd0 ; 75 wr_ddr_addr <= 21'd0 ; 76 rd_ddr_addr <= 21'd0 ; 77 add_cnt <= 7'd0 ; 78 ctrl_sta <= 5'd0 ; 79 end 80 else if(app_wdf_rdy&app_rdy) 81 case (ctrl_sta) 82 4'd0: 83 if (app_ini)begin 84 rd_ddr3_en <= 1'd0 ; 85 wr_ddr3_en <= 1'd0 ; 86 wr_ddr_addr <= 21'h1f_ffff ; 87 rd_ddr_addr <= 21'h1f_ffff ; 88 add_cnt <= 7'd0 ; 89 ctrl_sta <= ctrl_sta+5'd1 ; 90 end 91 else begin 92 rd_ddr3_en <= 1'd0 ; 93 wr_ddr3_en <= 1'd0 ; 94 wr_ddr_addr <= 21'd0 ; 95 rd_ddr_addr <= 21'd0 ; 96 add_cnt <= 7'd0 ; 97 ctrl_sta <=5'd0 ; 98 end 99 4'd1: //waite for data in FIFO_1 finish 100 if(wr_fifo_wcnt==`FIFO_ADD_CNT) begin 101 rd_ddr3_en <= 1'd0 ; 102 wr_ddr3_en <= 1'b1; 103 wr_ddr_addr <= wr_ddr_addr + 21'd1 ; 104 //rd_ddr_addr <= ; //keep address 105 add_cnt <= add_cnt + 7'd1 ; 106 ctrl_sta <= ctrl_sta+5'd1 ; 107 end 108 else begin 109 rd_ddr3_en <= 1'd0 ; 110 wr_ddr3_en <= 1'd0 ; 111 add_cnt <= 7'd0 ; 112 //wr_ddr_addr <= ; 113 //rd_ddr_addr <= ; 114 end 115 4'd2: //write ddr 116 if(add_cnt==`DDR_ADD_CNT) begin 117 rd_ddr3_en <= 1'd0 ; // 118 wr_ddr3_en <= 2'd0 ; 119 add_cnt <= 7'd0 ; 120 //wr_ddr_addr <= ; // 121 //rd_ddr_addr <= ; 122 ctrl_sta <= ctrl_sta+5'd1 ; 123 end 124 else begin 125 rd_ddr3_en <= 1'd0 ; 126 wr_ddr3_en <= 1'b1; 127 wr_ddr_addr <= wr_ddr_addr + 21'd1 ; 128 //rd_ddr_addr <= ; 129 add_cnt <= add_cnt+7'd1 ; 130 end 131 4'd3: // read ddr3 132 if(add_cnt==`DDR_ADD_CNT) begin 133 rd_ddr3_en <= 1'd0 ; 134 wr_ddr3_en <= 2'd0 ; 135 add_cnt <= 7'd0 ; 136 //wr_ddr_addr <= ; 137 //rd_ddr_addr <= ; 138 ctrl_sta <= ctrl_sta+5'd1 ; 139 end 140 else begin 141 rd_ddr3_en <= 1'd1 ; 142 wr_ddr3_en <= 1'b0; 143 //wr_ddr_addr <= ; 144 rd_ddr_addr <= rd_ddr_addr +21'd1 ; 145 add_cnt <= add_cnt+7'd1 ; 146 end 147 4'd4: //frame change -- bank change 148 if(v_bling) begin // 149 rd_ddr3_en <= 1'd0 ; 150 wr_ddr3_en <= 1'd0; //1'd1 ; 151 wr_ddr_addr <= 21'h1f_ffff ; 152 rd_ddr_addr <= 21'h1f_ffff ; 153 add_cnt <= 7'd0 ; 154 ctrl_sta <= 5'd1 ; 155 end 156 else begin 157 rd_ddr3_en <= 1'd0 ; 158 wr_ddr3_en <= 1'd0 ; 159 //wr_ddr_addr <= //keep address 160 //rd_ddr_addr <= 161 add_cnt <= 7'd0 ; 162 ctrl_sta <= 5'd1 ; 163 end 164 endcase 165 // ******************************************************************* 166 assign wr_ddr_en = wr_ddr3_en&app_wdf_rdy&app_rdy ; //read fifo enable &write ddr enable 167 assign rd_ddr_en = rd_ddr3_en&app_wdf_rdy&app_rdy ; //read ddr enable 168 // --------------------------------------------- 169 assign wr_addr = {wr_bank,wr_ddr_addr,3'b000}; 170 assign rd_addr = {rd_bank,rd_ddr_addr,3'b000}; 171 // --------------------------------------------- 172 always @(posedge clk_in or negedge rst_n) 173 if(!rst_n) ddr_addr <= 28'd0 ; 174 else if (wr_ddr3_en) ddr_addr <= wr_addr; 175 else if (rd_ddr3_en) ddr_addr <= rd_addr; 176 // ------------------------------------------- 177 always @(posedge clk_in or negedge rst_n) 178 if(!rst_n) app_en <= 1'd0 ; 179 else if ((rd_ddr_en)|(wr_ddr_en))app_en <= 1'd1 ; 180 else app_en <= 1'd0 ; 181 // --------------------------------------------- 182 always @(posedge clk_in or negedge rst_n) 183 if(!rst_n) app_cmd <= 3'b000 ; 184 else if(wr_ddr3_en) app_cmd <= 3'b000 ; // wr enable 185 else if(rd_ddr3_en) app_cmd <= 3'b001 ; //rd enable 186 else app_cmd <= 3'b100 ; //free 187 //--------------------------------------------- 188 always @(posedge clk_in or negedge rst_n) 189 if(!rst_n) app_wdf_wren <= 1'd0 ; 190 else if (wr_ddr_en) app_wdf_wren <= 1'd1 ; 191 else app_wdf_wren <= 1'd0 ; 192 193 endmodule
23行的接口是不需要的,因为对于从ddr读出来的数据也是接一个fifo。到时候把 app_rd_data接到FIFO的数据接口,app_rd_data_valid接到fifo的写使能端口
欢迎加入: FPGA广东交流群:162664354
FPGA开发者联盟: 485678884