一、分析

由于是异步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. rqalpha环境搭建(windows版)

    windows环境: win7 64bit rqalpha版本3.0.9 参考文档:http://rqalpha.readthedocs.io/zh_CN/latest/intro/install.h ...

  2. easyradius通讯接口 V4全新升级,显示同步失败原因,方便用户寻找故障

    最近一段时间,我们做了很多的努力,不仅完成了WayOs.BV.ROS.IK.PA接口的重写(主要加入智能判断,能处理的直接处理,不能处理的告诉用户),而且在原有DDNS访问失败的提示下,升级了同步失败 ...

  3. shell脚本介绍
 shell脚本结构和执行
date命令用法
 shell脚本中的变量

  4. [原]Jenkins(九)---jenkins分别发布多个项目到多个远程主机

    /** * lihaibo * 文章内容都是根据自己工作情况实践得出. * 版权声明:本博客欢迎转发,但请保留原作者信息! http://www.cnblogs.com/horizonli/p/533 ...

  5. python 读取配置文件方法

    #coding=utf8 import ConfigParser config = ConfigParser.ConfigParser() config.readfp(open(raw_input(& ...

  6. 设备重力感应 window.DeviceOrientationEvent

    设备屏幕方向与运动 https://developers.google.cn/web/fundamentals/native-hardware/device-orientation/ MDN devi ...

  7. solus 系统 - 怎么使用中文输入法?

    系统默认使用 ibus 输入法框架. 可以安装 ibus-libpinyin $ sudo eopkg install ibus-libpinyin 安装好之后需要初始化 ibus-setup $ i ...

  8. 如何将MP3录音转文字

    相信很多人都有电话录音的习惯,因为这样可以记录下很多重要的信息.那么当我们通过录音将一些重要的信息记录下来后,我们应该怎样将这些录音文件转换成文字进行记录呢?下面我们就一起来看一下吧. 操作步骤: 步 ...

  9. Redis环境配置和命令语句

    环境配置 拷贝Redis-x64-3.2.100到本地一个目录下,解压 然后设置环境变量PATH到该目录 Redis-server.exe:Redis服务端 Redis-cli.exe:Redis客户 ...

  10. Type Operators instanceof is used to determine whether a PHP variable is an instantiated object of a certain class/a class that implements an interface

    w 0-instanceof is used to determine whether a PHP variable is an instantiated object of a certain cl ...