如何加速VHDL中的数学运算?

时间:2013-02-08 03:27:19

标签: vhdl fpga

我目前在75MHz像素时钟的上升沿进行一些计算,以在屏幕上输出720p视频。一些数学(如几个模数)需要太长时间(20 + ns而75MHz是13.3ns)因此我的时序约束不能满足。我是FPGA的新手,但我想知道是否有一种方法可以以比当前像素时钟更快的速度运行计算,以便在75MHz时钟的下一个时钟周期内完成它们。我顺便使用VHDL。

3 个答案:

答案 0 :(得分:13)

根据今天的FPGA标准,75 MHz已经非常慢了。

问题是模运算,它实际上涉及分裂;分裂很慢。

仔细考虑您需要的操作,以及是否有任何方法可以重新组织计算。如果你正在计时像素,那就不像你有32位整数来处理;限制值更容易处理。

马丁暗示了一个选择:力量减少。如果您有1280像素/线并且需要每隔三分之一操作一次,则无需计算1280 mod 3!计数0,1,2,0,......而不是。

另一方面,如果您需要8位(或12位)数字的模3,则将所有可能的值存储在查找表中,这将足够快。

或者有时你可以乘以1/3(X“5555”)而不是除以3,然后乘以3(这是一个加法)并减去得到模数。这个管道确实很好,但由于X“5555”只是1/3的近似值,因此需要在仿真中验证它为每个输入提供正确的输出。 (对于16位输入,这不是一个很大的模拟!)模9的扩展很容易。

编辑:

您的评论中有两点:您的另一个选择是使用Spartan的时钟发生器创建一个X2时钟(150MHz),每个像素可以产生2个周期。良好的流水线代码应该满足150 MHz而不会有太多麻烦。

How not to pipeline!

PROCESS(Clk)
BEGIN
    if(rising_edge(Clk)) then
        for i in 0 to 2 loop
            case i is
                when 0 => temp1 <= a*data;
                when 1 => temp2 <= temp1*b;
                when 2 => result <= temp2*c;
                when others => null;
            end case;
        end loop;
    end if;
END PROCESS;

要实现的第一件事是循环和case语句相互抵消,所以这简化为

PROCESS(Clk)
BEGIN
    if rising_edge(Clk) then
        temp1 <= a*data;
        temp2 <= temp1*b;
        result <= temp2*c;
    end if;
END PROCESS;

这是越野车!测试平台也有问题,隐藏了这个问题。

在周期1中,显示数据a,b,c,并计算temp1 = Data * a 在周期2中,temp1乘以新值b而不是正确的值!
在第3周期再次相同!

由于测试平台设置输入并使它们保持不变,因此不会发现问题!

PROCESS(Clk)
BEGIN
    if rising_edge(Clk) then
        -- cycle 1
        temp1   <= a*data;
        b_copy  <= b;
        c_copy1 <= c;
        -- cycle 2
        temp2   <= temp1*b_copy;
        c_copy2 <= c_copy1;
        -- cycle 3
        result  <= temp2*c_copy2;
    end if;
END PROCESS;

我喜欢评论每个周期;我在一个循环中使用的每个术语都必须来自前一个循环,通过计算或从副本开始。

至少这可行,但它可以减少到2个周期深度和更少的复制寄存器,因为在这个例子中,四个输入是独立的(我假设没有必要的措施来避免溢出)。所以:

PROCESS(Clk)
BEGIN
    if rising_edge(Clk) then
        -- cycle 1
        temp1   <= a * data;
        temp2   <= b * c;
        -- cycle 2
        result  <= temp1 * temp2;
    end if;
END PROCESS;

答案 1 :(得分:10)

以下是一些技巧:

  • 流水线技术 - 将逻辑分解为多个时钟周期运行
  • 多循环路径 - 如果您不需要每个循环的答案,您可以告诉工具它可以花更长的时间。但是要注意不要告诉工具错误!
  • 再想一想 - 例如,你真的需要在非常宽的x mod 3上进行x,还是可以使用不断更新的modulo 3计数器?
  • 使用更好的工具 - 我有一些实例可以使用昂贵的合成器在深逻辑路径上实现时序,而不是使用供应商的合成器在相同的代码上满足时序。

更极端的解决方案涉及更换芯片,更快的设备,更新的设备,或更新,更快的设备。

答案 2 :(得分:2)

通常FPGA中的复杂数学运算是流水线的。流水线意味着您将操作划分为多个阶段。假设你有一个倍频,你的时钟速度需要太长时间。您将乘数除以3个阶段。基本上你的乘法器由三个不同的部分(它们有自己的时钟输入)组成一个链接。这三个部分将小于一个部分,因此它们具有较小的延迟,因此您可以使用更快的时钟。

这样做的一个缺点就是'延迟'。您的流水线系统将为输出提供延迟。在上面的乘数示例中,要获得正确的输出,您必须等到输入通过所有3个阶段。但这通常很小(取决于你的设计当然),可以忽略不计。

以下是一篇很好的(!)帖子:http://vhdlguru.blogspot.com/2011/01/what-is-pipelining-explanation-with.html 编辑:请参阅Brian的帖子。

供应商通常还会在其设计软件中将数学运算的优化和流水线版本作为IP内核。寻找他们。