0

我使用 VHDL 构造设计了一个异步非对称 fifo。它是具有深度和 prog_full 作为参数的通用 fifo。它具有 16 位输出数据宽度中的 32 位。您可以在此处找到 fifo 设计链接。
顶级非对称fifo (fifo_wrapper.vhd) 建立在 32 位异步 fifo (async_fifo.vhd) 之上。这个内部先进先出 (async_fifo) 是使用开放内核上通用 FIFO 的逻辑构建的 ( http://opencores.org/project,generic_fifos )。我添加了一个简单的测试台来尝试这个 fifo 设计。
但是这种设计存在一些我无法弄清楚的问题。当我模拟它时,fifo 设计工作得非常好,但是当我合成它并在硬件上与我的其他设计一起运行它时,有时我会得到一些错误的数据。可能有一些我无法模拟的极端情况还是其他原因?

这就是为什么我希望任何需要此设计的人尝试一下,如果他/她在仿真期间或综合后遇到任何问题,请告诉我。谢谢

PS:如果有其他论坛可以让我将我的设计供公众使用,请告诉我。谢谢

4

2 回答 2

1

基于写入和读取时钟完全异步的假设,有许多与这种异步 FIFO 设计相关的问题需要指出。

  • 一个(并且可能是)主要问题是写入端指针(async_fifo 中的 wp),它是一个普通的二进制计数器,在没有任何格雷编码的情况下被传输并同步到读取端时钟。因此,向量中的不同位可能在读取时钟域中的不同时间到达,因此写入指针值可能(并且很可能会不时地)与写入端值不同。因此,与读指针 (rp) 的比较毫无意义。在时钟域上传输的二进制值应在传输前进行格雷编码,并在到达时进行解码。还可以使用两个触发器级别的同步。

  • 假设这两个时钟(rd_clk 和 wr_clk)是异步的,但只有一个复位(rst),因此复位置低时可能会违反时序,除非在复位置低时对时钟有一些额外的要求。

  • 与 clear 类似,其中只有一个信号用于两个不同的时钟域。

  • 建议使用端口命名约定,其中端口的时钟域关系在名称中被清除,例如命名写入时钟域 wr_* 中的所有端口(例如 wr_clk_i、wr_clk_we_i 等,以及读取时钟域为 rd_*。

  • 复位被断言为低电平,因此命名为 rst_n 会很好。

于 2013-07-15T13:15:24.410 回答
0

n'我无法访问您的代码(防火墙),因此我将仅提及设计它们的一般要点,这可能对您和其他人有所帮助。

  • 为了完全保证时钟安全,写入端应使用完全安全的异步握手方法交换其指向读取端的指针,该方法使用 2 个亚稳定信号链。

这个结构是一个双缓冲寄存器。

  1. 写入端将其写入指针注册到缓冲区中,并将有效信号置为高电平。
  2. 一个亚稳定链将缓冲器有效信号重新计时到读时钟域
  3. 在读时钟端,一旦在元链的输出看到转换为高电平有效,写端缓冲区中的数据就会重新注册到读域上的另一个寄存器中。这没关系,因为已知缓冲区中的数据是稳定的。(因为元链)。
  4. 读域将 ack 信号置为高电平。
  5. 另一个亚稳定链将 ack 信号重新计时到写时钟域。
  6. 写入端在元链的输出端等待 ack 信号的转换,一旦看到它就会取消断言其有效信号。
  7. 读取端等待元链输出处的有效信号转换为低电平,一旦看到它就会解除其确认信号。
  8. 写入端等待元链输出端的 ack 信号转换为低电平。循环现在完成。
  9. 当前的写指针,现在可能已经移动了很多,现在可以再次传输。

采用类似的方法将读指针传输到写域。可以看出,虽然这种方法导致写/读侧的写指针和读/写侧的读指针之间存在延迟,但这种延迟永远不会导致溢出。相反,它会导致写入端过早地满,读取端过早地清空,这最终将在下次交换指针时解决。

这种方法是唯一不依赖于时钟速度的先验知识的fifo完全时钟安全的设计。根本不需要格雷码。

另一件需要注意的是,寻址/空/满等的逻辑需要在每个时钟域上复制。

于 2013-07-19T07:54:16.470 回答