大家好,又見面了,我是你們的朋友全棧君。
一、異步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

五、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