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

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

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

  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抓到的波形为

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

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

然后看一下读出来的数据

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

放大了看

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

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

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

原文地址:https://www.cnblogs.com/Librarian/p/11001270.html

时间: 2024-07-29 22:17:30

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

tcp/ip协议学习 第三章 IP协议

派猴子来的救兵 关于IP的RFC文档在此! IP的头文件还是先贴一下, 总是记不住. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-

学习笔记之TCP/IP协议的传输方式

一.通过网络发送数据,大致可以分为面向有连接与面向无连接两种类型: 1.面向无连接型包括以太网. IP.UDP等协议. 2. 面向有连接 型包括ATM.帧中继.TCP等 协议. 通过一张图了解一下: 面向有连接型 面向有连接型中,在发送数据之前,需要在收发主机之间连接一条通信线路 面向有连接型就好比人们平常打电话,输入完对方电话号码拨出之后,只有 对端拿起电话才能真正通话,通话结束后将电话机扣上就如同切断电源.因此在 面向有连接的方式下,必须在通信传输前后,专门进行建立和断开连接的处理.如果与对

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

本文由远航路上ing 原创,转载请标明出处. 这节笔记记录IP核的生成以及参数设置. 先再IP库里下载安装Framebuffer 的ipcore 并安装完毕. 一.IP核的生成: 1.先点击IP核则右边会出现生成对话框: 按箭头指示顺序进行设置:要设置生成ip核的路径(可以新建一个文件夹ipcore来放置IP核,若有多个IP核则在ipcore下分别建立文件夹),IP核的名字,以及语言的类型:verilog或VHDL.最后点击Customize. 2. 在上一步设置之后会出现下面的设置界面,先设置

TCP/IP/ICMP 学习实践

前言 在学习TCP分段与IP分片时.心有所感想把之前学习过的知识串联起来. 数据分段发生在传输层.分片发生在网络层. 相关术语: MTU(Maximum Transmission Unit,MTU),最大传输单元 以太网和802.3对数据帧的长度都有一个限制,其最大 值分别是1500和1492个字节.链路层的这个特性称作MTU. MSS(Maxitum Segment Size)最大分段大小的缩写,是TCP协议里面的一个概念 MSS就是TCP数据包每次能够传输的最大数据分段.为了达到最佳的传输效

linux 学习 设置固定网Ip

本人使用CentOs6.5 最近在学习linux操作系统,单在使用shell连接前都要使用ifconfig eth0 设置一个临时IP让我不胜其烦.决定学习设置一个固定IP 步骤: 1.登录计算机后使用 setup 命令 进入下图界面 2.选择网络配置 3.选择设备配置 4.进入 eth0 5.陪配置自己的相关信息 DHCP   [*]表示 自动获取ip   注意: 必须有DHCPserver 提供自动分配的服务否则没有作用 6.[[email protected] ~]# service  n

学习笔记之TCP/IP协议分层与OSI参考模型

1.协议的分层      ISO在制定标准化OSI之前,对网络体系结构相关的问题进行了充分的讨论, 最终提出了作为通信协议设计指标的OSI参考模型.这一模型将通信协议中必要 的功能分成了7层.通过这些分层,使得那些比较复杂的网络协议更加简单化. 在这一模型中,每个分层都接收由它下一层所提供的特定服务,并且负责为自己的上一层提供特定的服务.上下层之间进行交互时所遵循的约定叫做"接口".同一层之间的交互所遵循的约定叫做"协议". 协议分层就如同计算机软件中的模块化开发.

Altera FPGA 远程升级有关的几个IP的使用

在做在线远程升级的时候,一般需要两步:1.将数据写到外挂的flash中.2重新启动FPGA配置. 不过要做到远程升级,一般需要在原始程序中就考虑到加入远程升级模块,remote updata IP, 在升级的时候才可以启动远程升级功能. 远程升级之后程序加载的过程: 在进行远程升级成功以后,flash中应该会至少存储两个程序,出厂程序和升级程序. 两个程序在不同的地址空间中(出厂程序从0X0000开始存储).在FPGA上电之后,FPGA会加载出厂程序,出厂程序在运行之后,检测到remote up

计算机网络学习笔记--网络层之IP地址与子网

IPv4地址: 我们知道在网络层(TCP/IP体系结构的网际互联层),最重要的一个协议就是IP协议,现在正处于IPv4和IPv6的过渡时期,但目前来说,IPv4仍为主流,所以主要讲Ipv4. IP地址基本格式: 计算机内部IP地址的格式是32位的二进制数表示的,为了让人们看起来方便,通常采用点分十进制来表示IP地址,如192.168.1.25,其中用来分隔各段的那个点,也是为了方便人们阅读加上的,计算机内部并没有这个点. 公网IP地址和私网IP地址: 公网Ip地址是指可以在广域网上直接使用,直接

【DAY18】Socket编程,ROSE建模与TCP/IP的学习笔记

IDE eclipse调试 ------------------ 1.Debug 2.Step into : F5  ,单步进入. 3.Step return : F7,单步返回. 4.Stop over : F6,单步跳过. 安装Rose建模软件 ----------------- 1.安装虚拟光驱软件:DTLite.exe 2.加载Rose镜像文件. 3.一路安装,next... 4.安装完成注册License. a.在license管理器界面 开始 --> IBM Rose -> Lic