欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

学习笔记二:异步FIFO

发布时间:2024/7/5 编程问答 20 豆豆
生活随笔 收集整理的这篇文章主要介绍了 学习笔记二:异步FIFO 小编觉得挺不错的,现在分享给大家,帮大家做个参考.
  1 module fifo1 #(parameter DSIZE = 8, 2 parameter ASIZE = 4) //用格雷码的局限性:循环计数深度必须是2的n次幂,否则就失去了每次只变化一位的特性 3 (wclk,wrstn,wdata,wfull,winc,rclk,rrstn,rdata,rempty,rinc); 4 input wclk,wrstn,winc; 5 input [DSIZE - 1:0] wdata; 6 output wfull; 7 8 input rclk,rrstn,rinc; 9 output [DSIZE - 1:0] rdata; 10 output rempty; 11 12 reg wfull,rempty; //空满输出 13 reg [ASIZE:0] rbin,wbin; //读写二进制地址 14 reg [ASIZE:0] wptr,rq1_wptr,rq2_wptr, //读写指针打两拍CDC同步 15 rptr,wq1_rptr,wq2_rptr; 16 wire [ASIZE:0] rbinnext,wbinnext, //读写指针递增 17 rgraynext,wgraynext; //读写指针递增对应的格雷码 18 wire [ASIZE - 1:0] waddr,raddr; //实际读写mem的地址 19 20 reg [DSIZE - 1:0] mem [0:(1<<ASIZE) - 1]; //左移一位表示乘2 21 22 23 //---------------------双口RAM存储器 数据读写----------------------------- 24 assign rdata = mem[raddr]; // 25 always@(posedge wclk) begin // 26 if(winc && !wfull) begin 27 mem[waddr] <= wdata; 28 end 29 end 30 31 //---------------------将读指针CDC到写时钟域------------------------------ 32 always@(posedge wclk or negedge wrstn) begin 33 if(!wrstn) begin 34 wq2_rptr <= 5'd0; 35 wq1_rptr <= 5'd0; 36 end 37 else begin 38 wq1_rptr <= rptr; 39 wq2_rptr <= wq1_rptr; 40 end 41 end 42 43 //---------------------将写指针CDC到读时钟-------------------------------- 44 always@(posedge rclk or negedge rrstn) begin 45 if(!rrstn) begin 46 rq2_wptr <= 5'd0; 47 rq1_wptr <= 5'd0; 48 end 49 else begin 50 rq1_wptr <= wptr; 51 rq2_wptr <= rq1_wptr; 52 end 53 end 54 55 56 //读相关指针的产生 57 always@(posedge rclk or negedge rrstn) begin 58 if(!rrstn) begin 59 rptr <= 5'd0; 60 rbin <= 5'd0; 61 end 62 else begin 63 rptr <= rgraynext; 64 rbin <= rbinnext; 65 end 66 end 67 //写相关的指针 68 always@(posedge wclk or negedge wrstn) begin 69 if(!wrstn) begin 70 wbin <= 5'd0; 71 wptr <= 5'd0; 72 end 73 else begin 74 wbin <= wbinnext; 75 wptr <= wgraynext; 76 end 77 end 78 79 //addr截取与格雷码化指针 80 assign raddr = rbin[ASIZE - 1:0]; //mem的读地址 81 assign rbinnext = rbin + (rinc & ~rempty); //mem的下一个读地址 82 assign rgraynext = (rbinnext>>1) ^ rbinnext; //mem的读地址对应的格雷码 83 84 assign waddr = wbin[ASIZE - 1:0]; 85 assign wbinnext = wbin + (winc & !wfull); 86 assign wgraynext = (wbinnext>>1) ^ wbinnext; 87 88 //---------------------rempty产生------------------------------ 89 //FIFO empty when the next rptr == synchronized wptr or on the reset 90 always@(posedge rclk or negedge rrstn) begin 91 if(!rclk) begin 92 rempty <= 1'b1; 93 else begin 94 rempty <= (rgraynext == rq2_wptr); 95 end 96 end 97 98 //---------------------wfull产生------------------------------ 99 //FIFO full when CDC过来的格雷码(采样值)的最高位+次高位和bin转换过来的格雷码(理论值)均不同,剩下低位都相同 100 always@(posedge wclk or negedge wrstn) begin 101 if(!wrstn) begin 102 wfull <= 0; 103 end 104 else begin 105 wfull <= (wgraynext == {~wq2_rptr[ASIZE,ASIZE-1],wq2_rptr[ASIZE-2:0]}); 106 end 107 end 108 109 endmodule 110 /*Clifford E. Cummings的文章中提到的STYLE #1,构造一个指针宽度为N+1,深度为2^N字节的FIFO(为便方比较将格雷码指 111 针转换为二进制指针)。当指针的二进制码中最高位不一致而其它N位都 相等时,FIFO为满(在Clifford E. Cummings的文章中以 112 格雷码表示是前两位均不相同,而后两位LSB相同为满,这与换成二进制表示的MSB不同其他相同为满是一样的)。当指针完全相等时, 113 FIFO为空。 114 这种方法思路非常明了,为了比较不同时钟产生的指针,需要把不同时钟域的信号同步到本时钟域中来,而使用Gray码的目的就是使这个 115 异步同步化的过程发生亚稳态的机率最小。 116 */

 

很好的讲解:

https://www.cnblogs.com/aslmer/p/6114216.html#4067080

https://blog.csdn.net/wyj_2016/article/details/78469272

https://blog.csdn.net/IamSarah/article/details/76085635

https://blog.csdn.net/IamSarah/article/details/76093802

https://blog.csdn.net/tnaig/article/details/81503259

 

转载于:https://www.cnblogs.com/ucas-ime/p/10254811.html

总结

以上是生活随笔为你收集整理的学习笔记二:异步FIFO的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。