当前位置:   article > 正文

Cummings异步FIFO——第二篇_clifford e. cummings

clifford e. cummings

0. 参考

Simulation and Synthesis Techniques for Asynchronous FIFO Design with Asynchronous Pointer Comparisons -- Clifford E. Cummings ,Sunburst Design

1. 异步FIFO

异步FIFO是指读数据在一个clock demain,写数据在另一个clock demain的FIFO buffer。

相关参考之前一篇文章 Cummings——异步FIFO第一讲

 

2. 判断FIFO空满的第二种方法

通常情况下FIFO的空满是通过增加一位地址位来判断的,比如 Cummings——异步FIFO第一讲

中的方法,本文要介绍另一种方法,可以减少寄存器使用。

2.1 满判断

根据地址的高两位将FIFO的地址空间分成四部分,如下图figure2所示:

 

地址是格雷码地址。如果写地址落后读地址一个地址空间,比如写地址在00空间,读地址在01空间,那么说明写地址快要追上读地址,FIFO快要满了,这时候给一个”possibly going full"位,此时figure4中的direction latch会被set(低电平set,所以figure2中取反了)。

2.2 空判断

空判断与满判断类似,有一个“possibly going empty”位,低电平时将direction latch clear了。如下图,只是这时候

2.3 direction latch

direction为1表示快要满了,如果接下来读写地址相同,则满;为0表示快要空了,如果接下来读写地址相同,则空。

 

3. fifo结构图

FIFO的结构图如下,空满标志位是在CMP比较逻辑中产生的,在CMP中先生成direction方向位,然后判断读写地址。

4. RTL代码

4.1 top层

  1. module fifo2 (rdata, wfull, rempty, wdata,
  2. winc, wclk, wrst_n, rinc, rclk, rrst_n);
  3. parameter DSIZE = 8;
  4. parameter ASIZE = 4;
  5. output [DSIZE-1:0] rdata;
  6. output wfull;
  7. output rempty;
  8. input [DSIZE-1:0] wdata;
  9. input winc, wclk, wrst_n;
  10. input rinc, rclk, rrst_n;
  11. wire [ASIZE-1:0] wptr, rptr;
  12. wire [ASIZE-1:0] waddr, raddr;
  13. async_cmp #(ASIZE) async_cmp
  14. (.aempty_n(aempty_n), .afull_n(afull_n),
  15. .wptr(wptr), .rptr(rptr), .wrst_n(wrst_n));
  16. fifomem #(DSIZE, ASIZE) fifomem
  17. (.rdata(rdata), .wdata(wdata),
  18. .waddr(wptr), .raddr(rptr),
  19. .wclken(winc), .wclk(wclk));
  20. rptr_empty #(ASIZE) rptr_empty
  21. (.rempty(rempty), .rptr(rptr),
  22. .aempty_n(aempty_n), .rinc(rinc),
  23. .rclk(rclk), .rrst_n(rrst_n));
  24. wptr_full #(ASIZE) wptr_full
  25. (.wfull(wfull), .wptr(wptr),
  26. .afull_n(afull_n), .winc(winc),
  27. .wclk(wclk), .wrst_n(wrst_n));
  28. endmodule

4.2 mem读写

mem读写跟第一种FIFO一样, Cummings——异步FIFO第一讲

  1. module fifomem (rdata, wdata, waddr, raddr, wclken, wclk);
  2. parameter DATASIZE = 8; // Memory data word width
  3. parameter ADDRSIZE = 4; // Number of memory address bits
  4. parameter DEPTH = 1<<ADDRSIZE; // DEPTH = 2**ADDRSIZE
  5. output [DATASIZE-1:0] rdata;
  6. input [DATASIZE-1:0] wdata;
  7. input [ADDRSIZE-1:0] waddr, raddr;
  8. input wclken, wclk;
  9. `ifdef VENDORRAM
  10. // instantiation of a vendor's dual-port RAM
  11. VENDOR_RAM MEM (.dout(rdata), .din(wdata),
  12. .waddr(waddr), .raddr(raddr),
  13. .wclken(wclken), .clk(wclk));
  14. `else
  15. reg [DATASIZE-1:0] MEM [0:DEPTH-1];
  16. assign rdata = MEM[raddr];
  17. always @(posedge wclk)
  18. if (wclken) MEM[waddr] <= wdata;
  19. `endif
  20. endmodule

4.3 CMP比较逻辑

  1. module async_cmp (aempty_n, afull_n, wptr, rptr, wrst_n);
  2. parameter ADDRSIZE = 4;
  3. parameter N = ADDRSIZE-1;
  4. output aempty_n, afull_n;
  5. input [N:0] wptr, rptr;
  6. input wrst_n;
  7. reg direction;
  8. wire high = 1'b1;
  9. wire dirset_n = ~( (wptr[N]^rptr[N-1]) & ~(wptr[N-1]^rptr[N]));
  10. wire dirclr_n = ~((~(wptr[N]^rptr[N-1]) & (wptr[N-1]^rptr[N])) |
  11. ~wrst_n);
  12. always @(posedge high or negedge dirset_n or negedge dirclr_n)
  13. if (!dirclr_n) direction <= 1'b0;
  14. else if (!dirset_n) direction <= 1'b1;
  15. else direction <= high;
  16. //always @(negedge dirset_n or negedge dirclr_n)
  17. //if (!dirclr_n) direction <= 1'b0;
  18. //else direction <= 1'b1;
  19. assign aempty_n = ~((wptr == rptr) && !direction);
  20. assign afull_n = ~((wptr == rptr) && direction);
  21. endmodule

CMP的框图如下:

4.3.1 异步的空满产生

aempty_n为0时,empty置位为1.aempty_n为0(也就是空)是在rclk时钟域产生的(因为读数据时候才可能空),而aempty_n为1(也就是空被clear)是在我才离开时钟域产生(因为写数据才不为空)。

同样afull_n是在wclk产生满置位,在rclk满清零。

异步的空满操作:

 

如果afull_n=0说明满了,满这个状态相比于不满状态持续时间肯定短,如果刚刚满了,但是又接着读数据,那么这个满状态持续时间很短(在rclk的上升沿afull_n=1,使状态编程不满。),如果用wclk对afull_n采样这个满状态0可能不满足建立保持时间,所以就直接将afull_n接到置位上,避免时序不满足。 ​ 还可以看出wfull的set不受wclk的影响,这是因为满是由wclk控制的waddr来控制的;wfull的clear需要用wclk用两个周期来同步,这是因为不满是由rclk控制的raddr来控制的,需要用wclk同步一下。

4.3.2 reset操作

如figure6所示,这里的复位信号是wrst_n。如果wrst_n复位,则:

1) 满标志位立马清零。

2) 使读写地址都为零,所以地址比较器输出1

3) direction置为零

4) direction清零值得aempty_n为零,使empty为1.

 

4.3.3 写与满

置位之后,如果winc有效,则地址比较器输出0,aempty_n为1,两个rclk之后,empty为0.

如果winc继续有效,当waddr落后raddr一个地址空间时,direction为1,表明将要满了。

如果winc继续有效,当waddr等于raddr时,afull_n为0,立马时wfull为1.

4.3.4 读与空

上面写满了,如果接下来要读,即rinc有效,读写地址不同了,afull_n为1,两个wclk之后,full无效。

如果inc接着有效,当raddr落后waddr一个地址空间时,,,后面不必详述了,差不多东西。

4.4 空标志

  1. module rptr_empty (rempty, rptr, aempty_n, rinc, rclk, rrst_n);
  2. parameter ADDRSIZE = 4;
  3. output rempty;
  4. output [ADDRSIZE-1:0] rptr;
  5. input aempty_n;
  6. input rinc, rclk, rrst_n;
  7. reg [ADDRSIZE-1:0] rptr, rbin;
  8. reg rempty, rempty2;
  9. wire [ADDRSIZE-1:0] rgnext, rbnext;
  10. //---------------------------------------------------------------
  11. // GRAYSTYLE2 pointer
  12. //---------------------------------------------------------------
  13. always @(posedge rclk or negedge rrst_n)
  14. if (!rrst_n) begin
  15. rbin <= 0;
  16. rptr <= 0;
  17. end
  18. else begin
  19. rbin <= rbnext;
  20. rptr <= rgnext;
  21. end
  22. //---------------------------------------------------------------
  23. // increment the binary count if not empty
  24. //---------------------------------------------------------------
  25. assign rbnext = !rempty ? rbin + rinc : rbin;
  26. assign rgnext = (rbnext>>1) ^ rbnext; // binary-to-gray conversion
  27. always @(posedge rclk or negedge aempty_n)
  28. if (!aempty_n) {rempty,rempty2} <= 2'b11;
  29. else {rempty,rempty2} <= {rempty2,~aempty_n};
  30. endmodule

4.5 满标志

  1. module wptr_full (wfull, wptr, afull_n, winc, wclk, wrst_n);
  2. parameter ADDRSIZE = 4;
  3. output wfull;
  4. output [ADDRSIZE-1:0] wptr;
  5. input afull_n;
  6. input winc, wclk, wrst_n;
  7. reg [ADDRSIZE-1:0] wptr, wbin;
  8. reg wfull, wfull2;
  9. wire [ADDRSIZE-1:0] wgnext, wbnext;
  10. //---------------------------------------------------------------
  11. // GRAYSTYLE2 pointer
  12. //---------------------------------------------------------------
  13. always @(posedge wclk or negedge wrst_n)
  14. if (!wrst_n) begin
  15. wbin <= 0;
  16. wptr <= 0;
  17. end
  18. else begin
  19. wbin <= wbnext;
  20. wptr <= wgnext;
  21. end
  22. //---------------------------------------------------------------
  23. // increment the binary count if not full
  24. //---------------------------------------------------------------
  25. assign wbnext = !wfull ? wbin + winc : wbin;
  26. assign wgnext = (wbnext>>1) ^ wbnext; // binary-to-gray conversion
  27. always @(posedge wclk or negedge wrst_n or negedge afull_n)
  28. if (!wrst_n ) {wfull,wfull2} <= 2'b00;
  29. else if (!afull_n) {wfull,wfull2} <= 2'b11;
  30. else {wfull,wfull2} <= {wfull2,~afull_n};
  31. endmodule

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

闽ICP备14008679号