01signal.com

在 Versal ACAP FPGA 上使用 FIFO

FIFO Generator 去哪了?

在使用 Versal FPGA 时,AMD 没有提供任何实现普通 FIFO 的 IP 块(IP block),可供在 Verilog 或 VHDL 中进行实例化(instantiation)使用。广为人知的 FIFO Generator IP 在这些 FPGA 上不可用,至少对 Vivado 2022.1 及更早版本来说是如此。

因此,如果把现有 FPGA 设计中的 FPGA 部分改为 Versal FPGA,很可能需要对项目做一些改动。几乎所有的 FPGA 项目都会用到 FIFO Generator。

Memory Generator 也是如此:这个有时用来创建 block RAM 的 IP 在 Versal FPGA 上同样被取消了。不过,这个 IP 用得较少,因为 block RAM 通常依靠推断(inference)来创建。换句话说,在 Verilog(或 VHDL)中,人们通常会声明一个数组(array),目的是创建 RAM。

请注意,带 AXI 接口的 FIFO 和 RAM 仍然可以作为 IP 使用。对 Versal FPGA 来说,支持缺失的只是那些带有“原生(native)”接口的 FIFO 和 block RAM。

有几种方法可以绕过这个问题。我下面给出两种可行的方式。

关于 FIFO 的通用教程,请参考这个系列页面

方案 1:使用 AMD 参数化宏

AMD 参数化宏(AMD Parameterized Macros)在 Vivado 中适用于该软件所支持的所有 FPGA(即 7 系列及更新的 FPGA)。这些宏可以像 Verilog 或 VHDL 中的任何模块(module)一样在实例化(instantiation)中使用。它们的文档与 FPGA 原语(primitive)文档放在一起(例如,Versal Architecture Premium Series Libraries Guide,UG1485)。

不过,原语(primitive)与参数化宏之间有一个重要区别:当综合器(synthesizer)遇到原语时,通常只会在综合后的网表(netlist)中产生一个逻辑单元。而参数化宏则会像 Verilog 模块一样,产生一大堆逻辑单元。

有几个参数化宏可以生成 FIFO,尤其是下面这两个:

这两个宏生成的 FIFO 具有“原生”(native)接口,也就是像 wr_en 和 rd_en 这样的端口。当初 FIFO Generator 提供的大多数选项,都可以通过设置宏的实例化(instantiation)参数来启用。例如,这些 FIFO 既可以是“标准 FIFO”(Standard FIFO),也可以是“首字直通”FIFO(First Word Fall Through,FWFT)。

另外还有几个用于实现不同类型 RAM 的宏。此外,也有好几种 AXI-Stream FIFO,不过它们都可以用 IP 块创建,即使在 Versal FPGA 上也是如此。

关于如何使用这些宏的完整信息,请参阅相应的 Libraries Guide,对 Versal FPGA 来说就是 UG1485。也可以从 Vivado 中获取实例化(instantiation)模板:选择 Tools > Language Templates,然后进入 Verilog > AMD Parameterized Macros (XPM) > XPM > XPM_FIFO,再根据情况选择 Synchronous FIFO 或 Asynchronous FIFO。

下面是一个创建基本同步 FIFO 的示例,其功能与该页面所示的 FIFO 相同。

module fifo_8x2048
  #(parameter width = 8, depth = 2048)
   (
    input  clk,
    input  rst,
    input  wr_en,
    input [(width-1):0] din,
    input  rd_en,
    output [(width-1):0] dout,
    output full,
    output empty
    );

   xpm_fifo_sync #(
		   .DOUT_RESET_VALUE("0"),
		   .ECC_MODE("no_ecc"),
		   .FIFO_MEMORY_TYPE("auto"),
		   .FIFO_READ_LATENCY(1),
		   .FIFO_WRITE_DEPTH(depth),
		   .FULL_RESET_VALUE(1),
		   .READ_DATA_WIDTH(width),
		   .READ_MODE("std"),
		   .SIM_ASSERT_CHK(0),
		   .USE_ADV_FEATURES("0000"),
		   .WAKEUP_TIME(0),
		   .WRITE_DATA_WIDTH(width)
		   )
   xpm_fifo_sync_inst (
      .almost_empty(),
      .almost_full(),
      .data_valid(),
      .dbiterr(),
      .dout(dout),
      .empty(empty),
      .full(full),
      .overflow(),
      .prog_empty(),
      .prog_full(),
      .rd_data_count(),
      .rd_rst_busy(),
      .sbiterr(),
      .underflow(),
      .wr_ack(),
      .wr_data_count(),
      .wr_rst_busy(),
      .din(din),
      .injectdbiterr(1'b0),
      .injectsbiterr(1'b0),
      .rd_en(rd_en),
      .rst(rst),
      .sleep(1'b0),
      .wr_clk(clk),
      .wr_en(wr_en)
   );
endmodule

方案 2:使用嵌入式 FIFO Generator

嵌入式 FIFO Generator(Embedded FIFO Generator)实际上与众所周知的 FIFO Generator 几乎相同,但它只能用在块设计(block design)中。

因此,一个明显的解决方案是创建一个块设计,并添加一个嵌入式 FIFO Generator,然后像之前的 FIFO Generator 一样设置这个 IP 块的参数。接下来,把该 FIFO 的所有端口都连接到外部端口。最后得到的块设计有着与 FIFO 相同的端口,行为也像 FIFO,所以它就是一个 FIFO。

这个方案有点丑,尤其是 FIFO 的端口名会变得比平时更长。例如,端口名不再是 wr_en,而是 FIFO_WRITE_0_wr_en。

结论

尽管 FIFO Generator 从 Vivado 的 IP 目录(IP Catalog)中消失得既突然又令人费解,但用参数化宏或块设计来替代这个 IP 通常并不困难。

从更宏观的角度看,即使是在仍支持 FIFO Generator 的 FPGA 上,也许最好也不要再使用它,而不必考虑这种做法对将来把设计移植到 Versal FPGA 的可能性有什么影响。

本页由机器从英文翻译而来。如有疑问,请参阅原文
Copyright © 2021-2026. All rights reserved. (dcc38493)