异步FIFO是如何工作的?它的原理是什么?
1. 为什么 FIFO 能做跨时钟域2. 为什么 Vivado/Xilinx FIFO 的实际深度有时候不是你配置的深度而是多 1、少 1 或多 2一、先纠正一下一直以来我都认为fifo是做了数据的跨时钟域同步实际上严格说FIFO 不是把“数据本身同步”过去。异步 FIFO 是把两个时钟域“隔离开”然后只同步少量控制信息。比如你有wr_clk 域摄像头 / ADC / 以太网接收 rd_clk 域系统处理 / DDR / AXI / 图像处理如果你直接把data[15:0]从wr_clk域送到rd_clk域会出问题因为rd_clk可能在数据变化的瞬间采样导致多 bit 数据被采成乱值。异步 FIFO 的做法是wr_clk 域只负责写入 RAM rd_clk 域只负责从 RAM 读出 数据本身存在 RAM 里 跨时钟传递的不是 data而是“写指针”和“读指针”所以 FIFO 能跨时钟域的本质是数据不直接跨域跨域的是经过特殊处理的指针。这么说可能大家还是不太明白相当于是两个接力赛运动员之间要进行交接A运动员速度很快B运动员速度很慢A运动员直接把接力棒放在一个容器里面。B运动员即使很慢只要A运动员把接力棒放好了B运动员就可以非常顺利的带着接力棒出发。二、异步 FIFO 的基本结构一个异步 FIFO 大概长这样wr_clk 域 rd_clk 域 wr_en, din rd_en, dout | | v v 写指针 wr_ptr_bin 读指针 rd_ptr_bin | | v v 双口 RAM / BRAM / FIFO Memory ^ ^ | | 同步过来的 rd_ptr_gray 同步过来的 wr_ptr_gray 判断 full 判断 empty它里面有几个核心部分双口存储器一个端口用写时钟一个端口用读时钟写指针写域维护表示下一个写入位置读指针读域维护表示下一个读出位置Gray 码指针用于跨时钟同步两级同步器同步对方时钟域传过来的 Gray 指针full / empty 判断逻辑各自在本时钟域判断。FIFO_full是写时钟域的信号FIFO_empty是读时钟域的信号三、为什么用Gray 码指针假设写指针是二进制0111 - 1000从 7 变成 8 的时候4 个 bit 都变了。如果你把这个二进制指针直接同步到读时钟域读时钟域可能在它变化的中间采样到0000 1100 1010 1110这些都是错误中间态。这和多 bit 数据跨时钟域一样会出现“撕裂”。时钟在进行采样的时候很容易采样到错误的数据。所以异步 FIFO 通常会把二进制指针转换成Gray 码关于格雷码感兴趣的可以了解一下binary: 000 - 001 - 010 - 011 - 100 gray: 000 - 001 - 011 - 010 - 110Gray 码的特点是相邻两个数之间只有 1 个 bit 变化。所以格雷码就比较稳定。这样即使跨时钟域采样时刚好遇到变化也最多是“旧值”或“新值”不会采到乱七八糟的中间值。四、怎么判断 full / empty FIFO 的本质就是一个环形队列。写指针表示下一个要写的位置。读指针表示下一个要读的位置。如果wr_ptr rd_ptr有两种可能FIFO 空了FIFO 满了写指针绕了一圈追上读指针。所以真实设计里指针通常会多加一位“圈数位”。比如 FIFO 深度是 8需要 3 bit 地址addr ptr[2:0]但内部指针可能用 4 bitptr[3:0]低 3 bit 表示地址高 1 bit 表示绕圈状态。empty 判断在读时钟域里如果 本地读指针 同步过来的写指针 说明没有可读数据也就是empty (rd_gray_next wr_gray_sync);注意这里的wr_gray_sync是从写时钟域同步过来的写指针。full 判断在写时钟域里如果 写指针再前进一步会追上读指针 说明 FIFO 满经典 Gray 指针判断里满通常不是简单等于而是高位取反后比较。类似full (wr_gray_next {~rd_gray_sync[ADDR_W:ADDR_W-1], rd_gray_sync[ADDR_W-2:0]});这表示写指针已经比读指针多绕了一圈并且地址位置追上了读指针。五、为什么 FIFO 可以保证数据可靠关键在于这句话写域只在自己的时钟下写 RAM读域只在自己的时钟下读 RAM。数据写进去以后它存在 RAM 里并不是一个正在变化的跨域组合信号。读域什么时候读它只根据同步过来的写指针判断有没有数据可读如果有才读。写域什么时候写它只根据同步过来的读指针判断还有没有空间可写如果有才写。所以异步 FIFO 的跨域风险被压缩到了两个地方写指针同步到读域读指针同步到写域。而这两个指针又用Gray 码 两级同步器处理所以可靠性大幅提高。六、异步 FIFO 的读写过程假设wr_clk 比 rd_clk 快 FIFO 初始为空第 1 步写域写入 data0wr_clk W0: wr_en 1 din data0 写入 mem[wr_addr] wr_ptr_bin 1 wr_ptr_gray 更新这时候数据已经进入 RAM。但读域还不知道因为写指针要同步过去。第 2 步写指针跨到读域rd_clk R0: wr_ptr_gray_sync1 wr_ptr_gray rd_clk R1: wr_ptr_gray_sync2 wr_ptr_gray_sync1两拍之后读域看到同步过来的写指针 ! 本地读指针于是empty 拉低读域知道 FIFO 里有数据了。第 3 步读域读取 data0rd_clk R2: rd_en 1 dout mem[rd_addr] rd_ptr_bin 1 rd_ptr_gray 更新读完以后读指针变化。但写域还不知道读域已经腾出空间因为读指针也要同步回写域。第 4 步读指针同步回写域wr_clk W3: rd_ptr_gray_sync1 rd_ptr_gray wr_clk W4: rd_ptr_gray_sync2 rd_ptr_gray_sync1写域看到读指针变化后才知道空间释放了所以异步 FIFO 的full和empty都会有延迟。这里的读写指针同步是多bit信号之所以可以使用两级寄存器进行跨时钟域处理是因为它一次只变化一个bit这种变化相当于电平的跨时钟域处理所以可以只使用两级寄存器进行处理。七、为什么 FIFO 的 full / empty 有延迟因为对方指针要同步两拍。比如读域读走了一个数据理论上 FIFO 空间马上多了一个。但写域并不能立刻知道。它必须等rd_ptr_gray - 两级同步 - wr_clk 域所以full可能晚一点释放。同理写域写入一个数据后读域也不会马上知道。所以empty可能晚一点拉低。这不是 bug而是 CDC 安全机制带来的必然结果。八、为什么 Vivado 里 FIFO 深度不一定等于你设定的AMD/Xilinx 官方文档里明确说过FIFO 的有效深度或实际深度不一定和 GUI 里选择的深度一致因为实际深度取决于 FIFO 的实现方式以及启用的功能Vivado IDE 里也会报告 actual depth。影响因素包括 common/independent clock、standard/FWFT read mode、对称/非对称端口比例等。(AMD文档)也就是说你在 Vivado 里填的 depth是“配置目标”或“用户视角深度”。IP 内部为了实现 full/empty、FWFT、输出寄存器、非对称位宽、同步逻辑实际可写/可读深度可能会变。九、为什么有时候会多 1、少 1、多 2常见原因有几个。1. 异步 FIFO 需要区分 full 和 empty可能会牺牲一个深度经典环形 FIFO 里如果只看wr_ptr rd_ptr那你无法区分FIFO 空还是FIFO 满所以有些 FIFO 设计会采用最多只使用 depth - 1 个位置比如你配置 16 深度标准异步 FIFO 可能实际能可靠装 15 个。官方文档里的例子也提到对于深度 16、对称读写位宽、FWFT 的情况实际深度会从 15 增加到 17。(AMD文档)比如我下面这个仿真图我fifo例化的是16实际上仿真图里面写入了17个数据。这个例子背后的意思就是标准结构可能有效深度是 15 FWFT 又额外增加读侧可见深度 最后变成 17所以看到的“不是刚好等于配置值”并不是异常。2. FWFT 模式会让深度增加FWFT First Word Fall Through。意思是当 FIFO 里有数据时第一个数据会自动出现在dout上不需要你先rd_en才出来。AMD 文档里说明FWFT 可以在不发起读请求的情况下预先看到下一个数据当 FIFO 有数据时第一个 word 会自动出现在输出总线上。(AMD文档)更关键的是文档明确说FWFT 实现会把 FIFO 深度增加2 个 read words。(AMD文档)所以如果你用了 Vivado FIFO Generator 或 XPM FIFO并且配置了Read Mode First Word Fall Through你就可能看到类似配置 depth 2048 实际行为像 2049 / 2050 / 2047 / 2050具体表现取决于你看的是什么信号fullalmost_fullprog_fullwr_data_countrd_data_countdata_validemptydout3. 输出寄存器 / pipeline 会改变可见深度很多 Xilinx FIFO 为了提高时序性能会在输出侧加寄存器或 pipeline。这会造成RAM 里有一部分数据 输出寄存器里还有一部分数据 FWFT 预取逻辑里可能还有数据于是从用户接口看FIFO 似乎“多装了几个”。不是 RAM 真的变大了而是FIFO 内部除了主存储阵列还有输出暂存/预取路径。UG573 也提到考虑输出寄存器级、FWFT 模式或非对称端口时FIFO depth 会变化。(AMD文档)

相关新闻

2026低代码科普:AI对话式开发+数字员工,彻底改写企业数字化玩法

2026低代码科普:AI对话式开发+数字员工,彻底改写企业数字化玩法

2026年,低代码行业迎来了一场“从工具到伙伴”的变革,其中“AI对话式开发”和“AI数字员工”两大话题,成为行业内外热议的焦点。很多企业对这两项技术充满好奇,却又存在诸多疑问:AI对话式开发真的能不用拖拽就搭系统吗…

2026/7/26 22:29:02 阅读更多 →
串口通信协议栈设计与工业级可靠性实现

串口通信协议栈设计与工业级可靠性实现

1. 串口通信协议栈的层级定位串口通信在OSI模型中的定位一直存在争议,但通过实际工程实践可以明确其跨层特性。UART(Universal Asynchronous Receiver/Transmitter)作为最基础的串口实现,本质上定义了数据链路层的帧结构&#xff…

2026/7/26 20:50:31 阅读更多 →
STM32 RAM架构解析与优化实践

STM32 RAM架构解析与优化实践

1. STM32 RAM的硬件架构解析STM32微控制器的RAM系统远比大多数开发者想象的复杂。与PC上的内存条不同,STM32的RAM由多个物理上独立的内存区域组成,每个区域都有特定的设计目的和访问特性。以STM32F4系列为例,其内存系统包含192KB的主SRAM&…

2026/7/26 23:59:33 阅读更多 →

最新新闻

Blazor数据可视化实战:ComponentOne趋势线应用

Blazor数据可视化实战:ComponentOne趋势线应用

1. 项目概述:当Blazor遇上数据可视化在数据驱动的时代,如何从海量信息中快速识别关键模式成为每个开发者的必修课。最近我在一个金融分析项目中使用了ComponentOne的Blazor Charts组件,其趋势线功能让我眼前一亮。不同于简单的折线图展示&…

2026/7/27 5:16:27 阅读更多 →
灰狼算法优化PID控制参数:原理与Matlab实现

灰狼算法优化PID控制参数:原理与Matlab实现

1. 项目概述灰狼算法(Grey Wolf Optimizer, GWO)是一种受自然界灰狼群体狩猎行为启发的智能优化算法,近年来在控制工程领域展现出强大的参数优化能力。PID控制作为工业控制中最经典的控制算法,其参数整定质量直接影响系统响应性能…

2026/7/27 5:16:27 阅读更多 →
Opus 5模型在ARC-AGI-3基准测试中创下SOTA成绩,突破AI抽象推理能力

Opus 5模型在ARC-AGI-3基准测试中创下SOTA成绩,突破AI抽象推理能力

这次我们来看一个在 AI 通用智能评测领域的重要进展:Opus 5 模型在 ARC-AGI-3 基准测试中创下了新的 SOTA(State-of-the-Art)成绩。这个结果不仅展示了模型能力的突破,更重要的是为研究者和开发者提供了评估 AI 系统通用推理能力的…

2026/7/27 5:16:27 阅读更多 →
C++实现Windows开机自启动:注册表操作与Wow64兼容性详解

C++实现Windows开机自启动:注册表操作与Wow64兼容性详解

1. 项目概述与核心价值在桌面应用开发中,开机自启动是一个既基础又高频的需求。无论是我们常用的即时通讯软件、云盘同步工具,还是我们自己开发的系统监控、自动化脚本程序,都希望能“悄悄地”在用户登录系统后自动运行,提供无缝的…

2026/7/27 5:16:27 阅读更多 →
Em Dash与AI:提升技术文档可读性的实用指南

Em Dash与AI:提升技术文档可读性的实用指南

1. 背景与核心概念 在日常的技术文档编写和代码注释中,标点符号的正确使用往往被开发者忽视,但它在提升代码可读性和技术文档专业性方面起着至关重要的作用。破折号(Em Dash)作为英文写作中常用的标点符号,在技术领域同…

2026/7/27 5:16:27 阅读更多 →
大模型技术在办公场景的应用与学习路径

大模型技术在办公场景的应用与学习路径

1. 大模型技术演进与办公场景融合趋势过去一年里,AI大模型技术正以惊人的速度渗透到日常办公场景中。作为从业者,我观察到从代码生成到会议纪要,从数据分析到文档撰写,大模型正在重构传统工作流。最新发布的Agnes、书生浦语等模型…

2026/7/27 5:15:27 阅读更多 →

日新闻

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:54 阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/26 0:00:31 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻