DDR2(4):对DDR2 IP再次封装

  生成 DDR2 IP 后就可以使用了,网络上也很多直接对 DDR2 IP 操作的例程,但其实这样还不够好,我们可以对这个 DDR2 IP 进行再次封装,让它变得更加好用。现在试着封装一下,之前的 DDR2 IP 名字就是 DDR2.v,这个封装就命名为 DDR2_burst,其主要作用是完成一次 DDR2 的突发读写,即外界可以任意设置突发长度,在这个模块将这个任意的突发长度转换为突发长度 4 写进 DDR2 IP 里。

  封装 DDR2 IP 有常见的两种方式,一种是设计 DDR2_burst 和 DDR2 IP 外部互联,再用第三个 .v 文件将这两者连线,如下所示:

  另一种是直接将 DDR2_IP 放到 DDR2_burst 代码里面例化,如下所示:

  显然,第二种比较简洁,文件较少。

 

一、参数集 DDR2_param

  先给出参数集,方便移植。命名为 DDR2_param.v,内容如下:

//**************************************************************************
// *** 名称 : DDR2_param.v
// *** 作者 : xianyu_FPGA
// *** 博客 : https://www.cnblogs.com/xianyufpga/
// *** 日期 : 2020年6月
// *** 描述 : DDR2参数,PLL 100Mhz,DDR2 166.7Mhz,Full Rate
//**************************************************************************
`define     MEM_ADDR_W          13      //DDR2 地址位宽
`define     MEM_BANK_W          3       //DDR2 bank位宽
`define     MEM_DM_W            4       //DDR2 dm位宽
`define     MEM_DQ_W            32      //DDR2 数据位宽,一片16两片32
`define     MEM_DQS_W           4       //DDR2 DQS位宽

`define     LOCAL_DATA_W        64      //DDR2 IP核全速率数据位宽
`define     LOCAL_ADDR_W        25      //DDR2 IP核全速率地址位宽
`define     LOCAL_SIZE_W        3       //DDR2 IP核全速率local_size位宽
`define     LOCAL_BE_W          8       //DDR2 IP核全速率local_be位宽

`define     BURST_W             14      //burst长度位宽,burst_len + BURST_SIZE

  burst 长度位宽为什么是 14,下一篇博客会说明,现在记住这个数字。

 

二、DDR2_burst

  1 `include "DDR2_param.v"
  2 //**************************************************************************
  3 // *** 名称 : DDR2_burst.v
  4 // *** 作者 : xianyu_FPGA
  5 // *** 博客 : https://www.cnblogs.com/xianyufpga/
  6 // *** 日期 : 2020年6月
  7 // *** 描述 : 完成一次DDR2的突发读写
  8 //**************************************************************************
  9 
 10 module DDR2_burst
 11 //============================< 端口 >======================================
 12 (
 13 //DDR2 IP核接口 -----------------------------------------
 14 input                           pll_ref_clk             ,   //DDR2 参考时钟
 15 input                           global_reset_n          ,   //全局复位信号,连接外部复位
 16 output                          phy_clk                 ,   //DDR2 IP核工作时钟
 17 output                          reset_phy_clk_n         ,   //DDR2 IP核同步后的复位信号
 18 output                          local_init_done         ,   //DDR2 IP核初始化完成信号
 19 //突发读写接口 ------------------------------------------
 20 input                           burst_rdreq             ,   //突发读请求
 21 input                           burst_wrreq             ,   //突发写请求
 22 input   [`BURST_W       -1:0]   burst_rdlen             ,   //突发读长度
 23 input   [`BURST_W       -1:0]   burst_wrlen             ,   //突发写长度
 24 input   [`LOCAL_ADDR_W  -1:0]   burst_rdaddr            ,   //突发读地址
 25 input   [`LOCAL_ADDR_W  -1:0]   burst_wraddr            ,   //突发写地址
 26 output  [`LOCAL_DATA_W  -1:0]   burst_rddata            ,   //突发读数据
 27 input   [`LOCAL_DATA_W  -1:0]   burst_wrdata            ,   //突发写数据
 28 output                          burst_rdack             ,   //突发读应答,连接FIFO
 29 output                          burst_wrack             ,   //突发写应答,连接FIFO
 30 output  reg                     burst_rddone            ,   //突发读完成信号
 31 output  reg                     burst_wrdone            ,   //突发写完成信号
 32 //DDR2端口 ----------------------------------------------
 33 output                          mem_odt                 ,   //DDR2片上终结信号
 34 output                          mem_cs_n                ,   //DDR2片选信号
 35 output                          mem_cke                 ,   //DDR2时钟使能信号
 36 output  [`MEM_ADDR_W    -1:0]   mem_addr                ,   //DDR2地址总线
 37 output  [`MEM_BANK_W    -1:0]   mem_ba                  ,   //DDR2BANK信号
 38 output                          mem_ras_n               ,   //DDR2行地址选择信号
 39 output                          mem_cas_n               ,   //DDR2列地址选择信号
 40 output                          mem_we_n                ,   //DDR2写使能信号
 41 output  [`MEM_DM_W      -1:0]   mem_dm                  ,   //DDR2数据掩膜信号
 42 inout                           mem_clk                 ,   //DDR2时钟信号
 43 inout                           mem_clk_n               ,   //DDR2时钟反相信号
 44 inout   [`MEM_DQ_W      -1:0]   mem_dq                  ,   //DDR2数据总线
 45 inout   [`MEM_DQS_W     -1:0]   mem_dqs                     //DDR2数据源同步信号
 46 );
 47 //============================< 信号 >======================================
 48 wire                            rst_n                   ;   //本模块复位信号
 49 reg     [ 4:0]                  state                   ;   //状态机
 50 reg     [ `BURST_W      -1:0]   rdaddr_cnt              ;   //读地址计数器
 51 reg     [ `BURST_W      -1:0]   rddata_cnt              ;   //读数据计数器
 52 reg     [ `BURST_W      -1:0]   wrburst_cnt             ;   //一次突发写内的计数器
 53 reg     [ `BURST_W      -1:0]   wraddr_cnt              ;   //写地址计数器
 54 reg     [ `BURST_W      -1:0]   rdlen                   ;   //写突发长度
 55 reg     [ `BURST_W      -1:0]   wrlen                   ;   //读突发长度
 56 wire                            local_burstbegin        ;   //DDR2 IP核突发起始信号
 57 reg     [`LOCAL_SIZE_W  -1:0]   local_size              ;   //DDR2 IP核突发大小
 58 reg     [`LOCAL_ADDR_W  -1:0]   local_address           ;   //DDR2 IP核地址总线
 59 wire                            local_write_req         ;   //DDR2 IP核写请求信号
 60 wire                            local_read_req          ;   //DDR2 IP核读请求信号
 61 wire    [`LOCAL_DATA_W  -1:0]   local_wdata             ;   //DDR2 IP核写数据总线
 62 wire    [`LOCAL_DATA_W  -1:0]   local_rdata             ;   //DDR2 IP核读数据总线
 63 wire                            local_ready             ;   //DDR2 IP核准备好信号
 64 wire                            local_rdata_valid       ;   //DDR2 IP核读数据有效信号
 65 //============================< 参数 >======================================
 66 parameter   WRBURST_SIZE        = `BURST_W'd2           ;   //总线写突发大小
 67 parameter   RDBURST_SIZE        = `BURST_W'd2           ;   //总线读突发大小
 68 //-------------------------------------------------------
 69 parameter   IDLE                = 5'b00001              ;   //空闲状态
 70 parameter   WR_RDY              = 5'b00010              ;   //写准备状态
 71 parameter   WR                  = 5'b00100              ;   //写状态
 72 parameter   RD_ADDR             = 5'b01000              ;   //读状态
 73 parameter   RD_WAIT             = 5'b10000              ;   //读等待状态
 74 //==========================================================================
 75 //==    DDR2 IP核,PLL 100Mhz,DDR2 166.7Mhz,Full Rate
 76 //==========================================================================
 77 DDR2 u_DDR2
 78 (
 79     .pll_ref_clk                (pll_ref_clk            ),  //DDR2 参考时钟
 80     .global_reset_n             (global_reset_n         ),  //全局复位信号
 81     .soft_reset_n               (1'b1                   ),  //软复位信号
 82     .local_address              (local_address          ),  //DDR2 IP核地址总线
 83     .local_write_req            (local_write_req        ),  //DDR2 IP核写请求信号
 84     .local_read_req             (local_read_req         ),  //DDR2 IP核读请求信号
 85     .local_burstbegin           (local_burstbegin       ),  //DDR2 IP核突发起始信号
 86     .local_wdata                (local_wdata            ),  //DDR2 IP核写数据总线
 87     .local_be                   (8'b1111_1111           ),  //DDR2 IP核字节使能信号
 88     .local_size                 (local_size             ),  //DDR2 IP核突发大小
 89     .local_ready                (local_ready            ),  //DDR2 IP核准备好信号
 90     .local_rdata                (local_rdata            ),  //DDR2 IP核读数据总线
 91     .local_rdata_valid          (local_rdata_valid      ),  //DDR2 IP核读数据有效信号
 92     .local_refresh_ack          (                       ),  //DDR2 IP核自刷新应答信号
 93     .local_init_done            (local_init_done        ),  //DDR2 IP核初始化完成信号
 94     //---------------------------------------------------
 95     .mem_odt                    (mem_odt                ),  //DDR2片上终结信号
 96     .mem_cs_n                   (mem_cs_n               ),  //DDR2片选信号
 97     .mem_cke                    (mem_cke                ),  //DDR2时钟使能信号
 98     .mem_addr                   (mem_addr               ),  //DDR2地址总线
 99     .mem_ba                     (mem_ba                 ),  //DDR2组地址信号
100     .mem_ras_n                  (mem_ras_n              ),  //DDR2行地址选择信
101     .mem_cas_n                  (mem_cas_n              ),  //DDR2列地址选择信
102     .mem_we_n                   (mem_we_n               ),  //DDR2写使能信号
103     .mem_dm                     (mem_dm                 ),  //DDR2数据掩膜信号
104     .mem_clk                    (mem_clk                ),  //DDR2时钟信号
105     .mem_clk_n                  (mem_clk_n              ),  //DDR2时钟反相信号
106     .mem_dq                     (mem_dq                 ),  //DDR2数据总线
107     .mem_dqs                    (mem_dqs                ),  //DDR2数据源同步信号
108     .phy_clk                    (phy_clk                ),  //DDR2 IP核工作时钟
109     .reset_phy_clk_n            (reset_phy_clk_n        ),  //DDR2 IP核同步后的复位信号
110     .reset_request_n            (                       ),  //DDR2 IP核复位请求信号
111     .aux_full_rate_clk          (                       ),  //DDR2 IP核全速率时钟
112     .aux_half_rate_clk          (                       )   //DDR2 IP核半速率时钟
113 );
114 
115 //本模块复位信号
116 assign rst_n = reset_phy_clk_n && local_init_done;
117 //==========================================================================
118 //==    状态机
119 //==========================================================================
120 always @ (posedge phy_clk or negedge rst_n) begin
121     if(!rst_n) begin
122         burst_wrdone <= 1'b0;
123         burst_rddone <= 1'b0;
124         state <= IDLE; 
125     end
126     else begin
127         case(state)
128             //--------------------------------------------------- 空闲
129             IDLE:   begin
130                         burst_wrdone <= 1'b0;
131                         burst_rddone <= 1'b0;
132                         if(burst_wrreq && burst_wrlen != `BURST_W'd0)
133                             state <= WR_RDY;
134                         else if(burst_rdreq && burst_rdlen != `BURST_W'd0)
135                             state <= RD_ADDR;
136                         else
137                             state <= state;
138                     end
139             //--------------------------------------------------- 写准备
140             WR_RDY: begin
141                             state <= WR;
142                     end
143             //--------------------------------------------------- 写数据
144             WR:     begin
145                         if(wraddr_cnt + wrburst_cnt >= wrlen - `BURST_W'd1 && local_ready) begin
146                             state <= IDLE;  burst_wrdone <= 1'b1;
147                         end
148                     end
149             //--------------------------------------------------- 读地址
150             RD_ADDR:     begin
151                         if(rdaddr_cnt + RDBURST_SIZE >= rdlen && local_ready) begin
152                             state <= RD_WAIT;
153                         end
154                     end
155             //--------------------------------------------------- 读数据等待
156             RD_WAIT:begin
157                         if(rddata_cnt >= rdlen - `BURST_W'h1 && local_rdata_valid) begin
158                             state <= IDLE;  burst_rddone <= 1'b1;
159                         end
160                     end
161             default:        state <= IDLE;
162         endcase
163     end
164 end
165 //------------------------------------------ 状态机名称,测试用
166 reg [55:0] state_name; //1个字符8位宽
167 
168 always @(*) begin
169     case(state)
170         IDLE    :   state_name = "IDLE";
171         WR_RDY  :   state_name = "WR_RDY";
172         WR      :   state_name = "WR";
173         RD_ADDR :   state_name = "RD_ADDR";
174         RD_WAIT :   state_name = "RD_WAIT";
175         default :   state_name = "IDLE";
176     endcase
177 end
178 //==========================================================================
179 //==    在进入读状态前锁存读突发长度
180 //==========================================================================
181 always @ (posedge phy_clk or negedge rst_n) begin
182     if(!rst_n) begin
183         rdlen <= `BURST_W'h0;
184     end
185     else if(state == IDLE && burst_rdreq && burst_rdlen != `BURST_W'd0) begin
186         rdlen <= burst_rdlen;
187     end
188 end
189 
190 always @ (posedge phy_clk or negedge rst_n) begin
191     if(!rst_n) begin
192         wrlen <= `BURST_W'h0;
193     end
194     else if(state == IDLE && burst_wrreq && burst_wrlen != `BURST_W'd0) begin
195         wrlen <= burst_wrlen;
196     end
197 end
198 //==========================================================================
199 //==    写突发的数据计数
200 //==========================================================================
201 always @ (posedge phy_clk or negedge rst_n) begin
202     if(!rst_n) begin
203         wrburst_cnt <= `BURST_W'h0;
204     end
205     else if(state == WR && local_ready) begin
206         if(wrburst_cnt >= WRBURST_SIZE - `BURST_W'h1)
207             wrburst_cnt <= `BURST_W'h0;
208         else
209             wrburst_cnt <= wrburst_cnt + `BURST_W'h1;
210     end
211 end
212 //==========================================================================
213 //==    筹齐2个数据,地址+2
214 //==========================================================================
215 always @ (posedge phy_clk or negedge rst_n) begin
216     if(!rst_n) begin
217         wraddr_cnt <= `BURST_W'h0;
218     end
219     else if(state == WR && local_ready) begin
220         if(wraddr_cnt + wrburst_cnt >= wrlen - `BURST_W'd1)
221             wraddr_cnt <= `BURST_W'h0;
222         else if(wrburst_cnt == WRBURST_SIZE - `BURST_W'h1)
223             wraddr_cnt <= wraddr_cnt + WRBURST_SIZE;    
224     end
225 end
226 //==========================================================================
227 //==    每次给出读指令时,读地址递增2
228 //==========================================================================
229 always @ (posedge phy_clk or negedge rst_n) begin
230     if(!rst_n) begin
231         rdaddr_cnt <= `BURST_W'h0;
232     end
233     else if(state == RD_ADDR && local_ready) begin
234         if(rdaddr_cnt >= rdlen - `BURST_W'h1)
235             rdaddr_cnt <= `BURST_W'h0;
236         else
237             rdaddr_cnt <= rdaddr_cnt + RDBURST_SIZE;
238     end
239 end
240 //==========================================================================
241 //==    每读出一个数据时地址递增1
242 //==========================================================================
243 always @ (posedge phy_clk or negedge rst_n) begin
244     if(!rst_n) begin
245         rddata_cnt <= `BURST_W'h0;
246     end
247     else if(local_rdata_valid) begin
248         if(rddata_cnt >= rdlen - `BURST_W'h1)
249             rddata_cnt <= `BURST_W'h0;
250         else
251             rddata_cnt <= rddata_cnt + `BURST_W'h1;
252     end
253 end
254 //==========================================================================
255 //==    锁存local_size并在最后一次读写时如果不足突发大小则更改local_size为不足的大小
256 //==========================================================================
257 always @ (posedge phy_clk or negedge rst_n) begin
258     if(!rst_n) begin
259         local_size <= `LOCAL_SIZE_W'h0;
260     end
261     else if(state == IDLE && burst_rdreq && burst_rdlen != `BURST_W'd0) begin
262         local_size <= (burst_rdlen >= RDBURST_SIZE) ? RDBURST_SIZE : burst_rdlen;
263     end
264     else if(state == IDLE && burst_wrreq && burst_wrlen != `BURST_W'd0) begin
265         local_size <= (burst_wrlen >= WRBURST_SIZE) ? WRBURST_SIZE : burst_wrlen;
266     end
267     else if(state == RD_ADDR && rdaddr_cnt + {RDBURST_SIZE[`BURST_W-2:0],1'b0} > rdlen && local_ready) begin
268         local_size <= rdlen - rdaddr_cnt - RDBURST_SIZE;
269     end
270     else if(state == WR && wrburst_cnt == WRBURST_SIZE - `BURST_W'h1 &&
271             wraddr_cnt + {WRBURST_SIZE[`BURST_W-2:0],1'b0} > wrlen && local_ready) begin
272         local_size <= wrlen - wraddr_cnt - WRBURST_SIZE;
273     end
274 end
275 //==========================================================================
276 //==    锁存local_address,并且在完成一次突发读写时递增读写地址
277 //==========================================================================
278 always @ (posedge phy_clk or negedge rst_n) begin
279     if(!rst_n) begin
280         local_address <= `LOCAL_ADDR_W'h0;
281     end
282     else if(state == IDLE && burst_wrreq && burst_wrlen != `BURST_W'd0) begin
283         local_address <= burst_wraddr;
284     end
285     else if(state == IDLE && burst_rdreq && burst_rdlen != `BURST_W'd0) begin
286         local_address <= burst_rdaddr;
287     end
288     else if(state == WR && (wrburst_cnt == WRBURST_SIZE - `BURST_W'h1) && local_ready) begin
289         local_address <= local_address + WRBURST_SIZE;
290     end
291     else if(state == RD_ADDR && (rdaddr_cnt + RDBURST_SIZE < rdlen) && local_ready) begin
292         local_address <= local_address + RDBURST_SIZE;
293     end
294 end
295 //==========================================================================
296 //==    其他信号
297 //==========================================================================
298 //读数据
299 assign burst_rddata = local_rdata;
300 
301 //DDR2读应答,即读FIFO的写使能
302 assign burst_rdack = local_rdata_valid;
303 
304 //写数据
305 assign local_wdata = burst_wrdata;
306 
307 //DDR2写应答,即写FIFO的读使能
308 assign burst_wrack = (state == WR_RDY || (state == WR && local_ready)) ? 1'b1 : 1'b0;
309 
310 //写请求
311 assign local_write_req = (state == WR) ? 1'b1 : 1'b0;
312 
313 //读请求
314 assign local_read_req = (state == RD_ADDR) ? 1'b1 : 1'b0;
315 
316 //burstbegin信号,随便怎么写都行
317 assign local_burstbegin = ((state == WR && wrburst_cnt == `BURST_W'h0) || state == RD_ADDR) ? 1'b1 : 1'b0;
318 
319 
320 endmodule

 

三、仿真测试

  写突发和读突发设置为11,写入 1 到 11 共 11 个数,地址从 1 开始,看看波形是什么样的。

  1 `timescale 1ns/1ns  //时间精度
  2 `define    Clock 10 //时钟周期
  3 `include   "DDR2_param.v"
  4 
  5 module DDR2_burst_tb;
  6 //========================< 端口 >==========================================
  7 //DDR2 IP核接口 -------------------------------------
  8 reg                             pll_ref_clk         ;   //DDR2 参考时钟
  9 reg                             global_reset_n      ;   //全局复位信号;连接外部复位
 10 wire                            phy_clk             ;   //DDR2 IP核工作时钟
 11 wire                            reset_phy_clk_n     ;   //DDR2 IP核同步后的复位信号
 12 wire                            local_init_done     ;   //DDR2 IP核初始化完成信号
 13 //突发读写接口 --------------------------------------
 14 reg                             burst_rdreq         ;   //突发读请求
 15 reg                             burst_wrreq         ;   //突发写请求
 16 reg     [`BURST_W       -1:0]   burst_rdlen         ;   //突发读长度
 17 reg     [`BURST_W       -1:0]   burst_wrlen         ;   //突发写长度
 18 reg     [`LOCAL_ADDR_W  -1:0]   burst_rdaddr        ;   //突发读地址
 19 reg     [`LOCAL_ADDR_W  -1:0]   burst_wraddr        ;   //突发写地址
 20 wire    [`LOCAL_DATA_W  -1:0]   burst_rddata        ;   //突发读数据
 21 reg     [`LOCAL_DATA_W  -1:0]   burst_wrdata        ;   //突发写数据
 22 wire                            burst_rdack         ;   //突发读应答;连接FIFO
 23 wire                            burst_wrack         ;   //突发写应答;连接FIFO
 24 wire                            burst_rddone        ;   //突发读完成信号
 25 wire                            burst_wrdone        ;   //突发写完成信号
 26 //DDR2端口 ------------------------------------------
 27 wire                            mem_odt             ;   //DDR2片上终结信号
 28 wire                            mem_cs_n            ;   //DDR2片选信号
 29 wire                            mem_cke             ;   //DDR2时钟使能信号
 30 wire    [`MEM_ADDR_W    -1:0]   mem_addr            ;   //DDR2地址总线
 31 wire    [`MEM_BANK_W    -1:0]   mem_ba              ;   //DDR2BANK信号
 32 wire                            mem_ras_n           ;   //DDR2行地址选择信号
 33 wire                            mem_cas_n           ;   //DDR2列地址选择信号
 34 wire                            mem_we_n            ;   //DDR2写使能信号
 35 wire    [`MEM_DM_W      -1:0]   mem_dm              ;   //DDR2数据掩膜信号
 36 wire                            mem_clk             ;   //DDR2时钟信号
 37 wire                            mem_clk_n           ;   //DDR2时钟反相信号
 38 wire    [`MEM_DQ_W      -1:0]   mem_dq              ;   //DDR2数据总线
 39 wire    [`MEM_DQS_W     -1:0]   mem_dqs             ;   //DDR2数据源同步信号
 40 //==========================================================================
 41 //==    模块例化
 42 //==========================================================================
 43 DDR2_burst u_DDR2_burst
 44 (
 45     //IP核引出接口 ----------------------------------
 46     .pll_ref_clk            (pll_ref_clk            ),  //DDR2 参考时钟 
 47     .global_reset_n         (global_reset_n         ),  //全局复位信号,连接外部复位
 48     .phy_clk                (phy_clk                ),  //DDR2 IP核工作时钟
 49     .reset_phy_clk_n        (reset_phy_clk_n        ),  //DDR2 IP核同步后的复位信号  
 50     .local_init_done        (local_init_done        ),  //DDR2 IP核初始化完成信号
 51     //突发读写接口 ----------------------------------
 52     .burst_rdreq            (burst_rdreq            ),  //突发读请求
 53     .burst_wrreq            (burst_wrreq            ),  //突发写请求
 54     .burst_rdlen            (burst_rdlen            ),  //突发读长度
 55     .burst_wrlen            (burst_wrlen            ),  //突发写长度
 56     .burst_rdaddr           (burst_rdaddr           ),  //突发读地址
 57     .burst_wraddr           (burst_wraddr           ),  //突发写地址
 58     .burst_rddata           (burst_rddata           ),  //突发读数据
 59     .burst_wrdata           (burst_wrdata           ),  //突发写数据
 60     .burst_rdack            (burst_rdack            ),  //突发读应答,连接FIFO
 61     .burst_wrack            (burst_wrack            ),  //突发写应答,连接FIFO
 62     .burst_rddone           (burst_rddone           ),  //突发读完成信号
 63     .burst_wrdone           (burst_wrdone           ),  //突发写完成信号   
 64     //芯片接口 --------------------------------------
 65     .mem_odt                (mem_odt                ),  //DDR2片上终结信号
 66     .mem_cs_n               (mem_cs_n               ),  //DDR2片选信号
 67     .mem_cke                (mem_cke                ),  //DDR2时钟使能信号
 68     .mem_addr               (mem_addr               ),  //DDR2地址总线  
 69     .mem_ba                 (mem_ba                 ),  //DDR2bank信号
 70     .mem_ras_n              (mem_ras_n              ),  //DDR2行地址选择信号
 71     .mem_cas_n              (mem_cas_n              ),  //DDR2列地址选择信号
 72     .mem_we_n               (mem_we_n               ),  //DDR2写使能信号
 73     .mem_dm                 (mem_dm                 ),  //DDR2数据掩膜信号
 74     .mem_clk                (mem_clk                ),  //DDR2时钟信号
 75     .mem_clk_n              (mem_clk_n              ),  //DDR2时钟反相信号
 76     .mem_dq                 (mem_dq                 ),  //DDR2数据总线
 77     .mem_dqs                (mem_dqs                )   //DDR2数据源同步信号
 78 );
 79 
 80 DDR2_mem_model mem
 81 (
 82     .mem_dq                 (mem_dq                 ),
 83     .mem_dqs                (mem_dqs                ),
 84     .mem_dqs_n              (mem_dqs_n              ),
 85     .mem_addr               (mem_addr               ),
 86     .mem_ba                 (mem_ba                 ),
 87     .mem_clk                (mem_clk                ),
 88     .mem_clk_n              (mem_clk_n              ),
 89     .mem_cke                (mem_cke                ),
 90     .mem_cs_n               (mem_cs_n               ),
 91     .mem_ras_n              (mem_ras_n              ),
 92     .mem_cas_n              (mem_cas_n              ),
 93     .mem_we_n               (mem_we_n               ),
 94     .mem_dm                 (mem_dm                 ),
 95     .mem_odt                (mem_odt                )
 96 );
 97 //==========================================================================
 98 //==    时钟信号和复位信号
 99 //==========================================================================
100 initial begin
101     pll_ref_clk = 1;
102     forever
103         #(`Clock/2) pll_ref_clk = ~pll_ref_clk;
104 end
105 
106 initial begin
107     global_reset_n = 0; #(`Clock*20+1);
108     global_reset_n = 1;
109 end
110 //==========================================================================
111 //==    设计输入信号
112 //==========================================================================
113 initial begin
114     burst_wrreq     = 0;
115     burst_rdreq     = 0;
116     burst_wrlen     = 11;
117     burst_rdlen     = 11;
118     burst_wraddr    = 0;
119     burst_rdaddr    = 0;
120     burst_wrdata    = 0;
121     #(`Clock*20+1);
122     //--------------------------------------------------- 第1次
123     @(posedge u_DDR2_burst.rst_n); //初始化完成,复位结束
124     //
125     @(posedge phy_clk);
126     burst_wraddr    = 1;
127     burst_wrreq     = 1;
128     @(posedge phy_clk);
129     burst_wrreq     = 0;
130     //
131     @(posedge burst_wrdone);
132     @(posedge phy_clk);
133     burst_rdaddr    = 1;
134     burst_rdreq     = 1;
135     @(posedge phy_clk);
136     burst_rdreq     = 0;
137     //--------------------------------------------------- 第2次
138     //
139     @(posedge burst_rddone)
140     @(posedge phy_clk);
141     burst_wraddr    = 1;
142     burst_wrreq     = 1;
143     @(posedge phy_clk);
144     burst_wrreq     = 0;
145     //
146     @(posedge burst_wrdone);
147     @(posedge phy_clk);
148     burst_rdaddr    = 1;
149     burst_rdreq     = 1;
150     @(posedge phy_clk);
151     burst_rdreq     = 0;
152 end
153 
154 //设计写数据
155 task gen_data;
156 integer  i;
157     begin
158         @(posedge burst_wrack);
159         @(posedge phy_clk);
160         
161         for(i=1;i<=11;i=i+1) begin
162             burst_wrdata = i;
163             
164             @(posedge phy_clk);
165             if(!burst_wrack)
166                 i = i-1;
167         end
168         
169     end
170 endtask
171 
172 initial begin
173     gen_data;
174     gen_data;
175 end
176 
177 
178 
179 endmodule

 

四、仿真波形

  由波形可以看出各个信号的变化过程,上半部分是写,下半部分是读。有些信号在末尾会出现别的数字,实际上是废弃值,并没有取到。从波形可以看出,数据写入后又完整的读出来了,说明本次设计准确无误。

  如果有需要的同学,直接将本模块复制成一个 DDR2_param.v 文件和 DDR2_burst.v 文件即可使用。如果用不了也没办法,反正我的能用。

 

参考资料:锆石科技FPGA教程

 

posted @ 2020-06-15 21:13  咸鱼IC  阅读(1350)  评论(5编辑  收藏  举报