当前位置:   article > 正文

Xilinx FPGA:vivado实现乒乓缓存_vivado 双端口ram读写使用乒乓缓存

vivado 双端口ram读写使用乒乓缓存

一、项目要求

1、用两个伪双端口的RAM实现缓存

2、先写buffer1,再写buffer2 ,在读buffer1的同时写buffer2,在读buffer2的同时写buffer1。

3、写端口50M时钟,写入16个8bit  的数据,读出时钟25M,读出8个16bit 的数据。

二、信号转换图:

三、状态转换图

四、程序设计

先配置IP:

  1. `timescale 1ns / 1ps
  2. module ping_pang_1(
  3. input sys_clk ,
  4. input rst_n ,
  5. output wire [15 : 0] doutb1 ,
  6. output wire [15 : 0] doutb2
  7. );
  8. wire clk_50M ;
  9. wire clk_25M ;
  10. wire locked ;
  11. wire en ;
  12. assign en = locked & rst_n;
  13. clk_wiz_0 instance_name
  14. (
  15. // Clock out ports
  16. .clk_50M(clk_50M), // output clk_out1
  17. .clk_25M(clk_25M), // output clk_out2
  18. // Status and control signals
  19. .resetn(rst_n), // input resetn
  20. .locked(locked), // output locked
  21. // Clock in ports
  22. .sys_clk(sys_clk)); // input clk_in1
  23. ram1
  24. reg wea1 ;
  25. reg [3 : 0] addra1 ;
  26. reg [7 : 0] dina1 ;
  27. reg enb1 ;
  28. reg [2 : 0] addrb1 ;
  29. ping_pang ram1 (
  30. .clka(clk_50M), // input wire clka
  31. .ena(1), // input wire ena
  32. .wea(wea1), // input wire [0 : 0] wea
  33. .addra(addra1), // input wire [3 : 0] addra
  34. .dina(dina1), // input wire [7 : 0] dina
  35. .clkb(clk_25M), // input wire clkb
  36. .enb(enb1), // input wire enb
  37. .addrb(addrb1), // input wire [2 : 0] addrb
  38. .doutb(doutb1) // output wire [15 : 0] doutb
  39. );
  40. ram2
  41. reg wea2 ;
  42. reg [3 : 0] addra2 ;
  43. reg [7 : 0] dina2 ;
  44. reg enb2 ;
  45. reg [2 : 0] addrb2 ;
  46. ping_pang ram2 (
  47. .clka(clk_50M), // input wire clka
  48. .ena(1), // input wire ena
  49. .wea(wea2), // input wire [0 : 0] wea
  50. .addra(addra2), // input wire [3 : 0] addra
  51. .dina(dina2), // input wire [7 : 0] dina
  52. .clkb(clk_25M), // input wire clkb
  53. .enb(enb2), // input wire enb
  54. .addrb(addrb2), // input wire [2 : 0] addrb
  55. .doutb(doutb2) // output wire [15 : 0] doutb
  56. );
  57. /状态机
  58. localparam IDLE = 3'd0;
  59. localparam W1 = 3'd1;
  60. localparam W2_R1 = 3'd2;
  61. localparam W1_R2 = 3'd3;
  62. reg [2:0] cur_state,next_state;
  63. always@(posedge clk_50M)
  64. if(!rst_n)
  65. cur_state <= IDLE;
  66. else if(en)
  67. cur_state <= next_state;
  68. else
  69. cur_state <= IDLE;
  70. always@(*)
  71. case(cur_state)
  72. IDLE :begin
  73. next_state = W1;
  74. end
  75. W1 :begin
  76. if(addra1 == 14 && wea1)
  77. next_state = W2_R1;
  78. else
  79. next_state = cur_state;
  80. end
  81. W2_R1 :begin
  82. if(addra2 == 14 && wea2)
  83. next_state = W1_R2;
  84. else
  85. next_state = cur_state;
  86. end
  87. W1_R2 :begin
  88. if(addra1 == 14 && wea1)
  89. next_state = W2_R1;
  90. else
  91. next_state = cur_state;
  92. end
  93. default:;
  94. endcase
  95. /写状态机
  96. always@(posedge clk_50M)
  97. if(!rst_n)begin
  98. wea1 <= 0;
  99. addra1 <= 0;
  100. dina1 <= 0;
  101. wea2 <= 0;
  102. addra2 <= 0;
  103. dina2 <= 0;
  104. end
  105. else
  106. case(cur_state)
  107. IDLE :begin
  108. end
  109. W1 :begin
  110. if(addra1 == 15)
  111. wea1 <= 0;
  112. else
  113. wea1 <= 1;
  114. if(wea1 == 1)
  115. dina1 <= dina1 + 8'h27 ;
  116. else
  117. dina1 <= 0;
  118. if(wea1 == 1 && addra1 == 15)
  119. addra1 <= 0;
  120. else if(wea1 == 1)
  121. addra1 <= addra1 + 1;
  122. else
  123. addra1 <= addra1;
  124. end
  125. W2_R1:begin
  126. addra1 <= 0;
  127. wea1 <= 0; /ram1的写使能关闭
  128. if(addra2 == 15)
  129. wea2 <= 0;
  130. else
  131. wea2 <= 1;
  132. if(wea2 == 1)
  133. dina2 <= dina2 + 8'h19 ;
  134. else
  135. dina2 <= 0;
  136. if(wea2 == 1 && addra2 == 15)
  137. addra2 <= 0;
  138. else if(wea2 == 1)
  139. addra2 <= addra2 + 1;
  140. else
  141. addra2 <= 0;
  142. end
  143. W1_R2:begin
  144. wea2 <= 0;
  145. addra2 <= 0;
  146. if(addra1 == 15)
  147. wea1 <= 0;
  148. else
  149. wea1 <= 1;
  150. if(wea1 == 1)
  151. dina1 <= dina1 + 8'h27 ;
  152. else
  153. dina1 <= 0;
  154. if(wea1 == 1 && addra1 == 15)
  155. addra1 <= 0;
  156. else if(wea1 == 1)
  157. addra1 <= addra1 + 1;
  158. else
  159. addra1 <= 0;
  160. end
  161. default:;
  162. endcase
  163. 读状态机
  164. always@(negedge clk_25M)
  165. if(!rst_n)begin
  166. enb1 <= 0;
  167. addrb1 <= 0;
  168. enb2 <= 0;
  169. addrb2 <= 0;
  170. end
  171. else
  172. case(cur_state)
  173. IDLE :begin
  174. end
  175. W1 :begin
  176. end
  177. W2_R1 :begin
  178. enb2 <= 0;
  179. addrb2 <= 0;
  180. if(addrb1 == 7 && enb1)
  181. enb1 <= 0;
  182. else
  183. enb1 <= 1;
  184. if(enb1 == 1 && addrb1 == 7)
  185. addrb1 <= 0;
  186. else if(enb1)
  187. addrb1 <= addrb1 + 1;
  188. else
  189. addrb1 <= 0;
  190. end
  191. W1_R2 :begin
  192. addrb1 <= 0;
  193. enb1 <= 0;
  194. if(addrb2 == 7)
  195. enb2 <= 0;
  196. else
  197. enb2 <= 1;
  198. if(enb2 == 1 && addrb2 == 7)
  199. addrb2 <= 0;
  200. else if(enb2)
  201. addrb2 <= addrb2 + 1;
  202. else
  203. addrb2 <= 0;
  204. end
  205. default:;
  206. endcase
  207. endmodule

五、仿真设计

  1. `timescale 1ns / 1ps
  2. module test_ping_pang( );
  3. reg sys_clk ;
  4. reg rst_n ;
  5. wire[15:0] doutb1 ;
  6. wire[15:0] doutb2 ;
  7. initial
  8. begin
  9. sys_clk = 0 ;
  10. rst_n = 0 ;
  11. #10
  12. rst_n = 1 ;
  13. end
  14. always #1 sys_clk = ~sys_clk ;
  15. ping_pang_1 ping_pang_1_1(
  16. . sys_clk ( sys_clk ) ,
  17. . rst_n ( rst_n ) ,
  18. . doutb1 (doutb1 ) ,
  19. . doutb2 (doutb2 )
  20. );
  21. endmodule

五、仿真结果

六、记录一些小问题:

(2)

(3)

所以修改思路就是尽量让enb1和enb2之间没有空隙,在时序上是衔接着的

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

闽ICP备14008679号