当前位置:   article > 正文

FPGA中DDR3 MIG ip核使用说明_什么情况下使用mig ip

什么情况下使用mig ip

        此篇是我在学习中做的归纳与总结,其中如果存在版权或知识错误请直接联系我,欢迎留言。
PS:本着知识共享的原则,此篇博客可以随意转载,但请标明出处!

目录

1、DDR3工作原理

简介:

DDR基础操作步骤:

DDR读操作:

DDR写操作:

预充电:

2、DDR3 MIG ip核配置与调用

MIG ip核配置:

关键代码:


1、DDR3工作原理

简介:

DDR3(全称:double-data-rate 3 synchronous dynamic RAM),即第三代双倍速率同步动态随机存储器。

        1、同步是指DDR3数据的读取写入是按时钟同步的;

        2、动态是指DDR3中的数据掉电无法保存,且需要周期性的刷新,才能保持数据;

        3、随机存取即可以随机操作任一地址的数据;

        4、double-data-rate,即时钟的上升沿和下降沿都发生数据传输。

micron的MT41K128M16TW;MT41K为型号,128M16表示DDR3容量大小为128M*16 = 2Gb;

        该DDR3是8Bank配置,即BA[2:0];数据位宽配置为16bit;行地址A[13:0],列地址BA[2:0],那么算下来正好2Gb。

        1、控制器单元:包括输入命令解析,模式配置&控制部分;

        2、行地址选通单元:行激活通过此处操作;

        3、Bank控制逻辑:行/列地址解码用到bank选通

        4、列地址选择单元,读写操作同时在打开列地址的时候送到1;

        5、锁存与控制逻辑:刷新与预充电用到该模块;

        6、内部存储阵列,此处分8个bank,每个bank分16384行,128列;

        7、读写数据缓存及接口驱动; dq数据在此变换位宽后内外交互;

DDR基础操作步骤:

启动:上电->解复位->初始化->ZQCL->LEVELING->IDLE(READY)

读:IDLE—>行激活—>读数据(1次或多次突发)—>预充电—>IDLE

写:IDLE—>行激活—>写数据(1次或多次突发)—>预充电—>IDLE

刷新:IDLE->REF->IDLE

自刷新的进入与退出:IDLE->SFR->IDLE

定期校正:IDLE—>ZQCS—>IDLE,一般外部温度或电压改变时操作

动态更改配置:IDLE->MRS/MPR->IDLE

DDR读操作:

 ddr发起一次读的过程包含有:

        1、Active命令—含带地址位,以选择Bank和Row地址(BAO-BA2选择BANK、AO-A13选择Row)。用于打开一个工作行。

        2、Read命令—含带突发操作的起始Column地址和bank号,打开对应gating的列;

        3、数据经过特定的延时(CL+AL);将数据传出IO;

        4、完成数据传出后,需将当前cache的数据刷回存储整列并关闭当前工作行(携带命令和BA信息);[是否发布自动预充电命令(通过A10)]

DDR写操作:

        (第三步与读操作不同,其他与读操作一致)

        1、Active命令—含带地址位,以选择Bank和Row地址(BAO-BA2选择BANK、AO-A13选择Row)。用于打开一个工作行。

        2、Write命令—含带突发操作的起始Column地址和bank号,打开对应gating的列;

        3、数据经过特定的延时(CL+AL);将数据传入IO;

        4、完成数据传出后,需将当前cache的数据刷回存储整列并关闭当前工作行(携带命令和BA信息);[是否发布自动预充电命令(通过A10)]

预充电:

        由于SDRAM的寻址具体独占性,所以在进行完读写操作后,如果要对同—L-Bank的另一行进行寻址,就要将原来有效(工作)的L行关闭,重新发送行/列地址。

        L-Bank关闭现有工作行,准备打开新行的操作就是预充电(Precharge)。

        预充电可以通过单独的命令控制,也可以通过辅助设定让芯片在每次读写操作之后自动进行预充电。(A10)

        预充电的本质是一种对工作行中所有存储体进行数据重写,并对行地址进行复位,同时释放S-AMP。

2、DDR3 MIG ip核配置与调用

        上海勤谋电子科技有限公司推出的QM_XC7A35T开发板,采用Xilinx最新推出的7系列的XC7A35T-1FTG256C作为主控FPGA。

MIG ip核配置:

        选择DDR3控制器的类型为“DDR3 SDRAM

 

        选择DDR3颗粒的工作频率为400MHz,1系列的最高支持频率为400MHz,所以测试时不要采用更高的测试工作频率,内存型号为:MT41J128M16HA-15E,实际上的DDR3数据率是时钟频率的2倍,单击Next:

        配置“Controller Chip Select Pin”为“Disable”,这是为了在硬件设计时节省了一个FPGA的IO引脚资源,直接将DDR3 SDRAM的Chip Select引脚拉低保持片选信号一直有效

        System Clock和Reference Clock时钟输入,Internal Vref等配置如下图所示

        选择“Fixed Pin Out”

 

 单击“Read XDC/UCF”按钮,然后跳出 “Load your UCF” 对话框,选择资料包里提供或者网上的“DDR3.ucf”文件。

 DDR3.ucf 文件:

  1. NET "ddr3_dq[0]" LOC = "F15" ;
  2. NET "ddr3_dq[1]" LOC = "F13" ;
  3. NET "ddr3_dq[2]" LOC = "E16" ;
  4. NET "ddr3_dq[3]" LOC = "D11" ;
  5. NET "ddr3_dq[4]" LOC = "E12" ;
  6. NET "ddr3_dq[5]" LOC = "E13" ;
  7. NET "ddr3_dq[6]" LOC = "D16" ;
  8. NET "ddr3_dq[7]" LOC = "E11" ;
  9. NET "ddr3_dq[8]" LOC = "G12" ;
  10. NET "ddr3_dq[9]" LOC = "J16" ;
  11. NET "ddr3_dq[10]" LOC = "G16" ;
  12. NET "ddr3_dq[11]" LOC = "J15" ;
  13. NET "ddr3_dq[12]" LOC = "H14" ;
  14. NET "ddr3_dq[13]" LOC = "H12" ;
  15. NET "ddr3_dq[14]" LOC = "H16" ;
  16. NET "ddr3_dq[15]" LOC = "H13" ;
  17. NET "ddr3_dm[0]" LOC = "F12" ;
  18. NET "ddr3_dm[1]" LOC = "H11" ;
  19. NET "ddr3_dqs_p[0]" LOC = "D14" ;
  20. NET "ddr3_dqs_n[0]" LOC = "D15" ;
  21. NET "ddr3_dqs_p[1]" LOC = "G14" ;
  22. NET "ddr3_dqs_n[1]" LOC = "F14" ;
  23. NET "ddr3_addr[13]" LOC = "B11" ;
  24. NET "ddr3_addr[12]" LOC = "A8" ;
  25. NET "ddr3_addr[11]" LOC = "A9" ;
  26. NET "ddr3_addr[10]" LOC = "B12" ;
  27. NET "ddr3_addr[9]" LOC = "A13" ;
  28. NET "ddr3_addr[8]" LOC = "D8" ;
  29. NET "ddr3_addr[7]" LOC = "A12" ;
  30. NET "ddr3_addr[6]" LOC = "D9" ;
  31. NET "ddr3_addr[5]" LOC = "B10" ;
  32. NET "ddr3_addr[4]" LOC = "C9" ;
  33. NET "ddr3_addr[3]" LOC = "C14" ;
  34. NET "ddr3_addr[2]" LOC = "A14" ;
  35. NET "ddr3_addr[1]" LOC = "C8" ;
  36. NET "ddr3_addr[0]" LOC = "B14" ;
  37. NET "ddr3_ba[2]" LOC = "B15" ;
  38. NET "ddr3_ba[1]" LOC = "A15" ;
  39. NET "ddr3_ba[0]" LOC = "C16" ;
  40. NET "ddr3_ck_p[0]" LOC = "B9" ;
  41. NET "ddr3_ck_n[0]" LOC = "A10" ;
  42. NET "ddr3_ras_n" LOC = "B16" ;
  43. NET "ddr3_cas_n" LOC = "C11" ;
  44. NET "ddr3_we_n" LOC = "C12" ;
  45. NET "ddr3_reset_n" LOC = "E15" ;
  46. NET "ddr3_cke[0]" LOC = "D13" ;
  47. NET "ddr3_odt[0]" LOC = "C13" ;

然后完成IP核配置,MIG IP核例化如下所示:

  1. assign app_wdf_wren = app_en & app_wdf_rdy & app_rdy & (app_cmd == 3'd0);
  2. assign app_wdf_end = app_wdf_wren;
  3. assign app_addr = ( app_cmd == 3'd1 ) ? read_addr : write_addr ;
  4. mig_7series_0 u_mig_7series_0 (
  5. // Memory interface ports
  6. .ddr3_addr (ddr3_addr), // output [13:0] ddr3_addr
  7. .ddr3_ba (ddr3_ba), // output [2:0] ddr3_ba
  8. .ddr3_cas_n (ddr3_cas_n), // output ddr3_cas_n
  9. .ddr3_ck_n (ddr3_ck_n), // output [0:0] ddr3_ck_n
  10. .ddr3_ck_p (ddr3_ck_p), // output [0:0] ddr3_ck_p
  11. .ddr3_cke (ddr3_cke), // output [0:0] ddr3_cke
  12. .ddr3_ras_n (ddr3_ras_n), // output ddr3_ras_n
  13. .ddr3_reset_n (ddr3_reset_n), // output ddr3_reset_n
  14. .ddr3_we_n (ddr3_we_n), // output ddr3_we_n
  15. .ddr3_dq (ddr3_dq), // inout [15:0] ddr3_dq
  16. .ddr3_dqs_n (ddr3_dqs_n), // inout [1:0] ddr3_dqs_n
  17. .ddr3_dqs_p (ddr3_dqs_p), // inout [1:0] ddr3_dqs_p
  18. .init_calib_complete (init_calib_complete), // output init_calib_complete
  19. .ddr3_dm (ddr3_dm), // output [1:0] ddr3_dm
  20. .ddr3_odt (ddr3_odt), // output [0:0] ddr3_odt
  21. // Application interface ports
  22. .app_addr (app_addr), // input [27:0] app_addr
  23. .app_cmd (app_cmd), // input [2:0] app_cmd
  24. .app_en (app_en), // input app_en
  25. .app_wdf_data (app_wdf_data), // input [127:0] app_wdf_data
  26. .app_wdf_end (app_wdf_end), // input app_wdf_end
  27. .app_wdf_wren (app_wdf_wren), // input app_wdf_wren
  28. .app_rd_data (app_rd_data), // output [127:0] app_rd_data
  29. .app_rd_data_end (app_rd_data_end), // output app_rd_data_end
  30. .app_rd_data_valid (app_rd_data_valid), // output app_rd_data_valid
  31. .app_rdy (app_rdy), // output app_rdy
  32. .app_wdf_rdy (app_wdf_rdy), // output app_wdf_rdy
  33. .app_sr_req (1'b0), // input app_sr_req
  34. .app_ref_req (1'b0), // input app_ref_req
  35. .app_zq_req (1'b0), // input app_zq_req
  36. .app_sr_active (app_sr_active), // output app_sr_active
  37. .app_ref_ack (app_ref_ack), // output app_ref_ack
  38. .app_zq_ack (app_zq_ack), // output app_zq_ack
  39. .ui_clk (ui_clk), // output ui_clk
  40. .ui_clk_sync_rst (ui_clk_sync_rst), // output ui_clk_sync_rst
  41. .app_wdf_mask ( 16'd0 ), // input [15:0] app_wdf_mask
  42. // System Clock Ports
  43. .sys_clk_i (ddrclk_200Mhz),
  44. .sys_rst (~ ddr_rst_n) // input sys_rst
  45. );

        本文阐述的DDR3应用场景为,首先读取SPI-Flash中数据,然后存储至DDR3中,最后读取DDR3中数据输出。

        Verilog SPI-Flash读写总线控制模块程序:https://blog.csdn.net/m0_37779673/article/details/118033580

关键代码:

  1. always @(posedge ui_clk ) begin //DDR_output_clk is 200MHz
  2. if (!sys_rst_n) begin
  3. /// DDR3
  4. app_en <= 1'b0 ;
  5. app_cmd <= 3'd0 ;
  6. write_addr <= 28'd0 ;
  7. read_addr <= 28'd0 ;
  8. app_wdf_data <= 128'd0 ;
  9. end else begin
  10. case(top_state)
  11. 4'd0: begin // begin state
  12. if ( app_wdf_rdy & app_rdy ) begin // DDR3 is ready
  13. led_0 <= 0 ;
  14. flash_state <= 4'd0 ; //read flash ID
  15. end else
  16. led_0 <= 1;
  17. if ( flash_flag > 4'd0 ) //已读出一批数据
  18. top_state <= 4'd1 ;
  19. end
  20. 4'd1: begin // read Flash_data
  21. if ( rd_flash_data_cnt < 23'd8000000 ) begin //判断读取flash中数据数量
  22. cnt_rd_flash_data <= 3'd1 ;
  23. rd_flash_data_cnt <= rd_flash_data_cnt + 23'd4 ;
  24. flash_state <= 4'd1 ; //read flash 4bytes data
  25. flash_addr <= flash_addr + 24'd32 ;
  26. top_state <= 4'd2 ;
  27. end else begin
  28. rd_flash_data_cnt <= 0 ;
  29. flash_addr <= 0 ;
  30. top_state <= 4'd4 ;
  31. end
  32. end
  33. 4'd2: begin // build up DDR3 128bit save data
  34. flag_read_byte0 <= flag_read_byte ;
  35. l2h_flag_read_byte <= ( ~ flag_read_byte0 ) & flag_read_byte ;
  36. if ( l2h_flag_read_byte && (cnt_rd_flash_data == 1) ) begin
  37. cnt_rd_flash_data <= cnt_rd_flash_data + 3'd1 ;
  38. if ( flash_flag[0] == 1 ) begin
  39. app_wdf_data [ 7 : 0 ] <= read_flash_data0 ;
  40. end else begin
  41. app_wdf_data [ 7 : 0 ] <= 8'b0 ;
  42. end
  43. if ( flash_flag[1] == 1 ) begin
  44. app_wdf_data [ 15 : 8 ] <= read_flash_data1 ;
  45. end else begin
  46. app_wdf_data [ 15 : 8 ] <= 8'b0 ;
  47. end
  48. if ( flash_flag[2] == 1 ) begin
  49. app_wdf_data [ 23 : 16 ] <= read_flash_data2 ;
  50. end else begin
  51. app_wdf_data [ 23 : 16 ] <= 8'b0 ;
  52. end
  53. if ( flash_flag[3] == 1 ) begin
  54. app_wdf_data [ 31 : 24 ] <= read_flash_data3 ;
  55. end else begin
  56. app_wdf_data [ 31 : 24 ] <= 8'b0 ;
  57. end
  58. end
  59. if ( l2h_flag_read_byte && (cnt_rd_flash_data == 2) ) begin
  60. cnt_rd_flash_data <= cnt_rd_flash_data + 3'd1 ;
  61. if ( flash_flag[0] == 1 ) begin
  62. app_wdf_data [ 39 : 32 ] <= read_flash_data0 ;
  63. end else begin
  64. app_wdf_data [ 39 : 32 ] <= 8'b0 ;
  65. end
  66. if ( flash_flag[1] == 1 ) begin
  67. app_wdf_data [ 47 : 40 ] <= read_flash_data1 ;
  68. end else begin
  69. app_wdf_data [ 47 : 40 ] <= 8'b0 ;
  70. end
  71. if ( flash_flag[2] == 1 ) begin
  72. app_wdf_data [ 55 : 48 ] <= read_flash_data2 ;
  73. end else begin
  74. app_wdf_data [ 55 : 48 ] <= 8'b0 ;
  75. end
  76. if ( flash_flag[3] == 1 ) begin
  77. app_wdf_data [ 63 : 56 ] <= read_flash_data3 ;
  78. end else begin
  79. app_wdf_data [ 63 : 56 ] <= 8'b0 ;
  80. end
  81. end
  82. if ( l2h_flag_read_byte && (cnt_rd_flash_data == 3) ) begin
  83. cnt_rd_flash_data <= cnt_rd_flash_data + 3'd1 ;
  84. if ( flash_flag[0] == 1 ) begin
  85. app_wdf_data [ 71 : 64 ] <= read_flash_data0 ;
  86. end else begin
  87. app_wdf_data [ 71 : 64 ] <= 8'b0 ;
  88. end
  89. if ( flash_flag[1] == 1 ) begin
  90. app_wdf_data [ 79 : 72 ] <= read_flash_data1 ;
  91. end else begin
  92. app_wdf_data [ 79 : 72 ] <= 8'b0 ;
  93. end
  94. if ( flash_flag[2] == 1 ) begin
  95. app_wdf_data [ 87 : 80 ] <= read_flash_data2 ;
  96. end else begin
  97. app_wdf_data [ 87 : 80 ] <= 8'b0 ;
  98. end
  99. if ( flash_flag[3] == 1 ) begin
  100. app_wdf_data [ 95 : 88 ] <= read_flash_data3 ;
  101. end else begin
  102. app_wdf_data [ 95 : 88 ] <= 8'b0 ;
  103. end
  104. end
  105. if ( l2h_flag_read_byte && (cnt_rd_flash_data == 4) ) begin
  106. if ( flash_flag[0] == 1 ) begin
  107. app_wdf_data [ 103 : 96 ] <= read_flash_data0 ;
  108. end else begin
  109. app_wdf_data [ 103 : 96 ] <= 8'b0 ;
  110. end
  111. if ( flash_flag[1] == 1 ) begin
  112. app_wdf_data [ 111 : 104 ] <= read_flash_data1 ;
  113. end else begin
  114. app_wdf_data [ 111 : 104 ] <= 8'b0 ;
  115. end
  116. if ( flash_flag[2] == 1 ) begin
  117. app_wdf_data [ 119 : 112 ] <= read_flash_data2 ;
  118. end else begin
  119. app_wdf_data [ 119 : 112 ] <= 8'b0 ;
  120. end
  121. if ( flash_flag[3] == 1 ) begin
  122. app_wdf_data [ 127 : 120 ] <= read_flash_data3 ;
  123. end else begin
  124. app_wdf_data [ 127 : 120 ] <= 8'b0 ;
  125. end
  126. end
  127. if ( (l2h_flag_read_byte == 0 ) && ( cnt_rd_flash_data == 3'd4 )) begin
  128. top_state <= 4'd3 ;
  129. flash_state <= 4'd2 ;
  130. once_data_flag <= 1 ;
  131. end
  132. end
  133. 4'd3: begin // read 4bytes Flash data end --> DDR3 trans_end
  134. if ( init_calib_complete ) begin //DD3 loading finished
  135. if( app_rdy & app_wdf_rdy ) begin//等待这两个信号拉高就使命令有效
  136. if ( once_data_flag ) begin
  137. once_data_flag <= 0 ;
  138. app_cmd <= 3'd0 ; // write commend
  139. app_en <= 1'b1 ;
  140. write_addr <= write_addr + 28'd8;
  141. end else begin
  142. top_state <= 4'd1 ;
  143. app_en <= 1'b0 ;
  144. end
  145. end
  146. end
  147. end
  148. 4'd4: begin // DDR3 --> 输出数据
  149. end
  150. default : ;
  151. endcase
  152. end
  153. end

参考文献:

1、ug586_7Series_MIS.pdf

2、MT41J128M16JT-125K.pdf

3、ug470_7Series_Config.pdf

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/825956
推荐阅读
相关标签
  

闽ICP备14008679号