当前位置:   article > 正文

基于fpga对ddr3的读写控制_如何写一个低功耗的ddr3控制器

如何写一个低功耗的ddr3控制器

1.很多情况下,fpga的内部ip ram的存储量较小,所以需要外挂容量大的芯片。内部的芯片ram称为静态ram,其读写简单,速率中等,缺点就是存储空间较小。spartan—6芯片的最小单元为9k;充电刷新保持数据的额sdram称为动态ram,其容量大,缺点就是高功耗,管脚多,操作时许复杂,占用面积大。无论是静态还是动态ram都是一种易失性器件。

2.当前比较常用的是ddr3,有关ddr3的介绍https://baike.baidu.com/item/DDR3/9505741?fr=aladdin;fpga的spartan6家族中,有一个IP称为MCB(存储控制模块),本文主要就是对控制模块的读写控制,然后通过读写模块对ddr3的数据进行写入与读取。

3.模块的数据流与读写时序如下:

     整个模块的基本数据流就是图所示,本文设计一个display的控制模块,对整个模块进行一个数据验证。而ddr3_rd_ctrl的模块中,申请了一个fifo_2048的fifoIP核,来对ddr3存储的数据进行读取与显示。而frame_start的信号等同于显示器的行列驱动同步,pixel_vaild_o相当于有效显示区域。这个模块需要2个不同频率的时钟,对ddr3的读模块需要125M的时钟,显示模块为50M时钟。

              这个ddr3的数据读取的模块控制时序,需要说明的是读模块要先发出读命令然后才可以读取数据,而写模块要写入数据才可以发出写命令。MCB的fifo的使能信号需要严格控制。

 

3.ddr3的读写主要控制模块程序

  1. module wr_ddr3_ctrl(
  2. input wire sclk,
  3. input wire rst,
  4. input wire P2_DATA_EMPTY,
  5. input wire c3_calib_done,
  6. output wire[31:0] P2_DATA, // P2_DATA
  7. output wire P2_DATA_WR_EN, //P2_DATA_WR_EN
  8. output wire[3:0] P2_data_mask,
  9. output wire P2_CMD_WR_EN, //P2_CMD_WR_EN
  10. output wire[2:0] P2_CMD_INSTR, //P2_CMD_INSTR
  11. output wire[5:0] P2_CMD_BL, //P2_CMD_BL
  12. output wire[29:0] P2_CMD_ADDR //P2_CMD_ADDR
  13. );
  14. reg wr_data_en;
  15. reg [5:0] data_cnt=0;
  16. reg [31:0] wr_data=0;
  17. reg [5:0] burst_cnt=0;
  18. reg done_dely;
  19. wire wr_start_flag;
  20. reg wr_cmd_en;
  21. reg wr_cycle=0;
  22. reg [29:0] wr_addr=0;
  23. assign P2_CMD_BL=6'd63;
  24. assign P2_CMD_INSTR=3'b000;
  25. assign P2_data_mask=4'b0000;
  26. assign P2_CMD_ADDR=wr_addr;
  27. assign P2_CMD_WR_EN=wr_cmd_en;
  28. assign P2_DATA_WR_EN=wr_data_en;
  29. assign P2_DATA=wr_data;
  30. always@(posedge sclk)
  31. if(rst==1)
  32. done_dely<=0;
  33. else done_dely<=c3_calib_done;
  34. assign wr_start_flag=~(done_dely)&(c3_calib_done);
  35. always@(posedge sclk ) //
  36. if(rst==1)
  37. wr_data_en<=1'b0;
  38. else if(wr_start_flag==1||(wr_cycle==1&&P2_DATA_EMPTY==1))
  39. wr_data_en<=1'b1;
  40. else if(data_cnt=='d63)
  41. wr_data_en<=1'b0;
  42. always@(posedge sclk ) //
  43. if(rst==1)
  44. data_cnt<='d0;
  45. else if(wr_data_en==1)
  46. data_cnt<=data_cnt+1'b1;
  47. else data_cnt<='d0;
  48. always@(posedge sclk) //
  49. if(rst==1)
  50. wr_data<='d0;
  51. else if(wr_data_en==1&&data_cnt==63&&burst_cnt==63)
  52. wr_data<='d0;
  53. else if(wr_data_en==1)
  54. wr_data<=wr_data+1;
  55. always@(posedge sclk) //
  56. if(rst==1)
  57. burst_cnt<='d0;
  58. else if(wr_data_en==1&&data_cnt==63)
  59. burst_cnt<=burst_cnt+1'b1;
  60. always@(posedge sclk) //
  61. if(rst==1)
  62. wr_cmd_en<=1'b0;
  63. else if(wr_data_en==1&&data_cnt==63)
  64. wr_cmd_en<=1'b1;
  65. else wr_cmd_en<=1'b0;
  66. always@(posedge sclk) //
  67. if(rst==1)
  68. wr_cycle<='d0;
  69. else if(wr_data_en==1&&data_cnt==63&&burst_cnt==63)
  70. wr_cycle<='d0;
  71. else if(wr_start_flag==1)
  72. wr_cycle<=1;
  73. always@(posedge sclk) //
  74. if(rst==1)
  75. wr_addr<='d0;
  76. else if(wr_cmd_en==1)
  77. wr_addr<=wr_addr+256;
  78. endmodule
  1. module ddr3_rd(
  2. input wire sclk,
  3. input wire wr_sclk,
  4. input wire rst,
  5. input wire c3_calib_done,
  6. input wire frame_start,
  7. input wire pixel_vaild_o,
  8. input wire p3_rd_full,
  9. input wire [31:0] p3_rd_data,
  10. output reg p3_cmd_en,
  11. output wire [2:0] p3_cmd_inst,
  12. output wire [5:0] p3_cmd_bl,
  13. output reg [29:0] p3_cmd_byte_addr,
  14. output reg p3_rd_fifo_en,
  15. output wire [31:0] pixel_data
  16. );
  17. reg ddr3_ready;
  18. wire [10:0] wr_f_cnt;
  19. reg rd_ddr3_cycle;
  20. reg [5:0] data_cnt;
  21. reg user_fifo_wr_en;
  22. wire [10:0] r_f_cnt;
  23. reg fifo_enable_read;
  24. wire user_fifo_rd_en;
  25. assign p3_cmd_bl=63;
  26. assign p3_cmd_inst=001;
  27. always@(posedge wr_sclk)
  28. if(rst==1)
  29. ddr3_ready<=0;
  30. else ddr3_ready<=c3_calib_done;
  31. always@(posedge wr_sclk)
  32. if(rst==1)
  33. rd_ddr3_cycle<=0;
  34. else if(data_cnt==63)
  35. rd_ddr3_cycle<=0;
  36. else if(ddr3_ready==1&&wr_f_cnt<1024)
  37. rd_ddr3_cycle<=1;
  38. always@(posedge wr_sclk)
  39. if(rst==1)
  40. p3_cmd_en<=0;
  41. else if(ddr3_ready==1&&wr_f_cnt<1024&&rd_ddr3_cycle==0)
  42. p3_cmd_en<=1;
  43. else p3_cmd_en<=0;
  44. always@(posedge wr_sclk)
  45. if(rst==1)
  46. p3_rd_fifo_en<=1'b0;
  47. else if(data_cnt==63)
  48. p3_rd_fifo_en<=1'b0;
  49. else if(rd_ddr3_cycle==1&&p3_rd_full==1)
  50. p3_rd_fifo_en<=1'b1;
  51. always@(posedge wr_sclk)
  52. if(rst==1)
  53. p3_cmd_byte_addr<=30'd0;
  54. else if(p3_cmd_en==1&&p3_cmd_byte_addr==30'h3f00)
  55. p3_cmd_byte_addr<=30'd0;
  56. else if(p3_cmd_en==1)
  57. p3_cmd_byte_addr<=p3_cmd_byte_addr+256;
  58. always@(posedge wr_sclk)
  59. if(rst==1)
  60. data_cnt<=6'd0;
  61. else if(data_cnt==63)
  62. data_cnt<=6'd0;
  63. else if(rd_ddr3_cycle==1&&p3_rd_fifo_en==1)
  64. data_cnt<=data_cnt+1'b1;
  65. always@(posedge wr_sclk)
  66. if(rst==1)
  67. user_fifo_wr_en<=1'b0;
  68. else if(rd_ddr3_cycle==1&&p3_rd_full==1)
  69. user_fifo_wr_en<=1'b1;
  70. else if(data_cnt==63)
  71. user_fifo_wr_en<=1'b0;
  72. always@(posedge sclk)
  73. if(rst==1)
  74. fifo_enable_read<=1'b0;
  75. else if(r_f_cnt>1024&&frame_start==1)
  76. fifo_enable_read<=1'b1;
  77. assign user_fifo_rd_en=fifo_enable_read&pixel_vaild_o;
  78. fifo_wr2048_32 fifo_wr2048_32_inst (
  79. .wr_clk(wr_sclk), // input wr_clk *125M
  80. .rd_clk(sclk), // input rd_clk *50M
  81. .din(p3_rd_data), // input [31 : 0] din
  82. .wr_en(user_fifo_wr_en), // input wr_en
  83. .rd_en(user_fifo_rd_en), // input rd_en
  84. .dout(pixel_data), // output [31 : 0] dout
  85. .full(full), // output full
  86. .empty(empty), // output empty
  87. .rd_data_count(r_f_cnt), // output [10 : 0] rd_data_count
  88. .wr_data_count(wr_f_cnt) // output [10 : 0] wr_data_count
  89. );
  90. endmodule

4.模块时序仿真需要很多时间,仿真才是关键。

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

闽ICP备14008679号