FPGA中FIFO的应用(二)——异步FIFO设计

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


⭐️作者简介:小瑞同学,一个努力精进的FPGA和通信学习者。
🍎个人主页:小瑞同学的博客主页
🌻个人信条:越努力,越幸运!
⏰日期:2023.12.3
🔍来源:自学经历
📖文章内容概述:介绍了异步FIFO的基本工作原理和深度计算,通过仿真观察了其读写过程。


连载系列:FPGA中FIFO的应用
完整工程已上传至CSDN:下载链接

  • 同步FIFO设计
  • 异步FIFO设计
  • Vivado FIFO IP核的调用

1.异步FIFO简介

1.1 概述

☀️异步FIFO是指读写受两个不同的时钟控制,一般用于数据的跨时钟域传递以及不同数据宽度的数据接口。对于单bit信号跨时钟域可以使用简单的打拍进行同步,而对于多bit信号的跨时钟域传递,就需要使用异步FIFO了。

1.2 主要参数

☀️异步FIFO的主要参数和同步FIFO基本相同,主要的区别的是异步FIFO有读时钟rd_clk写时钟wr_clk两个时钟。

参数 意义
读时钟 ——
写时钟 ——
FIFO的宽度 FIFO一次读写的数据位宽
FIFO的深度 FIFO中存储的数据个数
空标志 FIFO已空时发出空信号,以阻止读操作继续读取无效数据
满标志 FIFO已满时发出满信号,以阻止写操作继续向FIFO中写数据而导致FIFO溢出

2.空满判断

2.1 高位扩展法

☀️异步FIFO的设计难点在于空满标志的判断,由于其读写时钟不同,无法用上篇文章提到的的计数器法进行判断
☀️这里我们采用高位扩展法高位扩展法就是将读写地址变量扩展出一个最高位作为判断位,判断位和地址组成读指针变量rd_ptr和写指针变量wr_ptr,对于二进制地址数据,判断方法如下:

  • 对于空标志,rd_ptrwr_ptr所经过的路径相同,反应在变量数值上就是 rd_ptr=wr_ptr
  • 对于满标志,wr_ptr需要比rd_ptr多走一圈,反应在变量数值上就是rd_ptr和wr_ptr的最高位不同,而其它位相同

FPGA中FIFO的应用(二)——异步FIFO设计,fpga开发,信号处理

2.2 空满标志的时钟域同步

☀️由于读写过程由不同时钟控制,所以在比较读写指针前需要先对其进行时钟域同步。但是这里存在一个问题,如果直接使用二进制数据进行同步的话,会出现多位数据同时跳变,这样就增大了出错的概率。格雷码可以很好的解决这个问题,相邻的两个格雷码之间只有1位不同,所以在同步之前我们先将二进制数据转化为格雷码。

2.3 二进制数和格雷码之间的转换

四位二进制数和格雷码的对应关系如下图所示。

FPGA中FIFO的应用(二)——异步FIFO设计,fpga开发,信号处理

具体的转化公式如下:

格雷码转二进制:
FPGA中FIFO的应用(二)——异步FIFO设计,fpga开发,信号处理

二进制转格雷码:
FPGA中FIFO的应用(二)——异步FIFO设计,fpga开发,信号处理
我们将二进制地址指针转化为对应的格雷码wr_grayrd_gray,然后进行时钟同步:

  • 时钟上升沿,将rd_gray打两拍延时得到rd_gray_d2
  • 时钟上升沿,将wr_gray打两拍延时得到wr_gray_d2

在转化为格雷码后,空满标志的判断标准将不同于二进制:

  • 空标志:rd_gray==wr_gray_d2。
  • 满标志:wr_gray和rd_gray_d2的最高位和次高位相反,而其它各位相等

例如:对于深度为8的FIFO,其地址宽度为3,当rd_ptr的二进制数为0001时,如果是满状态的话wr_ptr应该为1001,参考上表,对应的格雷码分别为0001和1101,即最高位和次高位相反,其它各位相等。

3.异步FIFO的深度计算

☀️在跨时钟域数据传递用到异步FIFO时,往往需要计算FIFO的理论最小深度,而实际FIFO深度通常要大于计算值
☀️现考虑这样的场景,假设模块A以一定的时钟频率不间断地向FIFO中写数据,而模块B以慢于A的时钟频率不间断地从FIFO中读取数据,如果系统一直工作,那么FIFO中的数据会越累积越多,需要FIFO的深度就是无穷大的,这并不现实。所以只有在突发传输过程中讨论FIFO的深度才有意义。要确定FIFO的深度,就要计算出在突发读写这段时间内有多少数据没有被读走

突发传输:短时间内进行相对高带宽的数据传输

这里举一个简单的题:

问:一个8bit位宽的FIFO,输入时钟是100MHz,输出时钟是50MHz,设计一个读写包文的缓存是2Kbit,两个包文间的发送时间间隔足够大,求异步FIFO的最小读写深度。

答:

  • 发送包文的突发长度是 250 B y t e 250Byte 250Byte,每个地址存取1个 B y t e Byte Byte
  • 输入时钟周期为 10 n s 10ns 10ns,输出时钟周期为 20 n s 20ns 20ns
  • 前一模块发送包文,写入FIFO所用的时间为 2000 / 8 ∗ 10 = 2500 n s 2000/8*10=2500 ns 2000/810=2500ns
  • 在这段时间内,后一模块接收包文,从FIFO中读出读取的数据量为 2500 / 20 = 125 B y t e 2500/20=125Byte 2500/20=125Byte
  • 异步FIFO理论最小深度为 250 B y t e − 125 B y t e = 125 B y t e 250Byte-125Byte=125Byte 250Byte125Byte=125Byte

有关FIFO深度计算更细致的讲解,可参考该文章:FIFO深度计算

4.verilog代码


module FIFO_asyn
#(parameter FIFO_WIDTH=8,
  parameter FIFO_DEPTH=16)
(
    input                        wclk   ,
    input                        rclk   ,
    input                        wr_rstn,
    input                        rd_rstn,
    input                        wr_en  ,
    input                        rd_en  ,
    input       [FIFO_WIDTH-1:0] din    ,
    
    output                       empty  ,
    output                       full   ,
    output reg  [FIFO_WIDTH-1:0] dout    
    );
    
localparam ADDR_LEN=$clog2(FIFO_DEPTH);
localparam PTR_LEN=ADDR_LEN+1;
//读写地址    
wire [ADDR_LEN-1:0] wr_addr;
wire [ADDR_LEN-1:0] rd_addr;
//读写指针
reg [PTR_LEN-1:0] wr_ptr;
reg [PTR_LEN-1:0] rd_ptr;
//读写指针对应的格雷码
wire [PTR_LEN-1:0] wr_gray;
wire [PTR_LEN-1:0] rd_gray;
//打拍寄存器变量
reg [PTR_LEN-1:0] wr_gray_d1;
reg [PTR_LEN-1:0] wr_gray_d2;
reg [PTR_LEN-1:0] rd_gray_d1;
reg [PTR_LEN-1:0] rd_gray_d2;
//FIFO
reg [FIFO_WIDTH-1:0] fifo [0:FIFO_DEPTH-1];
//读写指针为1bit判断位和读写地址的拼接
assign wr_addr=wr_ptr[ADDR_LEN-1:0];
assign rd_addr=rd_ptr[ADDR_LEN-1:0];
//二进制转格雷码
assign wr_gray=(wr_ptr>>1)^wr_ptr;
assign rd_gray=(rd_ptr>>1)^rd_ptr;
//空满判断
assign empty=(wr_gray_d2==rd_gray) ? 1'b1:1'b0;
assign full=(wr_gray=={~rd_gray_d2[PTR_LEN-1:PTR_LEN-2],rd_gray_d2[PTR_LEN-3:0]})? 1'b1: 1'b0;
//写FIFO
always@(posedge wclk or negedge wr_rstn)begin
    if(!wr_rstn)begin
        wr_ptr<='b0;        
    end
    else if(wr_en&&!full)begin        
        fifo[wr_addr]<=din;
        wr_ptr<=wr_ptr+1'b1;       
    end
    else begin
        wr_ptr<=wr_ptr;
    end
end

//读FIFO
always@(posedge rclk or negedge rd_rstn)begin
    if(!rd_rstn)begin
        rd_ptr<='b0;
        dout<='b0;
    end
    else if(rd_en&&!empty)begin
        dout<=fifo[rd_addr];
        rd_ptr<=rd_ptr+1'b1;                        
    end
    else begin
        rd_ptr<=rd_ptr;
        dout<=dout;
    end
end

//将写指针同步到读时钟域
always@(posedge rclk or negedge rd_rstn)begin
    if(!rd_rstn)begin
        wr_gray_d1<='b0;
        wr_gray_d2<='b0;
    end
    else begin
        wr_gray_d1<=wr_gray;
        wr_gray_d2<=wr_gray_d1;
    end
end
//将读指针同步到写时钟域
always@(posedge wclk or negedge wr_rstn)begin
    if(!wr_rstn)begin
        rd_gray_d1<='b0;
        rd_gray_d2<='b0;
    end
    else begin
        rd_gray_d1<=rd_gray;
        rd_gray_d2<=rd_gray_d1;
    end
end
endmodule

5.仿真分析

5.1 参考testbench文件

`timescale 1ns / 1ps

module tb();

parameter FIFO_WIDTH=8;

reg wclk;
reg rclk;
reg rstn;
reg wr_en;
reg rd_en;
reg [FIFO_WIDTH-1:0] din;
wire empty;
wire full;
wire [FIFO_WIDTH-1:0] dout;

initial begin
    wclk=1'b0;
    rclk=1'b0;
    rstn=1'b0;
    wr_en=1'b0;
    rd_en=1'b0;
    din='b0;
    #15;
    rstn=1'b1;
    
    repeat(16)wr_only;
    repeat(16)rd_only;    
    repeat(5)wr_rd;
    
    #30;
    wr_en=1'b0;
    rd_en=1'b0;
    $stop;
end

always #10 wclk=~wclk;
always #20 rclk=~rclk;

//只写的任务
task wr_only;
begin
    @(negedge wclk)begin
        wr_en=1'b1;
        rd_en=1'b0;
        din={$random}%(2^FIFO_WIDTH);//生成0~2^FIFO_WIDTH-1的随机数
    end
end
endtask
//只读的任务
task rd_only;
begin
    @(negedge rclk)begin
        rd_en=1'b1;
        wr_en=1'b0;
    end
end
endtask
//读写的任务
task wr_rd;
begin
    @(negedge rclk)begin
        rd_en=1'b1;
   end
    @(negedge wclk)begin       
        wr_en=1'b1;
        din={$random}%(2^FIFO_WIDTH);
   end
    
end
endtask
FIFO_asyn FIFO_asyn_u
(
    . wclk   (wclk),
    . rclk   (rclk),
    . wr_rstn (rstn),
    . rd_rstn (rstn),
    . wr_en  (wr_en),
    . rd_en  (rd_en),
    . din    (din),
    . empty  (empty),
    . full   (full),
    . dout   (dout)
    );
endmodule


5.2 仿真结果

可以看到,读写过程都按照各自的时钟频率进行,空满标志可以正确产生。

FPGA中FIFO的应用(二)——异步FIFO设计,fpga开发,信号处理


❤️如果觉得文章对你有所帮助的话,别忘了点个收藏哦~
❤️更多优质内容可浏览本人主页👇,期待再次与你相遇!
🎉🎉🎉🎉🎉🎉小瑞同学的博客主页🎉🎉🎉🎉🎉🎉文章来源地址https://www.toymoban.com/news/detail-772327.html

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

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

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

相关文章

  • 数字信号处理-11-FPGA FFT IP应用实例

    本文根据FFT相关原理进行设计构建工程,仿造前文的工程构建的混频功能的工程,设计工程显示该混频信号的功率谱,然后进行仿真分析。 本文不再针对FFT的原理进行过多赘述,提供一份简单的matlab仿真代码。根据仿真简述下FFT的相关使用注意事项。 代码设计,模拟生成了

    2024年02月02日
    浏览(45)
  • 基带信号处理设计原理图:2-基于6U VPX的双TMS320C6678+Xilinx FPGA K7 XC7K420T的图像信号处理板

    基于6U VPX的双TMS320C6678+Xilinx FPGA K7 XC7K420T的图像信号处理板          综合图像处理硬件平台包括图像信号处理板2块,视频处理板1块,主控板1块,电源板1块,VPX背板1块。 一、板卡概述          图像信号处理板包括2片TI 多核DSP处理器-TMS320C6678,1片Xilinx FPGA XC7K420T-

    2024年03月15日
    浏览(63)
  • 图像信号处理板设计原理图:2-基于6U VPX的双TMS320C6678+Xilinx FPGA K7 XC7K420T的图像信号处理板

             综合图像处理硬件平台包括图像信号处理板2块,视频处理板1块,主控板1块,电源板1块,VPX背板1块。 一、板卡概述          图像信号处理板包括2片TI 多核DSP处理器-TMS320C6678,1片Xilinx FPGA XC7K420T-1FFG1156,1片Xilinx FPGA XC3S200AN。实现四路千兆以太网输出,两路

    2024年02月04日
    浏览(59)
  • 【FPGA数据采集测试系统】——基于FPGA的通用数据采集测试系统是当今数字电路领域最热门的研究课题之一。它不仅可以用于数字信号处理,而且也被广泛应用于音频、视...

    【FPGA数据采集测试系统】——基于FPGA的通用数据采集测试系统是当今数字电路领域最热门的研究课题之一。它不仅可以用于数字信号处理,而且也被广泛应用于音频、视频以及其他多媒体领域。 此外,基于FPGA的数据采集测试系统还可以用于传感器接口、机器视觉、自动控制

    2024年02月09日
    浏览(47)
  • 【FPGA】分享一些FPGA高速信号处理相关的书籍

      在做FPGA工程师的这些年,买过好多书,也看过好多书,分享一下。         后续会慢慢的补充书评。 【FPGA】分享一些FPGA入门学习的书籍 【FPGA】分享一些FPGA协同MATLAB开发的书籍  【FPGA】分享一些FPGA视频图像处理相关的书籍  【FPGA】分享一些FPGA高速信号处理相关的书籍

    2024年02月04日
    浏览(47)
  • FPGA 音频信号处理

    第八届集创赛杯赛题目——紫光同创杯 - 全国大学生集成电路创新创业大赛 题目任务要求:采集信号、降噪、识别、视频展示。 硬件:麦克风、扬声器、FPGA(盘古50)、HDMI显示器 软件:紫光同创PDS(用于部署)、anaconda、jupyter(用于部署训练网络) 1.麦克风采集好数据经过

    2024年03月14日
    浏览(55)
  • <FPGA>异步FIFO的Verilg实现方法

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

    2024年02月07日
    浏览(66)
  • FPGA与LVDS:数字信号处理的完美组合

    FPGA与LVDS:数字信号处理的完美组合 FPGA(Field-Programmable Gate Array)是一种可编程逻辑器件,具有高度灵活性和可重构性,可实现各种数字逻辑和处理功能。而LVDS(Low-Voltage Differential Signaling)则是一种用于高速数据传输的技术,特点是传输距离长、抗干扰能力强、带宽大。

    2024年01月23日
    浏览(52)
  • 【FPGA-DSP】第九期:音频信号处理

    从本文开始将记录一些简单的 音频信号处理算法 在System Generator中的实现方法。本文将介绍如何搭建音频信号的采集与输出模型。 音频信号属于一维信号,一些基本概念如下: 采样频率:根据奈奎斯特采样定理,采样频率Fs应该不低于声音信号中最高频率2倍。常见的音频格

    2024年02月01日
    浏览(53)
  • 数字信号处理----数字上变频和下变频都FPGA实现

    数字上变频器(DUC)和数字下变频器(DDC)广泛应用于通信系统,用于信号采样速率的转换。当信号从基带转换至中频( IF )带,需要使用数字上变频器。而数字下变频器是用于将信号从中频( IF )带转换为基带。DUC和DDC通常包括使用混频器进行频率转换,此外还有采样率

    2024年01月16日
    浏览(57)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包