学习笔记二:异步FIFO
生活随笔
收集整理的这篇文章主要介绍了
学习笔记二:异步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的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 转 关于window10安装jdk,配置
- 下一篇: 20190626_二次开发BarTend