格雷码异步FIFO

        格雷码设计异步FIFO,读快写慢,读时钟会出现漏采样的情况,漏采的数据留在FIFO中,导致满信号间断分布。

源文件:

 module dual_clk_fifo
 #(parameter DATESIZE = 8,
   parameter ADDRSIZE = 4,
   parameter ALMOST_GAP = 3
)
(
input [DATESIZE-1:0] wdata,
input winc, wclk, wrst_n,
input rinc, rclk, rrst_n,
output wire [DATESIZE-1:0] rdata,
output reg wfull,
output reg rempty,
output reg almost_full,
output reg almost_empty
);
wire [ADDRSIZE-1:0] waddr, raddr;
reg  [ADDRSIZE:0] wptr, rptr;
wire rempty_val,wfull_val;
//--------------------------------
// RTL Verilog memory model
//--------------------------------
localparam DEPTH = 1<<ADDRSIZE;
reg [DATESIZE-1:0] mem [0:DEPTH-1];
assign rdata = mem[raddr];
always @(posedge wclk)
if (winc && !wfull) mem[waddr] <= wdata;

//--------------------------------
// read-domain to write-domain synchronizer
//--------------------------------
reg [ADDRSIZE:0] wq1_rptr,wq2_rptr;
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};

//--------------------------------
// Write-domain to read-domain synchronizer
//--------------------------------
reg [ADDRSIZE:0] rq1_wptr,rq2_wptr;
always @(posedge rclk or negedge rrst_n)
if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};

//--------------------------------
//Read pointer & empty generation logic
//--------------------------------
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];
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 ;

//--------------------------------
// Write pointer & full generation logic
//--------------------------------
reg [ADDRSIZE:0] wbin;
wire [ADDRSIZE:0] wgraynext, wbinnext;
// GRAYSTYLE2 pointer
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) {wbin, wptr} <= 0;
else {wbin, wptr} <= {wbinnext, wgraynext};
// Memory write-address pointer (okay to use binary to address memory)
assign waddr = wbin[ADDRSIZE-1:0];
assign wbinnext = wbin + (winc & ~ wfull);
assign wgraynext = (wbinnext>>1) ^ wbinnext;
//------------------------------------------------------------------
// Simplified version of the three necessary full-tests:
// assign wfull_val=((wgnext[ADDRSIZE] !=wq2_rptr[ADDRSIZE] ) &&
// (wgnext[ADDRSIZE-1] !=wq2_rptr[ADDRSIZE-1]) &&
// (wgnext[ADDRSIZE-2:0]==wq2_rptr[ADDRSIZE-2:0]));
//------------------------------------------------------------------
wire [ADDRSIZE:0] full_flag;
assign full_flag = {~wq2_rptr[ADDRSIZE:ADDRSIZE-1],wq2_rptr[ADDRSIZE-2:0]};
assign wfull_val = (wgraynext==full_flag);
always @(posedge wclk or negedge wrst_n)
if (!wrst_n) wfull <= 1'b0;
else wfull <= wfull_val;

//--------------------------------
// almost full and empty logic
//--------------------------------
//Gray encoded read and write address decode to bin.
wire [ADDRSIZE:0]rq2_wptr_bin,wq2_rptr_bin;
wire almost_empty_val,almost_full_val;
assign rq2_wptr_bin[ADDRSIZE] = rq2_wptr[ADDRSIZE]; 
assign wq2_rptr_bin[ADDRSIZE] = wq2_rptr[ADDRSIZE];
genvar i;
generate
    for(i=ADDRSIZE-1;i>=0;i=i-1) begin:wpgray2bin          
        assign rq2_wptr_bin[i] = rq2_wptr_bin[i+1]^rq2_wptr[i];
        assign wq2_rptr_bin[i] = wq2_rptr_bin[i+1]^wq2_rptr[i];
    end
endgenerate

//--------------------------------
// read almost empty
//--------------------------------
wire [ADDRSIZE:0] rgap_reg;
assign rgap_reg = rq2_wptr_bin - rbin;
assign almost_empty_val = (rgap_reg <= ALMOST_GAP);

always @(posedge rclk or negedge rrst_n)
if (!rrst_n) almost_empty <= 1'b1;
else almost_empty <= almost_empty_val;

//--------------------------------
//write almost full
//--------------------------------
wire [ADDRSIZE:0] wgap_reg;
assign wgap_reg = (wbin[ADDRSIZE] ^ wq2_rptr_bin[ADDRSIZE])? wq2_rptr_bin[ADDRSIZE-1:0] - wbin[ADDRSIZE-1:0]:DEPTH + wq2_rptr_bin - wbin;
assign almost_full_val = (wgap_reg <= ALMOST_GAP);

always @(posedge wclk or negedge wrst_n)
if (!wrst_n) almost_full <= 1'b0;
else almost_full <= almost_full_val;


endmodule 

测试文件: 

`timescale 1 ns / 1 ps

module dual_clk_fifo_tb;

    parameter DATESIZE = 8;
    parameter ADDRSIZE = 3;
    parameter ALMOST_GAP = 1; 
    reg [DATESIZE-1:0]wdata;
    reg wrst_n;
    reg winc;
    reg rinc;
    reg wclk;
    reg rclk;
    reg rrst_n;
    wire [DATESIZE-1:0]rdata;
    wire wfull;
    wire rempty;
    wire almost_empty;
    wire almost_full;

    reg [3:0]a;
    reg [3:0]b;
    reg [4:0]c;
    reg x;
    initial begin
        $dumpfile("dual_clk_fifo_tb.vcd");
        $dumpvars;
        wdata = 0;
        wrst_n = 0;
        rinc = 0;
        rclk = 0;
        rrst_n = 0;
        wclk = 0;
        winc = 0;
    

        #2;wrst_n = 0; rrst_n = 0;
        #4;wrst_n = 1; rrst_n = 1;
     
        #100;
        $finish();

    end
 always @(posedge wclk or wrst_n)begin
    if( wrst_n == 1'b0 )begin 
        winc = 1'b0;
    end 
    else if( wfull )
        winc = 1'b0;
    else 
        winc = 1'b1 ;
end 
    
// rinc generate    
always @(posedge rclk or rrst_n)begin
    if( rrst_n == 1'b0 )begin
        rinc = 1'b0 ;
    end 
    else if( rempty )
        rinc = 1'b0;
    else 
        rinc = 1'b1 ;
end 

// wdata 
always @(posedge wclk or negedge wrst_n)begin
    if( wrst_n == 1'b0 )begin
        wdata = 0 ;
    end  
    else if( winc )begin 
        wdata = wdata + 1'b1;
    end 
end 

    always #0.5 wclk = ~wclk;
    always #2   rclk = ~rclk;


dual_clk_fifo #(
    .DATESIZE                       ( DATESIZE     ),
    .ADDRSIZE                       ( ADDRSIZE     ),
    .ALMOST_GAP                     ( ALMOST_GAP   ))
U_DUAL_CLK_FIFO_0(
    .wdata                          ( wdata ),
    .winc                           ( winc  ),
    .wclk                           ( wclk  ),
    .wrst_n                         ( wrst_n),
    .rinc                           ( rinc  ),
    .rclk                           ( rclk  ),
    .rrst_n                         ( rrst_n),
    .rdata                          ( rdata ),
    .wfull                          ( wfull ),
    .rempty                         ( rempty),
    .almost_empty              (almost_empty),
    .almost_full                (almost_full)
);


endmodule


 仿真波形:

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值