Altera DDR2 IP核学习总结3-----------DDR2 IP核的使用

时间:2022-08-31 23:14:02

Altera DDR2 IP核学习总结3-----------DDR2 IP核的使用

根据上一篇生成的IP核,例化之后如上图,Local开头的数据是用户侧数据,其他数据暂时不用纠结,不用管。

Altera DDR2 IP核学习总结3-----------DDR2 IP核的使用

这些是需要关注的信号,但是初学阶段很难对这些信号形成具体的概念,这里参考明德扬的代码进行二次封装。

  1. module ddr2_intf(
  2. clk_in           ,
  3. clk_out          ,
  4. rst_n            ,
  5. local_address    ,
  6. local_write_req  ,
  7. local_read_req   ,
  8. local_wdata      ,
  9. local_ready      ,
  10. local_rdata      ,
  11. local_rdata_valid,
  12. local_init_done  ,
  13. local_burstbegin ,
  14. user_wdata       ,
  15. user_wdata_en    ,
  16. user_waddr       ,
  17. user_raddr       ,
  18. user_rdata_en    ,
  19. user_rdata       ,
  20. user_rdata_vld   ,
  21. user_wdata_rdy   ,
  22. user_rdata_rdy
  23. );
  24. parameter           ADDR_W     = 23       ;
  25. parameter           DDR_DATA_W = 32       ;
  26. parameter           BURST      = 2        ;
  27. parameter           USE_DATA_W = DDR_DATA_W * BURST;
  28. parameter           FIFO_W     = USE_DATA_W + ADDR_W;
  29. input                   clk_in           ;
  30. input                   rst_n            ;
  31. input                   clk_out          ;
  32. input                   local_ready      ;
  33. input  [DDR_DATA_W-1:0] local_rdata      ;
  34. input                   local_rdata_valid;
  35. input                   local_init_done  ;
  36. input  [USE_DATA_W-1:0] user_wdata       ;
  37. input                   user_wdata_en    ;
  38. input  [ADDR_W-1:0]     user_waddr       ;
  39. input  [ADDR_W-1:0]     user_raddr       ;
  40. input                   user_rdata_en    ;
  41. output [ADDR_W-1:0]     local_address    ;
  42. output                  local_write_req  ;
  43. output                  local_read_req   ;
  44. output [DDR_DATA_W-1:0] local_wdata      ;
  45. output                  local_burstbegin ;
  46. output [USE_DATA_W-1:0] user_rdata       ;
  47. output                  user_rdata_vld   ;
  48. output                  user_wdata_rdy   ;
  49. output                  user_rdata_rdy   ;
  50. reg    [USE_DATA_W-1:0] user_rdata       ;
  51. reg                     user_rdata_vld   ;
  52. reg                     user_wdata_rdy   ;
  53. reg                     user_rdata_rdy   ;
  54. wire   [ADDR_W-1:0]     local_address    ;
  55. wire                    local_write_req  ;
  56. wire                    local_read_req   ;
  57. wire   [DDR_DATA_W-1:0] local_wdata      ;
  58. wire                    local_burstbegin ;
  59. wire   [FIFO_W-1:0]     wfifo_wdata      ;
  60. wire                    wfifo_wrreq      ;
  61. wire                    wfifo_empty      ;
  62. wire                    wfifo_rdreq      ;
  63. wire   [FIFO_W-1:0]     wfifo_q          ;
  64. wire   [       5:0]     wfifo_usedw      ;
  65. wire   [ADDR_W-1:0]     rfifo_wdata      ;
  66. wire                    rfifo_wrreq      ;
  67. wire                    rfifo_empty      ;
  68. wire                    rfifo_rdreq      ;
  69. wire   [ADDR_W-1:0]     rfifo_q          ;
  70. wire   [       5:0]     rfifo_usedw      ;
  71. reg    [FIFO_W  :0]     ififo_wdata      ;
  72. reg                     ififo_wrreq      ;
  73. wire                    ififo_empty      ;
  74. wire                    ififo_rdreq      ;
  75. wire   [FIFO_W  :0]     ififo_q          ;
  76. wire   [       5:0]     ififo_usedw      ;
  77. wire                    ififo_rdy        ;
  78. reg    [USE_DATA_W-1:0] gfifo_wdata      ;
  79. reg                     gfifo_wrreq      ;
  80. wire                    gfifo_empty      ;
  81. wire                    gfifo_rdreq      ;
  82. wire   [USE_DATA_W-1:0] gfifo_q          ;
  83. wire   [       5:0]     gfifo_usedw      ;
  84. reg [ 1:0]              cnt0             ;
  85. wire                    add_cnt0         ;
  86. wire                    end_cnt0         ;
  87. reg [ 2:0]              x                ;
  88. reg [ 3:0]              cnt1             ;
  89. wire                    add_cnt1         ;
  90. wire                    end_cnt1         ;
  91. fifo_ahead_sys #(.DATA_W(FIFO_W),.DEPT_W(64)) u_wfifo(
  92. .aclr           (~rst_n             ),
  93. .clock          (clk_in             ),
  94. .data           (wfifo_wdata        ),
  95. .rdreq          (wfifo_rdreq        ),
  96. .wrreq          (wfifo_wrreq        ),
  97. .empty          (wfifo_empty        ),
  98. .q              (wfifo_q            ),
  99. .usedw          (wfifo_usedw        )
  100. );
  101. fifo_ahead_sys #(.DATA_W(ADDR_W),.DEPT_W(64)) u_rfifo(
  102. .aclr           (~rst_n             ),
  103. .clock          (clk_in             ),
  104. .data           (rfifo_wdata        ),
  105. .rdreq          (rfifo_rdreq        ),
  106. .wrreq          (rfifo_wrreq        ),
  107. .empty          (rfifo_empty        ),
  108. .q              (rfifo_q            ),
  109. .usedw          (rfifo_usedw        )
  110. );
  111. fifo_ahead_asy #(.DATA_W(FIFO_W+1),.DEPT_W(64))  u_ififo(
  112. .aclr    (~rst_n        ),
  113. .data    (ififo_wdata   ),
  114. .rdclk   (clk_out       ),
  115. .rdreq   (ififo_rdreq   ),
  116. .wrclk   (clk_in        ),
  117. .wrreq   (ififo_wrreq   ),
  118. .q       (ififo_q       ),
  119. .rdempty (ififo_empty ),
  120. .wrusedw (ififo_usedw )
  121. );
  122. assign wfifo_wdata = {user_waddr,user_wdata};
  123. assign wfifo_wrreq = user_wdata_en          ;
  124. assign wfifo_rdreq = ififo_rdy && wfifo_empty==0 && rfifo_empty==1;
  125. assign rfifo_wdata = user_raddr             ;
  126. assign rfifo_wrreq = user_rdata_en          ;
  127. assign rfifo_rdreq = ififo_rdy && rfifo_empty==0;
  128. always  @(posedge clk_in or negedge rst_n)begin
  129. if(rst_n==1'b0)begin
  130. ififo_wdata <= 0;
  131. end
  132. else if(wfifo_rdreq) begin
  133. ififo_wdata <= {1'b1,wfifo_q};
  134. end
  135. else if(rfifo_rdreq)begin
  136. ififo_wdata <= {1'b0,rfifo_q,{USE_DATA_W{1'b0}}};
  137. end
  138. end
  139. always  @(posedge clk_in or negedge rst_n)begin
  140. if(rst_n==1'b0)begin
  141. ififo_wrreq <= 0;
  142. end
  143. else begin
  144. ififo_wrreq <= wfifo_rdreq || rfifo_rdreq;
  145. end
  146. end
  147. assign ififo_rdy = ififo_usedw<40;
  148. always  @(posedge clk_in or negedge rst_n)begin
  149. if(rst_n==1'b0)begin
  150. user_wdata_rdy <= 0;
  151. end
  152. else begin
  153. user_wdata_rdy <= wfifo_usedw<40;
  154. end
  155. end
  156. always  @(posedge clk_in or negedge rst_n)begin
  157. if(rst_n==1'b0)begin
  158. user_rdata_rdy <= 0;
  159. end
  160. else begin
  161. user_rdata_rdy <= rfifo_usedw<40;
  162. end
  163. end
  164. wire      local_read_req_tmp;
  165. assign local_wdata     = ififo_q[USE_DATA_W-DDR_DATA_W*cnt0-1 -:DDR_DATA_W];
  166. assign local_address   = ififo_q[FIFO_W-1 -:ADDR_W];
  167. assign local_write_req = ififo_q[FIFO_W]    && ififo_empty==0 && local_init_done;
  168. assign local_read_req_tmp  = ififo_q[FIFO_W]==0 && ififo_empty==0 && local_init_done;
  169. assign local_read_req      = local_read_req_tmp && cnt0==1-1;
  170. assign local_burstbegin= add_cnt0 && cnt0==1-1;
  171. assign ififo_rdreq     =  end_cnt0;
  172. reg     ififo_q_ff0;
  173. always  @(posedge clk_out or negedge rst_n)begin
  174. if(rst_n==1'b0)begin
  175. ififo_q_ff0<=0;
  176. end
  177. else begin
  178. ififo_q_ff0<=ififo_q[FIFO_W];
  179. end
  180. end
  181. always @(posedge clk_out or negedge rst_n)begin
  182. if(!rst_n)begin
  183. cnt0 <= 0;
  184. end
  185. else if(add_cnt0)begin
  186. if(end_cnt0)
  187. cnt0 <= 0;
  188. else
  189. cnt0 <= cnt0 + 1;
  190. end
  191. end
  192. assign add_cnt0 = (local_write_req||local_read_req_tmp)&&local_ready;
  193. assign end_cnt0 = add_cnt0 && cnt0==2-1;
  194. always @(posedge clk_out or negedge rst_n)begin
  195. if(!rst_n)begin
  196. cnt1 <= 0;
  197. end
  198. else if(add_cnt1)begin
  199. if(end_cnt1)
  200. cnt1 <= 0;
  201. else
  202. cnt1 <= cnt1 + 1;
  203. end
  204. end
  205. assign add_cnt1 = local_rdata_valid;
  206. assign end_cnt1 = add_cnt1 && cnt1==BURST-1 ;
  207. always  @(posedge clk_out or negedge rst_n)begin
  208. if(rst_n==1'b0)begin
  209. gfifo_wrreq <= 0;
  210. end
  211. else begin
  212. gfifo_wrreq <= end_cnt1;
  213. end
  214. end
  215. always  @(posedge clk_out or negedge rst_n)begin
  216. if(rst_n==1'b0)begin
  217. gfifo_wdata <= 0;
  218. end
  219. else if(add_cnt1)begin
  220. gfifo_wdata[USE_DATA_W - DDR_DATA_W*cnt1 -1  -:DDR_DATA_W] <= local_rdata;
  221. end
  222. end
  223. fifo_ahead_asy #(.DATA_W(USE_DATA_W),.DEPT_W(64))  u_gfifo(
  224. .aclr    (~rst_n        ),
  225. .data    (gfifo_wdata   ),
  226. .rdclk   (clk_in        ),
  227. .rdreq   (gfifo_rdreq   ),
  228. .wrclk   (clk_out       ),
  229. .wrreq   (gfifo_wrreq   ),
  230. .q       (gfifo_q       ),
  231. .rdempty (gfifo_empty ),
  232. .wrusedw (gfifo_usedw )
  233. );
  234. assign gfifo_rdreq = gfifo_empty==0;
  235. always  @(posedge clk_in or negedge rst_n)begin
  236. if(rst_n==1'b0)begin
  237. user_rdata <= 0;
  238. end
  239. else begin
  240. user_rdata <= gfifo_q;
  241. end
  242. end
  243. always  @(posedge clk_in or negedge rst_n)begin
  244. if(rst_n==1'b0)begin
  245. user_rdata_vld <= 0;
  246. end
  247. else begin
  248. user_rdata_vld <= gfifo_rdreq;
  249. end
  250. end
  251. endmodule
  1. ddr2_intf   u8(
  2. .clk_in           (  clk               ),
  3. .clk_out          (  phy_clk           ),
  4. .rst_n            (  rst_n_ff1             ),
  5. .local_address    (  local_address     ),
  6. .local_write_req  (  local_write_req   ),
  7. .local_read_req   (  local_read_req    ),
  8. .local_wdata      (  local_wdata       ),
  9. .local_ready      (  local_ready       ),
  10. .local_rdata      (  local_rdata       ),
  11. .local_rdata_valid(  local_rdata_valid ),
  12. .local_init_done  (  local_init_done   ),
  13. .local_burstbegin (  local_burstbegin  ),
  14. .user_wdata       (  user_wdata        ),
  15. .user_wdata_en    (  user_wdata_en     ),
  16. .user_waddr       (  user_waddr        ),
  17. .user_raddr       (  user_raddr        ),
  18. .user_rdata_en    (  user_rdata_en     ),
  19. .user_rdata       (  user_rdata        ),
  20. .user_rdata_vld   (  user_rdata_vld    ),
  21. .user_wdata_rdy   (  user_wdata_rdy    ),
  22. .user_rdata_rdy   (  user_rdata_rdy    )
  23. );

封装之后只需要关注

  1. .user_wdata       (  user_wdata        ),
  2. .user_wdata_en    (  user_wdata_en     ),
  3. .user_waddr       (  user_waddr        ),
  4. .user_raddr       (  user_raddr        ),
  5. .user_rdata_en    (  user_rdata_en     ),
  6. .user_rdata       (  user_rdata        ),
  7. .user_rdata_vld   (  user_rdata_vld    ),
  8. .user_wdata_rdy   (  user_wdata_rdy    ),
  9. .user_rdata_rdy   (  user_rdata_rdy    )

上面这9个信号,当user_wdata_rdy为高电平的时候可以写入数据,user_rdata_rdy   (  user_rdata_rdy    ) 可以读出数据,

写了一个简单的测试程序

  1. always @(posedge clk or negedge rst_n)begin
  2. if(!rst_n)begin
  3. cnt0 <= 0;
  4. end
  5. else if(add_cnt0)begin
  6. if(end_cnt0)
  7. cnt0 <= 0;
  8. else
  9. cnt0 <= cnt0 + 1;
  10. end
  11. end
  12. assign add_cnt0 = user_wdata_en ;
  13. assign end_cnt0 = add_cnt0 && cnt0==100          ;
  14. assign user_wdata_en = user_wdata_rdy && flag_add==0;
  15. always @(posedge clk or negedge rst_n)begin
  16. if(!rst_n)begin
  17. cnt1 <= 0;
  18. end
  19. else if(add_cnt1)begin
  20. if(end_cnt1)
  21. cnt1 <= 0;
  22. else
  23. cnt1 <= cnt1 + 1;
  24. end
  25. end
  26. assign add_cnt1 = user_rdata_en ;
  27. assign end_cnt1 = add_cnt1 && cnt1==100            ;
  28. assign user_rdata_en = user_rdata_rdy && flag_add==1;
  29. always  @(posedge clk)begin
  30. if(!rst_n)
  31. flag_add <= 0;
  32. else if(end_cnt0)
  33. flag_add <= 1;
  34. else if(end_cnt1)
  35. flag_add <= 0;
  36. end
  37. always  @(posedge clk or negedge rst_n)begin
  38. if(rst_n==1'b0)begin
  39. user_wdata    <= 0;
  40. user_waddr    <= 0;
  41. user_raddr    <= 0;
  42. end
  43. else begin
  44. user_wdata    <= cnt0    ;
  45. user_waddr    <= cnt0*2    ;
  46. user_raddr    <= cnt1*2    ;
  47. end
  48. end

当flag_add为低电平的时候往DDR2中写入数据,flag_add为高电平的时候读出数据。一共写入一百个数据。

使用signaltapII抓到的波形为

Altera DDR2 IP核学习总结3-----------DDR2 IP核的使用

local_init_done为高电平说明DDR2芯片初始化完成,user_wdata_en为高电平时写入数据,放大了看则是

Altera DDR2 IP核学习总结3-----------DDR2 IP核的使用

写入的数据为地址的二分之一

然后看一下读出来的数据

Altera DDR2 IP核学习总结3-----------DDR2 IP核的使用

这里很清楚的可以看出来user_rdata_en跟user_rdata_vld并不能对齐

放大了看

Altera DDR2 IP核学习总结3-----------DDR2 IP核的使用

当user_rdata_vld为高电平的时候输出的数据有效,

Altera DDR2 IP核学习总结3-----------DDR2 IP核的使用

测量一下得知user_rdata_en跟user_rdata_vld的偏差是21个数据,从Altera DDR2 IP核学习总结1中得知DRAM数据输出有延迟,结构相同的DDR2自然有相同的特性,大神称为首字惩罚特性(当时纠结这个问题半天,怎么也解决不了,多谢群里的大神)。

观察写入数据和读取数据一致,DDR2驱动成功。

Altera DDR2 IP核学习总结3-----------DDR2 IP核的使用的更多相关文章

  1. 关于AXI4-Stream to Video Out 和 Video Timing Controller IP核学习

    关于AXI4-Stream to Video Out 和 Video Timing Controller IP核学习 1.AXI4‐Stream to Video Out Top‐Level Sign ...

  2. xilinx AXI相关IP核学习

    xilinx AXI相关IP核学习 1.阅读PG044 (1)AXI4‐Stream to Video Out Top‐Level Signaling Interface (2)AXI4‐Stream ...

  3. TCP&sol;IP协议学习&lpar;五&rpar; 基于C&num; Socket的C&sol;S模型

    TCP/IP协议作为现代网络通讯的基石,内容包罗万象,直接去理解理论是比较困难的:然而通过实践先理解网络通讯的理解,在反过来理解学习TCP/IP协议栈就相对简单很多.C#通过提供的Socket API ...

  4. linux 学习 设置固定网Ip

    本人使用CentOs6.5 最近在学习linux操作系统,单在使用shell连接前都要使用ifconfig eth0 设置一个临时IP让我不胜其烦.决定学习设置一个固定IP 步骤: 1.登录计算机后使 ...

  5. Lattice 的 Framebuffer IP核使用调试笔记之IP核生成与参数设置

    本文由远航路上ing 原创,转载请标明出处. 这节笔记记录IP核的生成以及参数设置. 先再IP库里下载安装Framebuffer 的ipcore 并安装完毕. 一.IP核的生成: 1.先点击IP核则右 ...

  6. TCP&sol;IP协议学习笔记

    计算机网络基础知识复习汇总:计算机网络基础知识复习 HTTP协议的解析:剖析 HTTP 协议 一个系列的解析文章: TCP/IP详解学习笔记(1)-- 概述 TCP/IP详解学习笔记(2)-- 数据链 ...

  7. TCP&sol;IP协议学习之实例ping命令学习笔记

    TCP/IP协议学习之实例ping命令学习笔记(一) 一. 目的为了让网络协议学习更有效果,在真实网络上进行ping命令前相关知识的学习,暂时不管DNS,在内网中,进行2台主机间的ping命令的整个详 ...

  8. IP地址和子网划分学习笔记之《IP地址详解》

    2018-05-03 18:47:37   在学习IP地址和子网划分前,必须对进制计数有一定了解,尤其是二进制和十进制之间的相互转换,对于我们掌握IP地址和子网的划分非常有帮助,可参看如下目录详文. ...

  9. 【计算机网络】网络层学习笔记:总结IP,NAT和DHCP

    前言:这篇文章是学习网络层协议时候总结的笔记,前面的主要部分介绍的都是IP协议, 后半部分介绍NAT协议和DHCP协议 参考书籍 <计算机网络-自顶向下>       作者 James F ...

随机推荐

  1. centos6&period;5升级python为2&period;7

    今天线上服务器全部升级python环境为python-2.7.6的环境,我采用的方法是ansible+shell,代码如下,友提,Python-2.7.6.tgz.setuptools-14.3.1. ...

  2. Android 手机卫士16--手机杀毒

    1.指定动画一直旋转 rotateAnimation.setRepeatCount(RotateAnimation.INFINITE); android:repeatCount 重复的次数,默认为0, ...

  3. windows系统下Tomcat与Apache服务器集成

    说明:此文是看书真实试验成功的,书中提到了不同版本不兼容的问题,但是很荣幸我没碰到,此例可供参考. 本文假设你已经有了java环境和tomcat,你已经熟悉tomcat的应用. Jdk 1.7.0_5 ...

  4. 关于Aazure 使用以前保留的vhd创建虚拟机的基本步骤

    1. 删除vm保留vhd(只删除虚拟机记录,不删除磁盘)2. 拷贝vhd以及status文件到指定的存储账号3. 使用拷贝的VHD创建disk4. 从disk创建vm,指定指定vnet以及cloud ...

  5. Java中的那些名词术语(不断更新中)

    在工作和学习中,总会遇到各种术语.岁月不饶人,记忆力越来越下降.在这里记录下那些曾经关注过学习过的东西. POJO: Plain Old Java Object DI: Dependency Inje ...

  6. AppCan 双击返回按钮退出应用

    使用AppCan开发手机应用,拦截返回键实现自定义2秒内双击退出应用的操作 var c1c = 0; window.uexOnload = function(type){ uexWindow.setR ...

  7. H5 canvas圆形的时钟

    今天用H5中的canvas标签做一个时钟,H5中有很多好用的新增标签,真的很不错. 1.canvas标签介绍 <canvas> 标签定义图形,比如图表和其他图像,你必须使用脚本来绘制图形. ...

  8. 453&period; Minimum Moves to Equal Array Elements

    Given anon-emptyinteger array of sizen, find the minimum number of moves required to make all array ...

  9. 【Scala篇】--Scala中Trait、模式匹配、样例类、Actor模型

    一.前述 Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大. 模式匹配机制相当于java中的switch-case. 使用了case关键字的类定义就是样例类(case ...

  10. golang:吐槽multipart的设计

    最近在做邮件解析的工作,因此接触到multipart库,用了之后才发现golang的multipart有一点设计很诡异. 红线标出来的话意思是:当Content-Transfer-Encoding的值 ...