异步FIFO(Verilog)

这篇具有很好参考价值的文章主要介绍了异步FIFO(Verilog)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介:

       FIFO(First In First Out)是异步数据传输时经常使用的存储器。该存储器的特点是数据先进先出(后进后出)。其实,多位宽数据的异步传输问题,无论是从快时钟到慢时钟域,还是从慢时钟到快时钟域,都可以使用 FIFO 处理。异步FIFO 是指读写时钟不一致,读写时钟是互相独立的。 在现代逻辑设计中,随着设计规模的不断扩大,一个系统中往往含有数个时钟,多时钟域带来的一个问题就是,如何设计异步时钟之间的接口电路。异步 FIFO 是这个问题的一种简便、快捷的解决方案,使用异步 FIFO 可以在两个不同时钟系统之间快速而方便地传输实时数据。

电路接口:

       控制电路将信号分为写入数据信号、读出数据信号、满信号、空信号、读使能信号、写使能信号、复位信号、时钟信号等。

信号名称

I/O

描述

w_clk

I

写时钟,频率50hz

r_clk     I    读时钟,频率25hz

w_rst_n

I

写复位清零

低有效

r_rst_n I 读复位清零 低有效

data_in

I

输入数据信号

wr_en

I

写使能信号

高有效

rd_en

I

读使能信号

高有效

data_out

O

输出数据信号

full

O

满信号

高有效

empty

O

空信号

高有效

原理图:

       典型异步 FIFO 结构图如下所示

异步fifo,fpga开发

设计思路:

双端口SRAM:

        FIFO 的存储用双端口 SRAM代替,用来存储写入的数据 data_in 以及读出的输出数据 data_out 。

        SRAM 的读写地址每次递增一个地址,保证了写入和读出按先进先出的顺序进行,写和读到最高地址后,重新返回零地址。

满信号、写地址生成电路:

        在原理图 SRAM 左侧为满信号以及写地址生成电路。这个电路通过判断写时钟域下,写指针和读指针的关系,然后生成满信号 full,以便停止对 FIFO 进行写操作,防止出现 FIFO 已满还在写的错误行为。

空信号、读地址生成电路:

        在原理图 SRAM 右侧为空信号以及读地址生成电路。这个电路通过判断读时钟域下,写指针和读指针的关系,然后生成满信号 empty,以便停止对 FIFO 进行读操作,防止出现 FIFO 已空还在读的错误行为。

        将读指针传递到写时钟域才能产生满信号,将写指针传递到读时钟域才能产生空信号,在两个不同时钟域下的指针进行对比,这里就涉及跨时钟域(CDC)的问题,需要打两拍来解决。

跨时钟域问题(CDC):

        将读指针同步到写时钟域,读指针可能会不变或增加(由于打拍会向后延迟两个时钟周期),而写指针本来就在写时钟域中,所以不必再次同步,也就是说,写指针和读指针做对比,写指针是真正的写指针,而同步后读指针是小于等于同步前的读指针,这样的作法,会导致满信号提前拉高,影响异步 FIFO 的性能,例如(深度为16,到14就满了),不会发生满了还在写的错误,但是会发生读空,却仍然有数据读出,所以这种情况就造成了FIFO的功能错误。

        将写指针同步到读时钟域,写指针可能会不变或增加(由于打拍会向后延迟两个时钟周期),而读指针本来就在读时钟域中,所以不必再次同步,也就是说,写指针和读指针做对比,读指针是真正的读指针,而同步后写指针是小于等于同步前的写指针,这样的作法,会导致 FIFO 已经写满但满信号还没有拉高,造成了FIFO的功能错误。但是不会发生读空,还接着读的现象。

异步fifo,fpga开发

        如图所示,将读指针同步到写时钟域,若在地址 2 处,FIFO 已经读空,则实际上读地址已经读到地址 4,会产生读空还读的错误;若在地址 2 处,FIFO 已经写满,则实际上读地址已经读到地址 4,会读空两个地址,只会产生性能的损失。所以进行写满判断时,应把读指针同步到写时钟域。

异步fifo,fpga开发

        如图所示,将写指针同步到读时钟域,若在地址 2 处,FIFO 已经写满,则实际上写地址已经写到地址 4,会产生写满还写的错误;若在地址 2 处,FIFO 已经读空,则实际上写地址已经写到地址 4,会写满两个地址,只会产生性能的损失。所以进行读空判断时,应把写指针同步到读时钟域。

        在进行跨时钟域处理时,每一个 bit 从 0 到 1 或从1 到 0 的变换都会有产生亚稳态的情况。亚稳态是指触发器无法在某个规定的时间段内到达一个可以确认的状态,如下图所示。

异步fifo,fpga开发

        为了减轻产生亚稳态对电路的影响,我们将二进制码转换为格雷码。格雷码是一种循环二进制码或者叫作反射二进制码。格雷码的特点是从一个数变为相邻的一个数时,只有一个数据位发生跳变,由于这种特点,就可以避免二进制编码计数组合电路中出现的亚稳态,并且当格雷码的最高位和次高位相同,其余位相同时认为是读空;当最高位和次高位不同,其余位相同认为是写满。

十进制 二进制 格雷码
0 0000 0000
1 0001 0001
2 0010 0011
3 0011 0010
4 0100 0110
5 0101 0111
6 0110 0101
7 0111 0100

二进制码转化为格雷码原理:

        二进制的最高位作为格雷码的最高位,次高位的格雷码为二进制的高位和次高位相异或得到,其他位与次高位类似。

设计代码:

module afifo_12_1024
 #(parameter 
   DATA_WIDTH = 12,
   DATA_DEPTH = 1024,
   ADDR_WIDTH = 10)
 (
     w_clk,
     w_rst_n,

     r_clk,
     r_rst_n,

     wr_en,
     rd_en,
     data_in,

     full,
     empty,
     data_out
 );

//**********************Port definition***********************//

           input wr_en;
           input rd_en;
           input [DATA_WIDTH-1:0] data_in;
 
           input w_clk;
           input w_rst_n;

           input r_clk;
           input r_rst_n;
 
           output full;
           output empty;
           output reg [DATA_WIDTH-1:0] data_out;

//******************write address generation******************//

           reg [ADDR_WIDTH:0] waddr_ptr; 
     always@(posedge w_clk or negedge w_rst_n)
            if(!w_rst_n)
               waddr_ptr <= 'd0; 
            else if((full == 'd0) && (wr_en))begin
               if(waddr_ptr >= 'd1023)
                  waddr_ptr <= 'd0;
               else
                  waddr_ptr <= waddr_ptr + 1'd1;
            end
            else 
               waddr_ptr <= waddr_ptr;

           wire [ADDR_WIDTH-1:0] waddr;
     assign waddr= waddr_ptr[ADDR_WIDTH-1:0];

//******************read address generation*******************//

           reg [ADDR_WIDTH:0] raddr_ptr;
     always@(posedge r_clk or negedge r_rst_n)
            if(!r_rst_n)
               raddr_ptr <= 'd0; 
            else if((empty == 'd0) && (rd_en))begin
               if(raddr_ptr >= 'd1023)
                  raddr_ptr <= 'd0;
               else
                  raddr_ptr <= raddr_ptr + 1'd1;
            end
            else 
               raddr_ptr <= raddr_ptr;

            wire [ADDR_WIDTH-1:0] raddr;
      assign raddr = raddr_ptr[ADDR_WIDTH-1:0];

//****************Binary conversion Gray code*****************//

            wire [ADDR_WIDTH:0] waddr_gray;
      assign waddr_gray = (waddr_ptr >> 1) ^ waddr_ptr;

            wire [ADDR_WIDTH:0] raddr_gray;
      assign raddr_gray = (raddr_ptr >> 1) ^ raddr_ptr;

//************Cross-clock domain processing(CDC)**************//

            reg [ADDR_WIDTH:0] waddr_gray_dly1;
            reg [ADDR_WIDTH:0] waddr_gray_dly2;
      always@(posedge r_clk or negedge r_rst_n)
            if(!r_rst_n)
              {waddr_gray_dly2,waddr_gray_dly1} <= 'd0;
            else
              {waddr_gray_dly2,waddr_gray_dly1} <= {waddr_gray_dly1,waddr_gray};

            reg [ADDR_WIDTH:0] raddr_gray_dly1;
            reg [ADDR_WIDTH:0] raddr_gray_dly2;
      always@(posedge w_clk or negedge w_rst_n)
            if(!w_rst_n)
              {raddr_gray_dly2,raddr_gray_dly1} <= 'd0;
            else
              {raddr_gray_dly2,raddr_gray_dly1} <= {raddr_gray_dly1,raddr_gray};
              
//****************empty full signal generation****************//
    
      assign full  = ((waddr_gray[ADDR_WIDTH:ADDR_WIDTH-1] !== raddr_gray_dly2[ADDR_WIDTH:ADDR_WIDTH-1]) &&
                      (waddr_gray[ADDR_WIDTH-2:0] == raddr_gray_dly2[ADDR_WIDTH-2:0]) && (w_rst_n))? 'd1:'d0;
      assign empty = ((raddr_gray == waddr_gray_dly2) && (r_rst_n))? 'd1:'d0;   

//***********************write to fifo************************//

            integer i;
            reg [ADDR_WIDTH-1:0] sram [0:DATA_DEPTH-1];
      always@(posedge w_clk or negedge w_rst_n)
            if(!w_rst_n)            
              for(i = 0; i < DATA_DEPTH;i = i + 1) begin
               sram[i] <= 'd0;
              end
            else if(wr_en && (!full))
               sram[waddr] <= data_in;

//******************read out to the fifo**********************//

      always@(posedge r_clk or negedge r_rst_n)
            if(!r_rst_n)            
               data_out <= 'd0; 
            else if(rd_en && (!empty))
               data_out <= sram[raddr];
            else 
               data_out <= data_out;
                  
endmodule

仿真代码:

`timescale 1ns/1ps
`define clk_period 20
module afifo_12_1024_tb();

           reg wr_en;
           reg rd_en;
           reg [11:0] data_in;
 
           reg w_clk;
           reg w_rst_n;

           reg r_clk;
           reg r_rst_n;
 
           wire full;
           wire empty;
           wire [11:0] data_out;

  afifo_12_1024  u1(
          .w_clk(w_clk),
          .w_rst_n(w_rst_n),

          .r_clk(r_clk),
          .r_rst_n(r_rst_n),

          .wr_en(wr_en),
          .rd_en(rd_en),
          .data_in(data_in),

          .full(full),
          .empty(empty),
          .data_out(data_out)
 );

 initial w_clk = 1;
 always # 10 w_clk = ~ w_clk;

 initial r_clk = 1;
 always # 20 r_clk = ~ r_clk;

 initial begin
   r_rst_n = 'd0;
   w_rst_n = 'd0;
   wr_en = 'd0;
   rd_en = 'd0;
   data_in = 'd0;
   
   #(`clk_period*10+1);

   w_rst_n = 'd1;
   r_rst_n = 'd1;

   #(`clk_period*10);
   
   data_in = 'd0;
   
   repeat(1023)begin
   wr_en = 'd1;
   data_in = data_in + 'd1;
   #(`clk_period);  
   end
   wr_en = 'd0;
   
   #(`clk_period*100);

   rd_en = 'd1;
  
   #(`clk_period*3000);
  
   rd_en = 'd0;

   #(`clk_period*10);

   $stop;

end
endmodule

仿真波形:

异步fifo,fpga开发

异步fifo,fpga开发

异步fifo,fpga开发文章来源地址https://www.toymoban.com/news/detail-720050.html

到了这里,关于异步FIFO(Verilog)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Verilog功能模块——读写位宽不同的异步FIFO

    Verilog功能模块——读写位宽不同的异步FIFO

    FIFO系列文章目录: Verilog功能模块——异步FIFO-CSDN博客 Verilog功能模块——同步FIFO-CSDN博客 Verilog功能模块——读写位宽不同的异步FIFO-CSDN博客 Verilog功能模块——读写位宽不同的同步FIFO-CSDN博客 Verilog功能模块——标准FIFO转FWFT FIFO-CSDN博客 前面的博文已经讲了异步FIFO和同步

    2024年02月01日
    浏览(11)
  • <FPGA>异步FIFO的Verilg实现方法

    <FPGA>异步FIFO的Verilg实现方法

            在上篇文章:同步FIFO的两种Verilog设计方法(计数器法、高位扩展法)中我们介绍了FIFO的基本概念,并对同步FIFO的两种实现方法进行了仿真验证。而异步FIFO因为读写时钟不一致,显然无法直接套用同步FIFO的实现方法,所以在本文我们将用Verilog实现异步FIFO的设计。

    2024年02月07日
    浏览(14)
  • FPGA的通用FIFO设计verilog,1024*8bit仿真,源码和视频

    FPGA的通用FIFO设计verilog,1024*8bit仿真,源码和视频

    名称:FIFO存储器设计1024*8bit 软件:Quartus 语言:Verilog 本代码为FIFO通用代码,其他深度和位宽可简单修改以下参数得到 代码功能: 设计一个基于FPGA的FIFO存储器,使之能提供以下功能  1.存储空间至少1024 储器  2.存储位宽8bit  3.拓展功能:存储器空、满报警 演示视频:http://

    2024年02月06日
    浏览(13)
  • 【FIFO】异步 FIFO 设计

    【FIFO】异步 FIFO 设计

    目录   写在前面 简介 传递多个异步信号 同步 FIFO 指针 异步FIFO指针 二进制 FIFO 指针注意事项 FIFO测试问题 格雷码计数器 ‑ 样式 #1 格雷码模式 格雷码计数器基础 额外的格雷码计数器注意事项 格雷码计数器 ‑ 样式 #2 处理满空情况 产生空标志 产生满标志 不同的时钟速度

    2024年02月02日
    浏览(7)
  • IC设计入门——异步FIFO

    IC设计入门——异步FIFO

    在异步FIFO中,数据读取和写入操作使用不同的时钟频率。由于写入和读取时钟不同步,因此称为异步FIFO。通常,这些用于数据需要从一个时钟域传递到另一个时钟域的系统中,这通常称为“时钟域交叉”。因此,异步FIFO有助于在两个工作于不同时钟的系统之间同步数据流。

    2024年02月19日
    浏览(12)
  • 跨时钟域方法(同步器、异步FIFO、边沿检测器、脉冲同步器、同步FIFO)

    跨时钟域方法(同步器、异步FIFO、边沿检测器、脉冲同步器、同步FIFO)

    目录 1、跨时钟域方法的原因 2、跨时钟处理的两种思路 3、跨时钟域分类——单比特信号跨时钟 3.1.1慢时钟———快时钟。(满足三边沿准则,有效事件可以被安全采样) 3.1.2慢时钟———快时钟。(不满足三边沿准则,有效事件可以被安全采样) 3.2.1有效事件传输背景下确

    2024年02月12日
    浏览(29)
  • Verilog同步FIFO设计

    Verilog同步FIFO设计

    同步FIFO(synchronous)的 写时钟和读时钟为同一个时钟,FIFO内部所有逻辑都是同步逻辑 ,常常用于交互数据缓冲。 异步FIFO:数据写入FIFO的时钟和数据读出FIFO的时钟是异步的(asynchronous) 典型同步FIFO有三部分组成: (1) FIFO写控制逻辑; (2)FIFO读控制逻辑; (3)FIFO 存储实体(

    2024年02月12日
    浏览(33)
  • 基于异步FIFO的串口回环测试

    基于异步FIFO的串口回环测试

      当涉及到串口通信的硬件设计和软件开发时,进行有效的测试是至关重要的。串口回环测试是一种常见的测试方法,用于验证串口通信的功能和稳定性。在许多应用中,为了确保串口通信的正常运行,往往需要使用缓冲区或FIFO来管理数据的传输和接收。   基于异步F

    2024年02月16日
    浏览(12)
  • FPGA之FIFO详解,初识FIFO

    FPGA之FIFO详解,初识FIFO

           在篇博客里引入FIFO IP核的概念,FIFO是FPGA中最常用的IP核,经常用在接口模块、串并转换、协议处理、数据缓存等很多场合,所以活学活用这个IP核对于后期项目开发很重要,并且灵活掌握FIFO,也是一名合格的FPGA工程师的一项基本功。        FIFO顾名思义就是First

    2024年01月20日
    浏览(15)
  • FPGA FIFO基本介绍(FIFO Geneerator(13.2))

    FPGA FIFO基本介绍(FIFO Geneerator(13.2))

    软件:vivado 2020.2  参考文献: 文档xilinx官网pg057-fifo-generator文档下载链接官网https://docs.xilinx.com/v/u/en-US/pg057-fifo-generatorhttps://docs.xilinx.com/v/u/en-US/pg057-fifo-generator https://docs.xilinx.com/v/u/en-US/pg057-fifo-generator 原官网免费文档已被上传为付费文档,笔者上传的免费文档未过审核。

    2024年01月25日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包