我目前在75MHz像素时钟的上升沿进行一些计算,以在屏幕上输出720p视频.一些数学(如几个模数)需要太长时间(20 + ns而75MHz是13.3ns)因此我的时序约束不能满足.我是FPGA的新手,但我想知道是否有一种方法可以以比当前像素时钟更快的速度运行计算,以便在75MHz时钟的下一个时钟周期内完成它们.我顺便使用VHDL.
Bri*_*ond 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,没有太多麻烦.
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;
Run Code Online (Sandbox Code Playgroud)
要实现的第一件事是循环和case语句相互抵消,所以这简化为
PROCESS(Clk)
BEGIN
if rising_edge(Clk) then
temp1 <= a*data;
temp2 <= temp1*b;
result <= temp2*c;
end if;
END PROCESS;
Run Code Online (Sandbox Code Playgroud)
这是越野车!测试平台也有问题,隐藏了问题.
在周期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;
Run Code Online (Sandbox Code Playgroud)
我喜欢评论每个周期; 我在一个循环中使用的每个术语必须来自前一个循环,通过计算或从副本.
至少这可行,但它可以减少到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;
Run Code Online (Sandbox Code Playgroud)
Mar*_*son 10
这是一些技巧:
x mod 3在非常宽的范围内做x,还是可以使用不断更新的modulo 3计数器?更极端的解决方案涉及更换芯片,更快的设备,更新的设备,或更新,更快的设备.