一、分析

由于是异步FIFO的设计,读写时钟不一样,在产生读空信号和写满信号时,会涉及到跨时钟域的问题,如何解决?
  跨时钟域的问题:由于读指针是属于读时钟域的,写指针是属于写时钟域的,而异步FIFO的读写时钟域不同,是异步的,要是将读时钟域的读指针与写时钟域的写指针不做任何处理直接比较肯定是错误的,因此我们需要进行同步处理以后仔进行比较
  解决方法加两级寄存器同步 + 格雷码(目的都是消除亚稳态)
 
1.使用异步信号进行使用的时候,好的设计都会对异步信号进行同步处理,同步一般采用多级D触发器级联处理,如下图。这种模型大部分资料都说的是第一级寄存器产生亚稳态后,第二级寄存器稳定输出概率为90%,第三极寄存器稳定输出的概率为99%,如果亚稳态跟随电路一直传递下去,那就会另自我修护能力较弱的系统直接崩溃。

2.将一个二进制的计数值从一个时钟域同步到另一个时钟域的时候很容易出现问题,因为采用二进制计数器时所有位都可能同时变化,在同一个时钟沿同步多个信号的变化会产生亚稳态问题。而使用格雷码只有一位变化,因此在两个时钟域间同步多个位不会产生问题。所以需要一个二进制到gray码的转换电路,将地址值转换为相应的gray码,然后将该gray码同步到另一个时钟域进行对比,作为空满状态的检测。

那么,多位二进制码如何转化为格雷码?

换一种描述方法:

verilog代码实现就一句:assign  gray_code = (bin_code>>1)  ^  bin_code;

 使用gray码解决了一个问题,但同时也带来另一个问题,即在格雷码域如何判断空与满。

这里直接给出结论:

  判断读空时:需要读时钟域的格雷码rgray_next和被同步到读时钟域的写指针rd2_wp每一位完全相同;

  判断写满时:需要写时钟域的格雷码wgray_next和被同步到写时钟域的读指针wr2_rp高两位不相同,其余各位完全相同;

二、Verilog实现

module  fifo
#(
  parameter WSIZE = ;
  parameter DSIZE = ;
)
(
  input wr_clk,
  input rst,
  input wr_en,
  input [WSIZE- : ]din,
  input rd_clk,
  input rd_en,
  output [WSIZE- : ]dout,
  output reg rempty,
  output reg wfull
); //定义变量
reg [WSIZE- :] mem [DSIZE- : ];
reg [WSIZE- : ] waddr,raddr;
reg [WSIZE : ] wbin,rbin,wbin_next,rbin_next;
reg [WSIZE : ] wgray_next,rgray_next;
reg [WSIZE : ] wp,rp;
reg [WSIZE : ] wr1_rp,wr2_rp,rd1_wp,rd2_wp;
wire rempty_val,wfull_val; //输出数据
assign dout = mem[raddr]; //输入数据
always@(posedge wr_clk)
  if(wr_en && !wfull)
    mem[waddr] <= din; //1.产生存储实体的读地址raddr; 2.将普通二进制转化为格雷码,并赋给读指针rp
always@(posedge rd_clk or negedge rst_n)
  if(!rst_n)
    {rbin,rp} <= ;
  else
    {rbin,rp} <= {rbin_next,rgray_next}; assign raddr = rbin[WSIZE- : ];
assign rbin_next = rbin + (rd_en & ~rempty);
assign rgray_next = rbin_next ^ (rbin_next >> ); //1.产生存储实体的写地址waddr; 2.将普通二进制转化为格雷码,并赋给写指针wp
always@(posedge wr_clk or negedge rst_n)
  if(!rst_n)
    {wbin,wp} <= ;
  else
    {wbin,wp} <= {wbin_next,wgray_next}; assign waddr = wbin[WSIZE- : ];
assign wbin_next = wbin + (wr_en & ~wfull);
assign wgray_next = wbin_next ^ (wbin_next >> ); //将读指针rp同步到写时钟域
always@(posedge wr_clk or negedge rst_n)
  if(!rst_n)
    {wr2_rp,wr1_rp} <= ;
  else
    {wr2_rp,wr1_rp} <= {wr1_rp,rp}; //将写指针wp同步到读时钟域
always@(posedge rd_clk or negedge rst_n)
  if(!rst_n)
    {rd2_wp,rd1_wp} <= ;
  else
    {rd2_wp,rd1_wp} <= {rd1_wp,wp}; //产生读空信号rempty
assign rempty_val = (rd2_wp == rgray_next);
always@(posedge rd_clk or negedge rst_n)
  if(rst_n)
    rempty <= 'b1;
  else
    rempty <= rempty_val; //产生写满信号wfull
assign wfull_val = ((~(wr2_rp[WSIZE : WSIZE-]),wr2_rp[WSIZE- : ]) == wgray_next);
always@(posedge wr_clk or negedge rst_n)
  if(!rst_n)
    wfull <= 'b0;
  else
    wfull <= wfull_val; endmodule

异步fifo的Verilog实现的更多相关文章

  1. 异步FIFO总结+Verilog实现

    异步FIFO简介 异步FIFO(First In First Out)可以很好解决多比特数据跨时钟域的数据传输与同步问题.异步FIFO的作用就像一个蓄水池,用于调节上下游水量. FIFO FIFO是一 ...

  2. 异步FIFO的verilog实现与简单验证(调试成功)

    最近在写一个异步FIFO的时候,从网上找了许多资料,文章都写的相当不错,只是附在后面的代码都多多少少有些小错误. 于是自己写了一个调试成功的代码,放上来供大家参考. 非原创 原理参考下面: 原文 ht ...

  3. 异步FIFO及verilog原码

    这几天看了Clifford E. Cummings的两篇大作<Simulation and Synthesis Techniques for Asynchronous FIFO Design&g ...

  4. 同步fifo与异步fifo

    参考以下帖子: https://blog.csdn.net/hengzo/article/details/49683707 https://blog.csdn.net/Times_poem/artic ...

  5. 怎么用Verilog语言描述同步FIFO和异步FIFO

    感谢 知乎龚大佬 打杂大佬 网上几个nice的博客(忘了是哪个了....) 前言 虽然FIFO都有IP可以使用,但理解原理还是自己写一个来得透彻. 什么是FIFO? Fist in first out ...

  6. Verilog设计异步FIFO

    转自http://ninghechuan.com 异步FIFO有两个异步时钟,一个端口写入数据,一个端口读出数据.通常被用于数据的跨时钟域的传输. 同步FIFO的设计.一个时钟控制一个计数器,计数器增 ...

  7. 异步fifo的设计

    本文首先对异步 FIFO 设计的重点难点进行分析 最后给出详细代码 一.FIFO简单讲解 FIFO的本质是RAM, 先进先出 重要参数:fifo深度(简单来说就是需要存多少个数据)           ...

  8. 基于FPGA的异步FIFO设计

    今天要介绍的异步FIFO,可以有不同的读写时钟,即不同的时钟域.由于异步FIFO没有外部地址端口,因此内部采用读写指针并顺序读写,即先写进FIFO的数据先读取(简称先进先出).这里的读写指针是异步的, ...

  9. 异步fifo的设计(FPGA)

    本文首先对异步 FIFO 设计的重点难点进行分析 最后给出详细代码 一.FIFO简单讲解 FIFO的本质是RAM, 先进先出 重要参数:fifo深度(简单来说就是需要存多少个数据)           ...

随机推荐

  1. windows server 2008 R2 计划任务备份系统

    实验环境拓扑图: 实验效果: Windows Server Backup 可以设置备份计划,但只能按日进行备份,不能设置按周或月进行备份.所以,需要使用到 windows Server 2008 R2 ...

  2. c# 正则匹配对称括号

    https://stackoverflow.com/questions/7898310/using-regex-to-balance-match-parenthesis

  3. centos7 centos中apache运行php需要连接mysql一直连不上,telnet访问mysql出错Connection closed by foreign host

    执行命令: getsebool -a|grep httpd 发现 httpd_can_network_connect off 解决:  setsebool httpd_can_network_conn ...

  4. 基于Java的数据采集(二)

    在上一篇文章<基于Java的数据采集(一)>:http://www.cnblogs.com/lichenwei/p/3904715.html 提到了如何如何读取网页源代码,并通过group ...

  5. irc

    https://www.irccloud.com/ webchat.freenode.net http://blog.csdn.net/wcc526/article/details/16993069 ...

  6. AngularJS中$timeout和$interval的用法详解

    1. 先将$interval,$timeout,作为参数注入到controller中,例如rds.controller('controllerCtrl', ['app', '$scope','$htt ...

  7. 网络编程 -- RPC实现原理 -- NIO多线程 -- 迭代版本V2

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——增加WriteQueue队列,存放selectionKey.addWriteEventToQueue()添加selectionKey并唤醒阻 ...

  8. CentOS 6 添加root权限账户

    sudo adduser william sudo passwd william //两次输入密码 赋予root权限 visudo 找到 ## Allow root to run any comman ...

  9. ios时间差

    /** * @method * * @brief 获取两个日期之间的天数 * @param fromDate       起始日期 * @param toDate         终止日期 * @re ...

  10. svn st 状态详解

    svn st status (stat, st): 显示工作副本中目录与文件的状态.用法: status [PATH...]  未指定参数时,只显示本地修改的条目(没有网络访问).  使用 -q 时, ...