DDR3(5):DDR3自動讀寫控制器


  和 DDR2 的設計類似,在 DDR3_burst 的基礎上,添加 FIFO,打造一個可以自動讀寫的 DDR3 控制器,讓其能夠方便的適用於不同的場合。

 

一、DDR3_ctrl

1、架構

  由架構圖可以看出,DDR3_ctrl 模塊由寫FIFO、讀FIFO、DDR3_burst構成,結構比較簡單。

2、代碼

  1 //**************************************************************************
  2 // *** 名稱 : DDR3_burst.v
  3 // *** 作者 : xianyu_FPGA
  4 // *** 博客 : https://www.cnblogs.com/xianyufpga/
  5 // *** 日期 : 2020年7月
  6 // *** 描述 : 完成一次DDR3的突發
  7 //**************************************************************************
  8 module DDR3_ctrl
  9 //============================< 參數 >======================================
 10 #(
 11 parameter DDR_DM_W              = 2                     ,   //芯片dm位寬
 12 parameter DDR_DQS_W             = 2                     ,   //芯片dqs位寬
 13 parameter DDR_BANK_W            = 3                     ,   //芯片bank位寬
 14 parameter DDR_ADDR_W            = 14                    ,   //芯片地址位寬
 15 parameter DDR_DATA_W            = 16                    ,   //芯片數據位寬
 16 //-------------------------------------------------------
 17 parameter APP_ADDR_W            = 28                    ,   //用戶地址位寬
 18 parameter APP_DATA_W            = 128                   ,   //用戶數據位寬
 19 //-------------------------------------------------------
 20 parameter BURST_ADDR_W          = 25                        //外部突發位寬 28-3
 21 )
 22 //============================< 信號 >======================================
 23 (
 24 //時鍾和復位 --------------------------------------------
 25 input                           sys_clk_i               ,   //DDR3 參考時鍾
 26 input                           sys_rst                 ,   //FPGA 全局復位
 27 //DDR3寫 ------------------------------------------------
 28 input   [BURST_ADDR_W   -3:0]   wr_min_addr             ,   //寫側 起始地址
 29 input   [BURST_ADDR_W   -3:0]   wr_max_addr             ,   //寫側 結束地址
 30 input                           wr_clk                  ,   //寫側 時鍾
 31 input   [15:0]                  wr_data                 ,   //寫側 數據
 32 input                           wr_vld                  ,   //寫側 有效
 33 //DDR3寫 ------------------------------------------------
 34 input   [BURST_ADDR_W   -3:0]   rd_min_addr             ,   //讀側 起始地址
 35 input   [BURST_ADDR_W   -3:0]   rd_max_addr             ,   //讀側 結束地址
 36 input                           rd_clk                  ,   //讀側 時鍾
 37 output  [15:0]                  rd_data                 ,   //讀側 數據
 38 input                           rd_req                  ,   //讀側 請求
 39 //DDR3控制 ----------------------------------------------
 40 input   [BURST_ADDR_W   -3:0]   burst_len               ,   //突發長度
 41 output                          DDR3_rst                ,   //DDR3復位
 42 input                           pingpang_vld            ,   //乒乓操作
 43 //DDR3接口 ----------------------------------------------
 44 output  [DDR_ADDR_W     -1:0]   ddr3_addr               ,
 45 output  [DDR_BANK_W     -1:0]   ddr3_ba                 ,
 46 output                          ddr3_cas_n              ,
 47 output                          ddr3_ck_n               ,
 48 output                          ddr3_ck_p               ,
 49 output                          ddr3_cke                ,
 50 output                          ddr3_ras_n              ,
 51 output                          ddr3_cs_n               ,
 52 output                          ddr3_reset_n            ,
 53 output                          ddr3_we_n               ,
 54 inout   [DDR_DATA_W     -1:0]   ddr3_dq                 ,
 55 inout   [DDR_DQS_W      -1:0]   ddr3_dqs_n              ,
 56 inout   [DDR_DQS_W      -1:0]   ddr3_dqs_p              ,
 57 output  [DDR_DM_W       -1:0]   ddr3_dm                 ,
 58 output                          ddr3_odt
 59 );
 60 //============================< 信號 >======================================
 61 wire                            ui_clk                  ;
 62 wire    [APP_DATA_W     -1:0]   burst_rd_data           ;   //讀突發數據
 63 wire    [APP_DATA_W     -1:0]   burst_wr_data           ;   //寫突發數據
 64 wire                            burst_rd_ack            ;   //讀突發應答信號
 65 wire                            burst_wr_ack            ;   //寫突發應答信號
 66 wire                            burst_rd_done           ;   //突發讀完成信號
 67 wire                            burst_wr_done           ;   //突發寫完成信號
 68 //-------------------------------------------------------
 69 wire    [ 9:0]                  wrFIFO_rd_count         ;   //寫FIFO剩余數據個數
 70 wire    [ 9:0]                  rdFIFO_wr_count         ;   //讀FIFO剩余數據個數
 71 //-------------------------------------------------------
 72 reg     [ 5:0]                  state                   ;
 73 reg                             burst_wr_req            ;   //突發寫請求
 74 reg                             burst_rd_req            ;   //突發讀請求
 75 reg     [BURST_ADDR_W   -3:3]   wr_addr                 ;
 76 reg     [BURST_ADDR_W   -3:3]   rd_addr                 ;
 77 reg     [ 1:0]                  wr_addr_msb             ;   //乒乓操作寫分區
 78 reg     [ 1:0]                  rd_addr_msb             ;   //乒乓操作讀分區
 79 wire    [BURST_ADDR_W   -1:0]   burst_wr_addr           ;   //寫突發地址
 80 wire    [BURST_ADDR_W   -1:0]   burst_rd_addr           ;   //讀突發地址
 81 //============================< 參數 >======================================
 82 localparam IDLE                 = 6'b000001             ;   //空閑狀態
 83 localparam ARBIT                = 6'b000010             ;   //仲裁狀態
 84 localparam WR                   = 6'b000100             ;   //寫狀態
 85 localparam WR_DONE              = 6'b001000             ;   //寫完成狀態
 86 localparam RD                   = 6'b010000             ;   //讀狀態
 87 localparam RD_DONE              = 6'b100000             ;   //讀完成狀態
 88 //==========================================================================
 89 //==    DDR3突發讀寫模塊,實現一段長度的突發讀寫
 90 //==========================================================================
 91 DDR3_burst
 92 #(
 93     .DDR_DM_W                   (DDR_DM_W               ),   //芯片dm位寬
 94     .DDR_DQS_W                  (DDR_DQS_W              ),   //芯片dqs位寬
 95     .DDR_BANK_W                 (DDR_BANK_W             ),   //芯片bank位寬
 96     .DDR_ADDR_W                 (DDR_ADDR_W             ),   //芯片地址位寬
 97     .DDR_DATA_W                 (DDR_DATA_W             ),   //芯片數據位寬
 98     //---------------------------------------------------
 99     .APP_DATA_W                 (APP_DATA_W             ),   //用戶數據位寬
100     .APP_ADDR_W                 (APP_ADDR_W             ),   //用戶地址位寬
101     //--------------------------------------------------- 
102     .BURST_ADDR_W               (BURST_ADDR_W           )    //外部突發位寬 28-3
103 )
104 u_DDR3_burst
105 (
106     .sys_clk_i                  (sys_clk_i              ),   //DDR3 參考時鍾
107     .sys_rst                    (sys_rst                ),   //FPGA 全局復位
108     .ui_clk                     (ui_clk                 ),   //DDR3 工作時鍾
109     .DDR3_rst                   (DDR3_rst               ),   //DDR3 同步復位
110     //--------------------------------------------------- 
111     .burst_rd_req               (burst_rd_req           ),   //突發讀請求
112     .burst_wr_req               (burst_wr_req           ),   //突發寫請求
113     .burst_rd_len               (burst_len              ),   //突發讀長度
114     .burst_wr_len               (burst_len              ),   //突發寫長度
115     .burst_rd_addr              (burst_rd_addr          ),   //突發讀地址
116     .burst_wr_addr              (burst_wr_addr          ),   //突發寫地址
117     .burst_rd_data              (burst_rd_data          ),   //突發讀數據
118     .burst_wr_data              (burst_wr_data          ),   //突發寫數據
119     .burst_rd_ack               (burst_rd_ack           ),   //突發讀應答,連接FIFO
120     .burst_wr_ack               (burst_wr_ack           ),   //突發寫應答,連接FIFO
121     .burst_rd_done              (burst_rd_done          ),   //突發讀完成信號
122     .burst_wr_done              (burst_wr_done          ),   //突發寫完成信號
123     //---------------------------------------------------
124     .ddr3_addr                  (ddr3_addr              ),
125     .ddr3_ba                    (ddr3_ba                ),
126     .ddr3_cas_n                 (ddr3_cas_n             ),
127     .ddr3_ck_n                  (ddr3_ck_n              ),
128     .ddr3_ck_p                  (ddr3_ck_p              ),
129     .ddr3_cke                   (ddr3_cke               ),
130     .ddr3_ras_n                 (ddr3_ras_n             ),
131     .ddr3_cs_n                  (ddr3_cs_n              ),
132     .ddr3_reset_n               (ddr3_reset_n           ),
133     .ddr3_we_n                  (ddr3_we_n              ),
134     .ddr3_dq                    (ddr3_dq                ),
135     .ddr3_dqs_n                 (ddr3_dqs_n             ),
136     .ddr3_dqs_p                 (ddr3_dqs_p             ),
137     .ddr3_dm                    (ddr3_dm                ),
138     .ddr3_odt                   (ddr3_odt               )
139 );
140 //==========================================================================
141 //==    FIFO
142 //==========================================================================
143 //寫FIFO
144 //---------------------------------------------------
145 wrFIFO_wr16_rd128_4096 wrFIFO
146 (
147     .wr_clk             (wr_clk                     ),  // input wire wr_clk
148     .wr_en              (wr_vld                     ),  // input wire wr_en
149     .din                (wr_data                    ),  // input wire [15 : 0] din
150     .rd_clk             (ui_clk                     ),  // input wire rd_clk
151     .rd_en              (burst_wr_ack               ),  // input wire rd_en
152     .dout               (burst_wr_data              ),  // output wire [127 : 0] dout
153     .full               (                           ),  // output wire full
154     .empty              (                           ),  // output wire empty
155     .rd_data_count      (wrFIFO_rd_count            )   // output wire [9 : 0] rd_data_count
156 );
157 
158 //讀FIFO
159 //---------------------------------------------------
160 rdFIFO_wr128_rd16_512 rdFIFO
161 (
162     .wr_clk             (ui_clk                     ),  // input wire wr_clk
163     .wr_en              (burst_rd_ack               ),  // input wire wr_en
164     .din                (burst_rd_data              ),  // input wire [127 : 0] din
165     .rd_clk             (rd_clk                     ),  // input wire rd_clk
166     .rd_en              (rd_req                     ),  // input wire rd_en
167     .dout               (rd_data                    ),  // output wire [15 : 0] dout
168     .full               (                           ),  // output wire full
169     .empty              (                           ),  // output wire empty
170     .wr_data_count      (rdFIFO_wr_count            )   // output wire [9 : 0] wr_data_count
171 );
172 //==========================================================================
173 //==    狀態機
174 //==========================================================================
175 always @(posedge ui_clk) begin
176     if(DDR3_rst)
177         state <= IDLE;
178     else begin
179         case(state)
180             //--------------------------------------------------- 空閑
181             IDLE:   state <= ARBIT;
182             //--------------------------------------------------- 仲裁
183             ARBIT:  if(wrFIFO_rd_count >= burst_len)
184                         state <= WR;
185                     else if(rdFIFO_wr_count < burst_len)
186                         state <= RD;
187             //--------------------------------------------------- 寫
188             WR:     if(burst_wr_done)
189                         state <= WR_DONE;
190             //--------------------------------------------------- 寫完成
191             WR_DONE:    state <= IDLE;
192             //--------------------------------------------------- 讀
193             RD:     if(burst_rd_done)
194                         state <= RD_DONE;
195             //--------------------------------------------------- 讀完成
196             RD_DONE:    state <= IDLE;
197             
198             default:    state <= IDLE;
199         endcase
200     end
201 end
202 
203 //狀態機名稱,Modelsim測試用
204 //---------------------------------------------------
205 reg [55:0] state_name; //1個字符8位寬
206 always @(*) begin
207     case(state)
208         IDLE    :   state_name = "IDLE";
209         ARBIT   :   state_name = "ARBIT";
210         WR      :   state_name = "WR";
211         WR_DONE :   state_name = "WR_DONE";
212         RD      :   state_name = "RD";
213         RD_DONE :   state_name = "RD_DONE";
214         default :   state_name = "IDLE";
215     endcase
216 end
217 //==========================================================================
218 //==    讀寫請求
219 //==========================================================================
220 always @ (posedge ui_clk) begin
221     if(DDR3_rst) begin
222         burst_wr_req <= 1'b0;
223     end
224     else if(burst_wr_req == 1'b0 && state == WR) begin
225         burst_wr_req <= 1'b1;
226     end
227     else if(burst_wr_req == 1'b1 && state == WR && burst_wr_done) begin
228         burst_wr_req <= 1'b0;
229     end
230 end
231 
232 always @ (posedge ui_clk) begin
233     if(DDR3_rst) begin
234         burst_rd_req <= 1'b0;
235     end
236     else if(burst_rd_req == 1'b0 && state == RD) begin
237         burst_rd_req <= 1'b1;
238     end
239     else if(burst_rd_req == 1'b1 && state == RD && burst_rd_done) begin
240         burst_rd_req <= 1'b0;
241     end
242 end
243 //==========================================================================
244 //==    讀寫地址設計
245 //==========================================================================
246 always @ (posedge ui_clk) begin
247     if(DDR3_rst) begin
248         wr_addr <= wr_min_addr[BURST_ADDR_W-3:3];
249     end
250     else if(state == WR && burst_wr_done) begin
251         if(wr_addr ==  wr_max_addr[BURST_ADDR_W-3:3] - burst_len)
252             wr_addr <= wr_min_addr[BURST_ADDR_W-3:3];
253         else
254             wr_addr <= wr_addr + burst_len;
255     end
256 end
257 
258 always @ (posedge ui_clk) begin
259     if(DDR3_rst) begin
260         rd_addr <= rd_min_addr[BURST_ADDR_W-3:3];
261     end
262     else if(state == RD && burst_rd_done) begin
263         if(rd_addr ==  rd_max_addr[BURST_ADDR_W-3:3]- burst_len)
264             rd_addr <= rd_min_addr[BURST_ADDR_W-3:3];
265         else
266             rd_addr <= rd_addr + burst_len;
267     end
268 end
269 
270 //寫乒乓,未測試
271 //---------------------------------------------------
272 always @ (posedge ui_clk) begin
273     if(DDR3_rst) begin
274         wr_addr_msb <= 2'b1;
275     end
276     else if(pingpang_vld == 1'b1) begin
277         if(state == WR && burst_wr_done && wr_addr == wr_max_addr[BURST_ADDR_W-3:3] - burst_len && rd_addr_msb != wr_addr_msb+1)
278             wr_addr_msb <= wr_addr_msb + 2'h1;
279     end
280     else if(pingpang_vld == 1'b0) begin
281         wr_addr_msb <= 2'b0;
282     end
283 end
284 
285 //讀乒乓,未測試
286 //---------------------------------------------------
287 always @ (posedge ui_clk) begin
288     if(DDR3_rst) begin
289         rd_addr_msb <= 2'h0;
290     end
291     else if(pingpang_vld == 1'b1) begin
292         if(state == RD && burst_rd_done && rd_addr == rd_max_addr[BURST_ADDR_W-3:3] - burst_len && wr_addr_msb != rd_addr_msb+1)
293             rd_addr_msb <= rd_addr_msb + 2'h1;
294     end
295     else if(pingpang_vld == 1'b0) begin
296         rd_addr_msb <= 2'b0;
297     end
298 end
299 
300 //讀寫地址
301 //---------------------------------------------------
302 assign burst_wr_addr = {wr_addr_msb,wr_addr};
303 assign burst_rd_addr = {rd_addr_msb,rd_addr};
304 
305 
306 endmodule

1、DDR3_burst 的寫采用【數據對齊模式】,加上本模塊向 DDR3 發送讀寫請求是通過判斷 FIFO 里的個數來決定的,因此讀寫 FIFO 采用 first word fall through 模式,其讀使能和讀數據對齊,而且有更精准的 FIFO 數據計數,因此更適合於本次的控制器設計。外部連接的 VGA_req 信號需要由常用的提前一拍給出改為直接給出。

2、突發長度在端口上輸入,一般設置為一行圖像個數的 1/8,數據進行 16 轉 128 處理后,剛好一次突發就是一行的圖像數據。

3、一開始照着 DDR2 的方式設計讀寫地址,結果數據大了后就讀空了,后來才知道將 DDR3 設計為跳躍式的讀寫效率非常低,所以改成了順序式的讀寫地址,問題就解決了。

 

二、仿真設計

  1 `timescale 1ns/1ps  //時間精度
  2 
  3 module DDR3_ctrl_tb;
  4 //============================< 端口 >==========================================
  5 parameter DDR_DM_W              = 2                     ;   //芯片dm位寬
  6 parameter DDR_DQS_W             = 2                     ;   //芯片dqs位寬
  7 parameter DDR_BANK_W            = 3                     ;   //芯片bank位寬
  8 parameter DDR_ADDR_W            = 14                    ;   //芯片地址位寬
  9 parameter DDR_DATA_W            = 16                    ;   //芯片數據位寬
 10 //-------------------------------------------------------
 11 parameter APP_ADDR_W            = 28                    ;   //用戶地址位寬
 12 parameter APP_DATA_W            = 128                   ;   //用戶數據位寬
 13 //-------------------------------------------------------
 14 parameter BURST_ADDR_W          = 25                    ;   //外部突發位寬 28-3
 15 //============================< 信號 >======================================
 16 reg                             DDR3_200m               ;   //DDR3 參考時鍾
 17 reg                             FPGA_rst_n              ;   //FPGA 全局復位
 18 //DDR3寫 ------------------------------------------------
 19 reg                             UART_50m                ;   //寫側 時鍾
 20 reg     [15:0]                  DDR3_wr_data            ;   //寫側 數據
 21 reg                             DDR3_wr_vld             ;   //寫側 有效
 22 //DDR3寫 ------------------------------------------------
 23 reg                             HDMI_clk1x              ;   //讀側 時鍾
 24 wire    [15:0]                  DDR3_rd_data            ;   //讀側 數據
 25 wire                            DDR3_rd_req             ;   //讀側 請求
 26 //DDR3控制 ----------------------------------------------
 27 wire                            DDR3_rst                ;   //DDR3 IP核復位
 28 //DDR3接口 ----------------------------------------------
 29 wire    [DDR_ADDR_W     -1:0]   ddr3_addr               ;
 30 wire    [DDR_BANK_W     -1:0]   ddr3_ba                 ;
 31 wire                            ddr3_cas_n              ;
 32 wire                            ddr3_ck_n               ;
 33 wire                            ddr3_ck_p               ;
 34 wire                            ddr3_cke                ;
 35 wire                            ddr3_ras_n              ;
 36 wire                            ddr3_cs_n               ;
 37 wire                            ddr3_reset_n            ;
 38 wire                            ddr3_we_n               ;
 39 wire    [DDR_DATA_W     -1:0]   ddr3_dq                 ;
 40 wire    [DDR_DQS_W      -1:0]   ddr3_dqs_n              ;
 41 wire    [DDR_DQS_W      -1:0]   ddr3_dqs_p              ;
 42 wire    [DDR_DM_W       -1:0]   ddr3_dm                 ;
 43 wire                            ddr3_odt                ;
 44 //==========================================================================
 45 //==            DDR3,輸入200m得到400m,內部4:1,用100m
 46 //==========================================================================
 47 DDR3_ctrl
 48 #(
 49     .DDR_DM_W                   (2                      ),  //芯片dm位寬
 50     .DDR_DQS_W                  (2                      ),  //芯片dqs位寬
 51     .DDR_BANK_W                 (3                      ),  //芯片bank位寬
 52     .DDR_ADDR_W                 (14                     ),  //芯片地址位寬
 53     .DDR_DATA_W                 (16                     ),  //芯片數據位寬
 54     //---------------------------------------------------
 55     .APP_DATA_W                 (128                    ),  //用戶數據位寬
 56     .APP_ADDR_W                 (28                     ),  //用戶地址位寬
 57     //---------------------------------------------------
 58     .BURST_ADDR_W               (25                     )   //外部突發位寬 28-3
 59 )
 60 u_DDR3_ctrl
 61 (
 62     //時鍾和復位 ----------------------------------------
 63     .sys_clk_i                  (DDR3_200m              ),  //DDR3 參考時鍾
 64     .sys_rst                    (FPGA_rst_n             ),  //FPGA 全局復位
 65     //DDR3寫 --------------------------------------------
 66     .wr_min_addr                (0                      ),  //寫側 起始地址
 67     .wr_max_addr                (200*10                 ),  //寫側 結束地址
 68     .wr_clk                     (UART_50m               ),  //寫側 時鍾
 69     .wr_data                    (DDR3_wr_data           ),  //寫側 數據
 70     .wr_vld                     (DDR3_wr_vld            ),  //寫側 有效
 71     //DDR3讀 --------------------------------------------
 72     .rd_min_addr                (0                      ),  //讀側 起始地址
 73     .rd_max_addr                (200*10                 ),  //讀側 結束地址
 74     .rd_clk                     (HDMI_clk1x             ),  //讀側 時鍾
 75     .rd_data                    (DDR3_rd_data           ),  //讀側 數據
 76     .rd_req                     (DDR3_rd_req            ),  //讀側 請求
 77     //DDR3控制 ------------------------------------------
 78     .burst_len                  (25                     ),  //突發長度(行/8)
 79     .DDR3_rst                   (DDR3_rst               ),  //DDR3復位
 80     .pingpang_vld               (1'b0                   ),  //乒乓操作
 81     //DDR3接口 ------------------------------------------
 82     .ddr3_addr                  (ddr3_addr              ),
 83     .ddr3_ba                    (ddr3_ba                ),
 84     .ddr3_cas_n                 (ddr3_cas_n             ),
 85     .ddr3_ck_n                  (ddr3_ck_n              ),
 86     .ddr3_ck_p                  (ddr3_ck_p              ),
 87     .ddr3_cke                   (ddr3_cke               ),
 88     .ddr3_ras_n                 (ddr3_ras_n             ),
 89     .ddr3_cs_n                  (ddr3_cs_n              ),
 90     .ddr3_reset_n               (ddr3_reset_n           ),
 91     .ddr3_we_n                  (ddr3_we_n              ),
 92     .ddr3_dq                    (ddr3_dq                ),
 93     .ddr3_dqs_n                 (ddr3_dqs_n             ),
 94     .ddr3_dqs_p                 (ddr3_dqs_p             ),
 95     .ddr3_dm                    (ddr3_dm                ),
 96     .ddr3_odt                   (ddr3_odt               )
 97 );
 98 
 99 //仿真模型
100 ddr3_model u_ddr3_model
101 (
102     .rst_n              (ddr3_reset_n                   ),
103     .ck                 (ddr3_ck_p                      ),
104     .ck_n               (ddr3_ck_n                      ),
105     .cke                (ddr3_cke                       ),
106     .cs_n               (ddr3_cs_n                      ),
107     .ras_n              (ddr3_ras_n                     ),
108     .cas_n              (ddr3_cas_n                     ),
109     .we_n               (ddr3_we_n                      ),
110     .dm_tdqs            ({ddr3_dm[1],ddr3_dm[0]}        ),  //ddr3_dm為2位
111     .ba                 (ddr3_ba                        ),
112     .addr               (ddr3_addr                      ),
113     .dq                 (ddr3_dq[15:0]                  ),  //ddr3_dq為16位
114     .dqs                ({ddr3_dqs_p[1],ddr3_dqs_p[0]}  ),  //ddr3_dqs_p為2位
115     .dqs_n              ({ddr3_dqs_n[1],ddr3_dqs_n[0]}  ),  //ddr3_dqs_n為2位
116     .tdqs_n             (                               ),
117     .odt                (ddr3_odt                       )
118 );
119 //==========================================================================
120 //==    時鍾信號和復位信號
121 //==========================================================================
122 always #2.5  DDR3_200m  = ~DDR3_200m;       //200Mhz
123 always #10   UART_50m   = ~UART_50m;        //50Mhz
124 always #5    HDMI_clk1x = ~HDMI_clk1x;      //100Mhz
125 
126 initial begin
127     UART_50m    = 0;    
128     DDR3_200m   = 0;    
129     HDMI_clk1x = 0; 
130 
131     FPGA_rst_n  = 0;    #21;
132     FPGA_rst_n  = 1;
133 end
134 //==========================================================================
135 //==    寫
136 //==========================================================================
137 reg     [15:0]              h_cnt                   ;
138 wire                        add_h_cnt               ;
139 wire                        end_h_cnt               ;
140 reg     [15:0]              v_cnt                   ;
141 wire                        add_v_cnt               ;
142 wire                        end_v_cnt               ;
143 
144 //寬度計數
145 //---------------------------------------------------
146 always @(posedge UART_50m) begin
147     if(DDR3_rst)
148         h_cnt <= 'd0;
149     else if(add_h_cnt) begin
150         if(end_h_cnt)
151             h_cnt <= 'd0;
152         else
153             h_cnt <= h_cnt + 1'b1;
154     end
155 end
156 
157 assign add_h_cnt = 1;
158 assign end_h_cnt = add_h_cnt && h_cnt== 200+1;
159 
160 //高度計數
161 //---------------------------------------------------
162 always @(posedge UART_50m) begin
163     if(DDR3_rst)
164         v_cnt <= 'd0;
165     else if(add_v_cnt) begin
166         if(end_v_cnt)
167             v_cnt <= 'd0;
168         else
169             v_cnt <= v_cnt + 1'b1;
170     end
171 end
172 
173 assign add_v_cnt = end_h_cnt;
174 assign end_v_cnt = add_v_cnt && v_cnt== 10+1;
175 
176 always @(posedge UART_50m) begin
177     if(DDR3_rst) begin
178         DDR3_wr_vld  <= 'd0;
179         DDR3_wr_data <= 'd0;
180     end
181     else if(v_cnt > 'd0 && v_cnt <= 'd10) begin
182          if(h_cnt > 'd0 && h_cnt <= 'd200) begin
183                 DDR3_wr_vld  <= 1'd1;
184                 DDR3_wr_data <= DDR3_wr_data + 'd1;
185          end    
186          else begin
187                 DDR3_wr_vld <=  'd0;   
188          end
189     end
190     else begin
191         DDR3_wr_vld <=  'd0;
192         DDR3_wr_data <= 'd0;
193     end
194 end
195 //==========================================================================
196 //==    讀
197 //==========================================================================
198 reg     [15:0]              cnt_h               ;
199 wire                        add_cnt_h           ;
200 wire                        end_cnt_h           ;
201 reg     [15:0]              cnt_v               ;
202 wire                        add_cnt_v           ;
203 wire                        end_cnt_v           ;
204 //========================< 參數 >==========================================
205 always @(posedge HDMI_clk1x) begin
206     if(DDR3_rst)
207         cnt_h <= 'd0;
208     else if(add_cnt_h) begin
209         if(end_cnt_h)
210             cnt_h <= 'd0;
211         else
212             cnt_h <= cnt_h + 1'b1;
213     end
214 end
215 
216 assign add_cnt_h = 1;
217 assign end_cnt_h = add_cnt_h && cnt_h==200+1;
218 
219 always @(posedge HDMI_clk1x) begin
220     if(DDR3_rst)
221         cnt_v <= 'd0;
222     else if(add_cnt_v) begin
223         if(end_cnt_v)
224             cnt_v <= 'd0;
225         else
226             cnt_v <= cnt_v + 1'b1;
227     end
228 end
229 
230 assign add_cnt_v = end_cnt_h;
231 assign end_cnt_v = add_cnt_v && cnt_v==10+1;
232 
233 
234 assign DDR3_rd_req = (cnt_v > 0) && (cnt_v <=10 ) && 
235                      (cnt_h > 0) && (cnt_h <=200);
236 
237 endmodule

  仿真模仿 200x10 的圖片寫入到 DDR3 中,圖像數據為 1-2000,一行200個數據,突發長度設置為 200/8 = 25。寫時鍾設置為 50Mhz,讀時鍾設置為 100Mhz。

 

三、仿真波形

1、總體波形

2、端口處的寫數據波形細節

3、往DDR3寫數據的波形細節

4、端口處的讀數據波形細節

5、往DDR3讀數據的波形細節

 

四、UART_DDR3_HDMI

  DDR3 控制器寫好后,建個串口傳圖工程看看能不能用,通過串口輸入一張 1280*720 的圖片,圖片在 DDR3 中緩存,最終通過 HDMI 輸出到顯示屏中,關於串口傳圖的實現可以參閱博客《串口傳圖:RGB332格式和RGB565格式》,關於HDMI 協議可以參閱博客《協議——HDMI》。

1、工程架構

2、實驗結果

   完結撒花!

 

參考資料:V3學院FPGA教程 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM