Cummings异步FIFO——第一篇 (5)

写时钟控制,打两拍

module sync_r2w #(parameter ADDRSIZE = 4)
(output reg [ADDRSIZE:0] wq2_rptr,
input [ADDRSIZE:0] rptr,
input wclk, wrst_n);
reg [ADDRSIZE:0] wq1_rptr;
always @(posedge wclk or negedge wrst_n)
   if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
   else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
endmodule
6.4 写地址到读时钟域同步

读时钟控制,打两拍

module sync_w2r #(parameter ADDRSIZE = 4)
(output reg [ADDRSIZE:0] rq2_wptr,
input [ADDRSIZE:0] wptr,
input rclk, rrst_n);
reg [ADDRSIZE:0] rq1_wptr;
always @(posedge rclk or negedge rrst_n)
   if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
   else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
endmodule
6.5 空标志位产生

产生空标志位、n-1位当前的二进制读地址、n位格雷码读地址

产生空标志位的结构框图如下:

Cummings异步FIFO——第一篇

module rptr_empty #(parameter ADDRSIZE = 4)
(output reg rempty,
output [ADDRSIZE-1:0] raddr,
output reg [ADDRSIZE :0] rptr,
input [ADDRSIZE :0] rq2_wptr,
input rinc, rclk, rrst_n);
reg [ADDRSIZE:0] rbin;
wire [ADDRSIZE:0] rgraynext, rbinnext;
//-------------------
// GRAYSTYLE2 pointer
//-------------------
always @(posedge rclk or negedge rrst_n)  //格雷码计数器的第二种写法
if (!rrst_n) {rbin, rptr} <= 0;
else {rbin, rptr} <= {rbinnext, rgraynext};
// Memory read-address pointer (okay to use binary to address memory)
assign raddr = rbin[ADDRSIZE-1:0];//给到memory模块
assign rbinnext = rbin + (rinc & ~rempty);
assign rgraynext = (rbinnext>>1) ^ rbinnext;
//---------------------------------------------------------------
// FIFO empty when the next rptr == synchronized wptr or on reset
//---------------------------------------------------------------
   assign rempty_val = (rgraynext == rq2_wptr);//空判断是根据下一次要读的地址来判断的
always @(posedge rclk or negedge rrst_n)
   if (!rrst_n) rempty <= 1'b1;
   else rempty <= rempty_val;
endmodule
6.6 满标志产生

产生满标志、n-1位当前写地址、n位格雷码写地址

产生满标志位的结构框图如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzxjfj.html