天天看點

異步FIFO了解[通俗易懂]

大家好,又見面了,我是你們的朋友全棧君。

一、異步FIFO與同步FIFO的差別

異步FIFO通常用于時鐘域的過渡,是雙時鐘設計,即FIFO工作于獨立的兩個時鐘之間,也就是讀寫時鐘域不同。

二、難點及解決方法

一是如何同步異步信号以及處理亞穩态問題;針對這一難點,采用的是使用格雷碼指針和二進制指針及握手信号。就是現将寫指針同步到讀時鐘域,讀指針同步到寫時鐘域,然後通過格雷碼判斷空滿。

二是如何正确地設計空/滿等信号的控制電路。針對這一難點,利用讀寫指針互相比較産生空/滿标志,采用兩種方法來辨識空/滿兩種狀态:

一種是在讀寫位址前加一位附加位,通過附加位來辨識空/滿狀态;(本文使用該種方法,其實兩種歸根結底就是加一個标志)

另一種方法是通過劃分位址空間來判斷。

三、深度的計算

網上找的一個例子,一個8bit寬的AFIFO,輸入時鐘為100MHz,輸出時鐘為95MHz,設一個package為4Kbit,且兩個package之間的發送間距足夠大。問AFIFO的深度。

burst_length=4K/8=500

deep=500-500X95/100 =25

四、格雷碼和二進制碼之間的轉換

1.gray to bin

always @ (gray)

for(i=0;i<SIZE;i=i+1)

bin[i] = bin[i]^(gray>>i)

2.bin to gray

assign gray = (bin>>1)^bin;

五、整體結構圖(style #1 if you have saw SNUG user guide)

Simulation and Synthesis Techniques for Asynchronous的網盤連結 連結:http://pan.baidu.com/s/1ntsqGjR 密碼:scfz

異步FIFO了解[通俗易懂]

五、Verilog關鍵代碼

//top

module asyn_fifo(

rdata, // Data path from FIFO

rempty, // Flag asserted high for empty stack

wfull , // Flag asserted high for full stack

wdata, // Data path into FIFO

winc,wclk,wrst_n,

rinc,rclk,rrst_n

);

parameter DSIZE = 8;

parameter ASIZE = 4;

output [DSIZE -1 : 0] rdata;

output rempty, wfull;

input [ASIZE -1 : 0] wdata;

input winc,wclk,wrst_n;

input rinc,rclk,rrst_n;

wire [ASIZE-1:0] waddr, raddr;

wire [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr;

sync_r2w i_sync_r2w (.wq2_rptr(wq2_rptr), .rptr(rptr),.wclk(wclk), .wrst_n(wrst_n));

sync_w2r i_sync_w2r (.rq2_wptr(rq2_wptr), .wptr(wptr),.rclk(rclk), .rrst_n(rrst_n));

fifomem #(DSIZE, ASIZE) i_fifomem

(.rdata(rdata), .wdata(wdata),

.waddr(waddr), .raddr(raddr),

.wclken(winc), .wfull(wfull),

.wclk(wclk));

rptr_empty #(ASIZE) i_rptr_empty

(.rempty(rempty),

.raddr(raddr),

.rptr(rptr), .rq2_wptr(rq2_wptr),

.rinc(rinc), .rclk(rclk),

.rrst_n(rrst_n));

wptr_full #(ASIZE) i_wptr_full

(.wfull(wfull), .waddr(waddr),

.wptr(wptr), .wq2_rptr(wq2_rptr),

.winc(winc), .wclk(wclk),

.wrst_n(wrst_n));

endmodule

//read to write

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)

wq1_rptr <= 0;

else wq1_rptr <= rptr;

always @(posedge wclk or negedge wrst_n)

if (!wrst_n)

wq2_rptr <= 0;

else wq2_rptr <= wq1_rptr;

endmodule

//write full

module wptr_full

#(parameter ADDRSIZE = 4)

(output reg wfull,

output [ADDRSIZE-1:0] waddr,

output reg [ADDRSIZE :0] wptr,

input [ADDRSIZE :0] wq2_rptr,

input winc, wclk, wrst_n);

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;

//——————————————————————

assign wfull_val = (wgraynext=={~wq2_rptr[ADDRSIZE:ADDRSIZE-1],wq2_rptr[ADDRSIZE-2:0]});

always @(posedge wclk or negedge wrst_n)

if (!wrst_n) wfull <= 1’b0;

else wfull <= wfull_val;

endmodule

module fifomem #(parameter DATASIZE = 8, // Memory data word width

parameter ADDRSIZE = 4) // Number of mem address bits

(output [DATASIZE-1:0] rdata,

input [DATASIZE-1:0] wdata,

input [ADDRSIZE-1:0] waddr, raddr,

input wclken, wfull, wclk);

reg [DATASIZE-1:0] mem[15:0];

asign rdata = mem[raddr];

always @(posedge wclk)

if (wclken && !wfull) mem[waddr] <= wdata;

endmodule

釋出者:全棧程式員棧長,轉載請注明出處:https://javaforall.cn/129046.html原文連結:https://javaforall.cn