前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >异步FIFO理解[通俗易懂]

异步FIFO理解[通俗易懂]

作者头像
全栈程序员站长
发布2022-07-28 20:50:54
9970
发布2022-07-28 20:50:54
举报

大家好,又见面了,我是你们的朋友全栈君。

一、异步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理解[通俗易懂]
异步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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年4月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档