4

我目前在 75MHz 像素时钟的上升沿进行一些计算,以在屏幕上输出 720p 视频。一些数学运算(比如一些模数)花费的时间太长(20+ns,而 75MHz 是 13.3ns),所以我的时序约束没有得到满足。我是 FPGA 新手,但我想知道是否有办法以比当前像素时钟更快的速度运行计算,以便在 75MHz 时钟的下一个滴答声之前完成它们。顺便说一句,我正在使用 VHDL。

4

3 回答 3

14

按照今天的 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。

怎么流水线!

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 中,显示 Data,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;
于 2013-02-08T16:52:29.113 回答
12

这里有一些技巧:

  • 流水线 - 将逻辑拆分为在多个时钟周期内运行
  • 多周期路径 - 如果您不需要每个周期的答案,您可以告诉工具它可以花费更长的时间。需要注意不要告诉工具错误的事情!
  • 再想一想——例如,你真的需要x mod 3在 very wide上做x,或者你可以使用不断更新的模 3 计数器吗?
  • 使用更好的工具 - 我有过使用昂贵的合成器可以满足深度逻辑路径上的时序的实例,而使用供应商的合成器则不能满足相同代码的时序。

更极端的解决方案包括更换硅片,以获得更快的设备、更新的设备或更新、更快的设备。

于 2013-02-08T13:43:13.240 回答
2

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

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

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

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

于 2013-02-08T05:28:24.263 回答