我目前在 75MHz 像素时钟的上升沿进行一些计算,以在屏幕上输出 720p 视频。一些数学运算(比如一些模数)花费的时间太长(20+ns,而 75MHz 是 13.3ns),所以我的时序约束没有得到满足。我是 FPGA 新手,但我想知道是否有办法以比当前像素时钟更快的速度运行计算,以便在 75MHz 时钟的下一个滴答声之前完成它们。顺便说一句,我正在使用 VHDL。
3 回答
按照今天的 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;
这里有一些技巧:
- 流水线 - 将逻辑拆分为在多个时钟周期内运行
- 多周期路径 - 如果您不需要每个周期的答案,您可以告诉工具它可以花费更长的时间。需要注意不要告诉工具错误的事情!
- 再想一想——例如,你真的需要
x mod 3
在 very wide上做x
,或者你可以使用不断更新的模 3 计数器吗? - 使用更好的工具 - 我有过使用昂贵的合成器可以满足深度逻辑路径上的时序的实例,而使用供应商的合成器则不能满足相同代码的时序。
更极端的解决方案包括更换硅片,以获得更快的设备、更新的设备或更新、更快的设备。
通常 FPGA 中的复杂数学运算是流水线的。流水线意味着您将操作划分为多个阶段。假设你有一个乘法器,它对你的时钟速度来说太长了。您将乘数分为 3 个阶段。基本上,您的乘法器由三个不同的部分(它们有自己的时钟输入)组成,一个接一个。这三个部分将小于一个部分,因此它们的延迟更小,因此您可以为它们使用更快的时钟。
这样做的一个缺点是“延迟”。您的流水线系统将提供具有延迟的输出。在上面的乘法器示例中,要获得正确的输出,您必须等到输入通过所有 3 个阶段。但这通常非常小(当然取决于您的设计)并且可以忽略。
这是一个很好的(!)帖子:http: //vhdlguru.blogspot.com/2011/01/what-is-pipelining-explanation-with.html编辑:请参阅 Brian 的帖子。
此外,供应商通常在其设计软件中将数学运算的优化和流水线版本作为 IP 内核提供。寻找他们。