异步FIFO理解[通俗易懂]

一、异步FIFO与同步FIFO的区别 二、关键点及解决方法 三、深度的计算 四、整体结构图(style#1ifyouhavesawSNUGuserguide)SimulationandSynthesisTechniquesforAsynchronous的网盘链接链接:http://pan.baidu.com/s/1ntsqGjR密码:scf

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

一、异步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.net/129046.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • (怪盗基德的滑翔翼)(最长上升子序列)[通俗易懂]

    (怪盗基德的滑翔翼)(最长上升子序列)[通俗易懂]原题链接怪盗基德是一个充满传奇色彩的怪盗,专门以珠宝为目标的超级盗窃犯。而他最为突出的地方,就是他每次都能逃脱中村警部的重重围堵,而这也很大程度上是多亏了他随身携带的便于操作的滑翔翼。有一天,怪盗基德像往常一样偷走了一颗珍贵的钻石,不料却被柯南小朋友识破了伪装,而他的滑翔翼的动力装置也被柯南踢出的足球破坏了。不得已,怪盗基德只能操作受损的滑翔翼逃脱。假设城市中一共有N幢建筑排成一条线,每幢建筑的高度各不相同。初始时,怪盗基德可以在任何一幢建筑的顶端。他可以选择一个方向逃跑,但是不能中途改变方向

    2022年8月8日
    10
  • 亿图2021激活码【最新永久激活】「建议收藏」

    (亿图2021激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html1STL5S9V8F-eyJsa…

    2022年3月27日
    1.7K
  • Nginx原理简述

    Nginx原理简述Nginx 原理简介 1 nginx 的作用反向代理 隐藏服务器的地址 负载均衡 轮询 权重 ip hash 动静分离 nginx 作为静态资源服务器 对 nginx 的主要操作都是在改配置文件 2 nginx 原理 nginx 是以进程为单位的 这里是进程不是线程 每个进程有自己独立的资源 不用再像线程一样加锁了 如果你刚下载好了 nginx 你启动之后 打开任务管理器看一下有几个 nginx 进程 如果不出意外 它会有两个 nginx 进程 为什么会有两个进程呢 原理解析 nginx 里面 有两

    2025年8月11日
    3
  • OCX控件数字签名图文教程[通俗易懂]

    OCX控件数字签名图文教程[通俗易懂]这段时间做了一个B/S下套打的控件(过几天整理一下放到博客上来),控件测试完成,但是因为没有数字证书,IE如果不设置信任区域和等级的话,会直接被阻止下载安装(我不期望客户能熟练地改IE设置),但是数字证书价格昂贵,暂不考虑,看到cnblogs上一篇文章后深受启发,照着搞了一个测试用的数字签名,但是这篇文章上的OS貌似是win2000,IE5,我有必要在win7下给大家做个演示:首先,下载

    2022年7月13日
    14
  • noip2014普及组复赛题解_noip2019普及组复赛试题

    noip2014普及组复赛题解_noip2019普及组复赛试题NOIP2012普及组解题报告            byRtPYH——————————————————————————————————————前言:作者是一个蒟蒻,如果对本文有建议,欢迎提出!鄙人将虚心接受。

    2022年8月22日
    7
  • Xilinx原语ODDR的使用

    ODDRisXilinxHDLLanguageTemplate。ODDR:OutputDoubleDataRate(DDR)。在介绍ODDR之前,我们先简单了解一下OLOGIC。OLOGIC块在FPGA内的位置紧挨着IOB,其作用是FPGA通过IOB发送数据到器件外部的专用同步块。OLOGIC资源的类型有OLOGIC2(位于HPI/Obanks)和OLOGIC3(位于…

    2022年4月7日
    448

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号