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教程 

posted @ 2020-07-31 19:58  咸鱼IC  阅读(5118)  评论(1编辑  收藏  举报