CONSTANT声明是将值存储在块RAM还是FPGA的触发器中?

时间:2016-02-29 02:10:01

标签: filter vhdl constants

例如,如果我想使用常数将滤波器系数存储在n-Tap FIR滤波器中,CONSTANT声明是否会使用FPGA触发器将我的值存储在Block RAM或寄存器中?也可以使用SIGNAL来存储系数而不使用RAM单元吗?

4 个答案:

答案 0 :(得分:6)

常数本身并未存储"任何地方 - 它们的值只是替换为您使用它们的VHL代码。

它们存储的位置取决于您如何使用它们以及如何优化代码。

如果您将信号乘以常数2,例如,根本不使用任何元素 - 数据总线将以一种有效地将值左移一位的方式连接。

或者,它们可能最终成为其他元素的硬连线输入,例如乘法器。

无论哪种方式,您都应该查看综合结果以彻底了解生成的RTL。

答案 1 :(得分:4)

  

[...] CONSTANT声明会使用FPGA触发器将我的值存储在Block RAMs或寄存器中吗?

常量是存储在内存块还是寄存器中,或者它们是否合并到boolen方程中取决于算法的实现。让我们看看下面的数学方程式(不是VHDL代码):

y = c_1 * x_1 + c_2 * x_2 + c_3 * x_3 +... + c_N * x_N

N是系数的数量,x_i是输入值,c_i是常数系数。

您可以通过以下方式在VHDL /硬件中实现此等式:

  1. N并行乘数和加法树来总结产品;所有这些都是在一个时钟周期内完成组合,甚至是流水线,每个时钟周期的吞吐量为一个结果。

  2. N依次执行乘法累加步骤;每个时钟周期使用一次乘法累加。

  3. 你甚至可以将两者结合起来。

    在情况1中,合成器使用常数优化每个乘法:

    • 如果系数是2的幂,则只需接线,
    • 此外,如果系数的二进制表示包含少量的1(5 * x = x + 4 * x),
    • 或倍频硬宏,其常数值(VDD,GND)连接到一个输入端。

    因此,在情况1中,不需要存储器或寄存器来存储常量。

    在情况2中,合成器将乘法累加步骤映射到硬件乘法器加上加法器。此乘法器和加法器将重复用于所有N步,因此必须在内存中查找系数。如果你有很多系数,那么使用内存块(Block-RAM)。当前迭代步骤i将构成内存地址。如果只有少量系数,那么它们也可以存储在分布式存储器(LUT-RAM)中或通过布尔方程计算。但即使在这种情况下,系数也会映射到触发器,因为它们的值不随时间变化。

      

    也可以使用SIGNAL来存储系数而不使用RAM单元吗?

    是的,当然。通过适当的同步描述,它们将被映射到触发器。

答案 2 :(得分:1)

使用过的存储元素:

  • 寄存器
  • 分布式RAM(LUTRAM)
  • 的BlockRAM

...取决于您选择的VHDL描述和大小。

你应该使用常数而不是信号。此外,使用同步读取操作来推断已注册的输出可能会有所帮助。

查看综合报告以验证预期的描述。

答案 3 :(得分:0)

以Paebbels的回答为基础,这取决于。虽然它们也可以在分布式ROM(LUTROM)中实现。这取决于综合工具。例如,Xilinx的Vivado在其综合指南(UG901)中描述了如何推断RAM / ROM。

对于FIR滤波器的示例,您可能会有类似的内容:

type coeff_array is array(natural range<>) of std_logic_vector(17 downto 0);
constant coeffs : coeff_array(0 to N-1) := ( x"XXXX", x"XXXX", ..., x"XXXX" );

现在,这是分布式ROM还是RAM取决于工具。使用Vivado进行的快速测试表明,这种结构可以合成一个大门(只是LUT逻辑)。但是,它可以通过以下方式强制进入Block RAM(也就是块ROM)。

signal coeffs : coeff_array(0 to N-1) := ( x"XXXX", x"XXXX", ..., x"XXXX" );
attribute ROM_STYLE : string;
attribute ROM_STYLE of coeffs : signal is "block";

推断任何特定类型结构(LUT,LUTRAM,LUTROM,块ROM,块RAM)的方法取决于所讨论的工具。通过综合运行测试,看看你得到了什么。并查看合成器的综合指南,了解如何获得所需的合成器。