You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于格雷码的异步FIFO:如何获取缓冲区元素数量?

当然可以实现!我之前在做异步FIFO的流量监控模块时就处理过类似需求,核心思路是把跨时钟域的指针同步到同一时钟域后,转换为二进制再计算差值——不过得先理清几个关键细节:

核心实现思路

异步FIFO的读写指针分属两个时钟域,要计算元素数量,必须先把对方域的指针同步到当前域(就是你已经在用的两级触发器同步格雷码的方式),然后在同一个时钟域内完成计算。

1. 分时钟域维护计数

你可以根据需求在两个时钟域分别计算元素数:

  • 写时钟域计数:基于本地写指针(格雷码转二进制)和同步到写时钟域的读指针(格雷码转二进制)计算
  • 读时钟域计数:基于本地读指针(格雷码转二进制)和同步到读时钟域的写指针(格雷码转二进制)计算

2. 格雷码转二进制的硬件实现

格雷码无法直接做加减运算,第一步要把同步后的格雷码指针转成二进制。硬件上用组合逻辑就能实现,比如对n位格雷码gray[n-1:0],转二进制bin[n-1:0]的规则是:

// 以Verilog为例的组合逻辑实现
assign bin[n-1] = gray[n-1];
generate
    for (genvar i = n-2; i >= 0; i--) begin: gray_to_bin_loop
        assign bin[i] = bin[i+1] ^ gray[i];
    end
endgenerate

这个逻辑在FPGA/ASIC里很容易实现,只要同步后的格雷码稳定,就不会有时序问题。

3. 元素数量的计算公式

假设FIFO深度为FIFO_DEPTH(优先选2的幂次,这样模运算可以用位截取优化,硬件效率更高):

  • 写时钟域:write_domain_count = (write_ptr_bin - read_ptr_sync_bin) % FIFO_DEPTH
  • 读时钟域:read_domain_count = (write_ptr_sync_bin - read_ptr_bin) % FIFO_DEPTH

模运算的作用是处理环形缓冲区的绕回情况:比如深度为8时,写指针是1,同步后的读指针是7,1-7=-6,模8后得到2,正好对应FIFO里的实际元素数(从7到0到1,共2个)。

4. 关键注意事项

  • 计数的延迟特性:两级触发器同步会带来2个时钟周期的延迟,所以计算出的计数是近似值,会比实际元素数滞后1-2个时钟周期。这是跨时钟域同步的固有特性,无法避免,但对于大多数水位监控、流量控制场景完全够用。
  • 与满/空信号的一致性:当write_domain_count == FIFO_DEPTH时,就是FIFO满状态;当read_domain_count == 0时,就是FIFO空状态,这和你原来的格雷码判断逻辑完全一致,可以用来验证计数的正确性。
  • 非2幂次深度的处理:如果FIFO深度不是2的幂次,模运算的硬件实现会更复杂,且原来的格雷码最高两位判断满的逻辑也需要调整,所以尽量优先选择2的幂次深度。

内容的提问来源于stack exchange,提问作者Roarer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:14:39