• DDR2 IP核调式记录2


    本文相对简单,只供自己看看就行。从其它的博客找了个代码,然后记录下仿真波形。

    1. 功能

            直接使用quartus生成的DDR2 IP核,然后实现循环 -->写入burst长度的数据后读出。

            代码数据的传输是32位,实际使用了两片IC。因此IP核也是32位交互。

    2.信号分析

            burst=4,是IC固有的=预取值。而代码中LEN为用户一次想要读取数据的长度的。与local_size和burst_length无关。

            分为4个状态: IDLE、WRITER、WRITING、READR、READING。WRITER和READR状态下,开始读写burst的第一个数据,其余的在WRITING和READING状态读写。

             local_ready:很重要的一个指示信号。要进行读写操作,必须在IP核(ddr2)准备好的情况下进行。因此,需要一直对此信号进行检测判断。

            写入地址(mem_local_addr),一开始为1,当读到的数据长度rdatalen=5时(初始值=1),mem_local_addr <= mem_local_addr + 4;

    命令

    连续写

    连续读

    读完写

    3. 仿真波形分析

    如下图所示:每次先写入连续4个数据,(例如1,2,3,4),然后再依次读出。

    读过程及下一次写

    4. 附代码

    顶层代码:

    1. module ddr2wrtest (
    2. input clk , // Clock
    3. input global_reset_n , // Asynchronous reset active low
    4. output [ 12: 0] mem_addr ,
    5. output [ 2: 0] mem_ba ,
    6. output mem_cas_n ,
    7. output mem_cke ,
    8. inout mem_clk ,
    9. inout mem_clk_n ,
    10. output mem_cs_n ,
    11. output [ 1: 0] mem_dm ,
    12. inout [ 15: 0] mem_dq ,
    13. inout [ 1: 0] mem_dqs ,
    14. output mem_odt ,
    15. output mem_ras_n ,
    16. output mem_we_n
    17. );
    18. parameter LEN = 8; // 突发长度 4
    19. parameter IDEL = 5'b00001; // 空闲态
    20. parameter WRITER = 5'b00010; // 准备写
    21. parameter WRITING = 5'b00100; // 写状态
    22. parameter READR = 5'b01000; // 准备读
    23. parameter READING = 5'b10000; // 读状态
    24. reg [ 5: 0] state;
    25. //**********************与IP相连部分********************//
    26. reg [ 24: 0] mem_local_addr =1 ;
    27. wire mem_local_init_done ;
    28. wire local_burstbegin_sig ;
    29. wire [ 31: 0] mem_local_rdata ;
    30. wire mem_local_rdata_valid ;
    31. wire mem_local_read_req ;
    32. wire mem_local_ready ;
    33. wire [ 3: 0] mem_local_size ;
    34. reg [ 31: 0] mem_local_wdata ;
    35. wire mem_local_write_req ;
    36. wire phy_clk ;
    37. wire reset_phy_clk_n ;
    38. //*****************************************************//
    39. wire rst_n ;
    40. reg [ 3: 0] rdatalen ; // 读突发长度计数器
    41. reg [ 3: 0] wdatalen ; // 写突发长度计数器
    42. reg [100: 0] state_name ; // 状态名
    43. assign rst_n = reset_phy_clk_n&&mem_local_init_done;
    44. assign mem_local_size = LEN;
    45. assign local_burstbegin_sig = ((state == WRITER&&mem_local_ready) || (state == READR&&mem_local_ready))?1:0;
    46. assign mem_local_write_req = (state == WRITING)?1:0;
    47. assign mem_local_read_req = (state == READR&&mem_local_ready)?1:0;
    48. ddr2 ddr2_inst
    49. (
    50. //==============================《 》===============================
    51. .aux_full_rate_clk ( ), //全速率时钟
    52. .aux_half_rate_clk ( ), //半速率时钟
    53. //==============================《 用户操作信号 》===============================
    54. .global_reset_n (global_reset_n ), //全局复位
    55. .local_address (mem_local_addr ), //当前操作地址
    56. .local_be (8'hff ), //数据掩码
    57. .local_burstbegin (local_burstbegin_sig ), //突发起始信号
    58. .local_init_done (mem_local_init_done ), //初始化完成信号
    59. .local_rdata (mem_local_rdata ), //读数据总线
    60. .local_rdata_valid (mem_local_rdata_valid ), //读有效标志
    61. .local_read_req (mem_local_read_req ), //读请求,保持一个时钟周期
    62. .local_ready (mem_local_ready ), //接受到请求
    63. .local_refresh_ack ( ), //自动刷新
    64. .local_size (mem_local_size ), //突发长度
    65. .local_wdata (mem_local_wdata ), //写数据总线
    66. .local_write_req (mem_local_write_req ), //写请求
    67. //==============================《 与DDR2相连的信号 》===============================
    68. .mem_addr (mem_addr ), //地址总线
    69. .mem_ba (mem_ba ), //bank地址
    70. .mem_cas_n (mem_cas_n ), //行选通
    71. .mem_cke (mem_cke ), //时钟使能
    72. .mem_clk (mem_clk ), //操作时钟
    73. .mem_clk_n (mem_clk_n ), //反向时钟
    74. .mem_cs_n (mem_cs_n ), //片选信号
    75. .mem_dm (mem_dm ), //DDR2数据屏蔽信号
    76. .mem_dq (mem_dq ), //数据总线
    77. .mem_dqs (mem_dqs ), //数据选取脉冲信号
    78. .mem_odt (mem_odt ), //片内终结信号
    79. .mem_ras_n (mem_ras_n ), //行选通
    80. .mem_we_n (mem_we_n ), //使能
    81. //==============================《 用户操作信号 》===============================
    82. .phy_clk (phy_clk ), //提供给用户的操作时钟
    83. .pll_ref_clk (clk ), //给ddr2的输入时钟
    84. .reset_phy_clk_n (reset_phy_clk_n ), //提供给用户的复位信号
    85. .reset_request_n ( ), //当PLL锁定后为低电平
    86. .soft_reset_n (1'b1 ) //软复位,不包括PLL的复位
    87. );
    88. always@(*)
    89. case (state)
    90. IDEL : state_name = "IDEL";
    91. WRITER : state_name = "WRITER" ;
    92. WRITING : state_name = "WRITING" ;
    93. READR : state_name = "READR" ;
    94. READING : state_name = "READING";
    95. default : /* default */;
    96. endcase
    97. always@(posedge phy_clk or negedge rst_n)begin
    98. if(!rst_n)
    99. state <= IDEL;
    100. else
    101. case (state)
    102. IDEL : state <= WRITER;
    103. WRITER : if(mem_local_ready)
    104. state <= WRITING;
    105. else
    106. state <= WRITER;
    107. WRITING : if(wdatalen == LEN)
    108. state <= READR;
    109. else
    110. state <= state;
    111. READR : if(mem_local_ready)
    112. state <= READING;
    113. else
    114. state <= READR;
    115. READING : if(rdatalen == LEN)
    116. state <= IDEL;
    117. else
    118. state <= state;
    119. default : state <= state;
    120. endcase
    121. end
    122. // 写的数据自加1
    123. always@(posedge phy_clk or negedge rst_n)begin
    124. if(!rst_n)
    125. mem_local_wdata <= 1;
    126. else if(state == WRITING && mem_local_ready)
    127. mem_local_wdata <= mem_local_wdata + 1;
    128. else
    129. mem_local_wdata <= mem_local_wdata;
    130. end
    131. // 当前写的数据突发长度
    132. always@(posedge phy_clk or negedge rst_n)begin
    133. if(!rst_n)
    134. wdatalen <= 1;
    135. else if(state == WRITING && mem_local_ready)
    136. wdatalen <= wdatalen + 1;
    137. else if(state == WRITING && !mem_local_ready)
    138. wdatalen <= wdatalen ;
    139. else
    140. wdatalen <= 1;
    141. end
    142. // 当前读的数据突发长度
    143. always@(posedge phy_clk or negedge rst_n)begin
    144. if(!rst_n)
    145. rdatalen <= 1;
    146. else if(state == READING && mem_local_rdata_valid)
    147. rdatalen <= rdatalen + 1;
    148. else
    149. rdatalen <= 1;
    150. end
    151. // 操作地址自加
    152. always@(posedge phy_clk or negedge rst_n)begin
    153. if(!rst_n)
    154. mem_local_addr <= 1;
    155. else if(rdatalen == LEN)
    156. mem_local_addr <= mem_local_addr + LEN;
    157. end
    158. endmodule

    测试代码

    1. `timescale 1ns/1ps
    2. module test_tb ();
    3. reg clk ;
    4. reg global_reset_n;
    5. wire [ 12: 0] mem_addr ;
    6. wire [ 2: 0] mem_ba ;
    7. wire mem_cas_n ;
    8. wire mem_cke ;
    9. wire mem_clk ;
    10. wire mem_clk_n ;
    11. wire mem_cs_n ;
    12. wire [ 1: 0] mem_dm ;
    13. wire [ 15: 0] mem_dq ;
    14. wire [ 1: 0] mem_dqs ;
    15. wire mem_odt ;
    16. wire mem_ras_n ;
    17. wire mem_we_n ;
    18. ddr2wrtest u1 (
    19. .clk (clk ), // Clock
    20. .global_reset_n (global_reset_n ) , // Asynchronous reset active low
    21. .mem_addr (mem_addr ),
    22. .mem_ba (mem_ba ),
    23. .mem_cas_n (mem_cas_n ),
    24. .mem_cke (mem_cke ),
    25. .mem_clk (mem_clk ),
    26. .mem_clk_n (mem_clk_n ),
    27. .mem_cs_n (mem_cs_n ),
    28. .mem_dm (mem_dm ),
    29. .mem_dq (mem_dq ),
    30. .mem_dqs (mem_dqs ),
    31. .mem_odt (mem_odt ),
    32. .mem_ras_n (mem_ras_n ),
    33. .mem_we_n (mem_we_n )
    34. );
    35. ddr2_mem_model mem (
    36. .mem_dq (mem_dq),
    37. .mem_dqs (mem_dqs),
    38. .mem_dqs_n (mem_dqs_n),
    39. .mem_addr (mem_addr),
    40. .mem_ba (mem_ba),
    41. .mem_clk (mem_clk),
    42. .mem_clk_n (mem_clk_n),
    43. .mem_cke (mem_cke),
    44. .mem_cs_n (mem_cs_n),
    45. .mem_ras_n (mem_ras_n),
    46. .mem_cas_n (mem_cas_n),
    47. .mem_we_n (mem_we_n),
    48. .mem_dm (mem_dm),
    49. .mem_odt (mem_odt)
    50. );
    51. always #10 clk = ~clk;
    52. initial begin
    53. clk = 0;
    54. global_reset_n = 0;
    55. @(posedge clk);
    56. @(posedge clk);
    57. @(posedge clk);
    58. @(posedge clk);
    59. @(posedge clk);
    60. @(posedge clk);
    61. @(posedge clk);
    62. @(posedge clk);
    63. @(posedge clk);
    64. global_reset_n = 1;
    65. end
    66. endmodule

  • 相关阅读:
    简述什么是迭代器(Iterator)?
    一切皆可盲盒:孙宇晨传递给商业太空旅游的机会
    MySQL中如何进行表的优化和压缩?
    总结数据结构-1
    Dubbo和SpringCloud对比
    卷积神经网络 图像识别,卷积神经网络图像处理
    搭建NTP Sever实现网络设备时间同步
    基于深度学习的监控场景下是否佩戴安全帽检测(yolov5)
    opencv c++ 边缘提取
    Cell子刊综述:药物研发进入智能生成时代
  • 原文地址:https://blog.csdn.net/weixin_41155462/article/details/132622564