FPGA为什么跑不快

来源:本站
导读:目前正在解读《FPGA为什么跑不快》的相关信息,《FPGA为什么跑不快》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《FPGA为什么跑不快》的详细说明。
简介:以Quartus为例(延时数据为Stratix III器件典型延时)手动布局:module top(input clk,din,output dout);

以Quartus为例(延时数据为Stratix III器件典型延时)手动布局:

module top(input clk,din,output dout);

[cpp]view plaincopyprint?

regdin_ff,din_ff2;

always@(posedgeclk)

begin

din_ff<=din;

din_ff2<=din_ff;

end

assigndout=din_ff2; endmodule

reg din_ff,din_ff2;

always@(posedge clk)

begin

din_ff <= din;

din_ff2 <= din_ff;

end

assign dout = din_ff2;

endmodule

忽略IO时序,怎样使这个电路跑到最快?在FPGA中线延时占主导,因此我们首先需要把din_ff和din_ff2两个寄存器邻近摆放。在Assignment Editor中,新增Location规则,目标选择din_ff或din_ff2,位置选择“LAB”,再选择你希望的LAB坐标(在此例中具体坐标在哪不重要)。将这两个寄存器摆到同一个LAB内,就实现了数据路径上的最优化。 这就是所谓的“手动布局”。

一个寄存器的Tsu/Th大概是50ps,Tco大概85ps,同一个LAB的互联延时大概200ps,忽略Minimum Pulse Width约束,是否意味着这个电路的最小周期是335ps即能跑3GHz呢?注意,此时数据路径上已经没有瓶颈了。

****************........我是分割线.......*****************

::基于OCV的fmax计算::

查看Timequest报告,你会发现报出的fmax远小于期望的3GHz,为什么呢?

在Quartus自动PR时,时钟通常会被拉到全局缓冲CLKCTRL(这有时是不可避免的,如PLL输出),再拉到每个DFF。虽然全局时钟到每个DFF的平均Skew较小,但绝对延时是比较大的(ns级)。而Timequest的分析是基于OCV的(简单来说,就是所有延时都有min和max),延时的绝对值越大,min和max的差值也越大。比如,假定CLKCTRL出来的延时如下:

[cpp]view plaincopyprint?

CLKCTRL->din_ff|clk平均延时2ns(min1.5ns,max2.5ns) CLKCTRL->din_ff2|clk平均延时2ns(min1.5ns,max2.5ns)

CLKCTRL -> din_ff|clk 平均延时2ns(min 1.5ns,max 2.5ns)

CLKCTRL -> din_ff2|clk 平均延时2ns(min 1.5ns,max 2.5ns)

工具先修Hold Time,din_ff到din_ff2的最快路径为(我们假定Tco(min)+线延时(min)-Th =250ps):

[cpp]view plaincopyprint?

Data(early):CLKCTRL----1.5ns---->din_ff|clk----250ps---->din_ff2|d

Data(early):CLKCTRL ----1.5ns----> din_ff|clk ----250ps----> din_ff2|d

din_ff2的最慢时钟路径为:

[cpp]view plaincopyprint?

Clock(late):CLKCTRL----2.5ns---->din_ff2|clk

Clock(late):CLKCTRL ----2.5ns----> din_ff2|clk

(1.5ns+250ps<2.5ns)此时工具发现需要在din_ff后面插750ps(min)的Buffer才能使Hold Time无违规(FPGA中不插Delay Cell,一般是绕线)。插完Buffer后,我们来看看此时能达到的最小周期(计算Setup Time):

din_ff到din_ff2的最慢路径为(我们假定Tco(max)+线延时 (max)+Tsu = 350ps,插的Buffer(max)=950ps):

[cpp]view plaincopyprint?

Data(late):CLKCTRL----2.5ns---->din_ff|clk----350ps+950ps=1.3ns---->din_ff2|d

Data(late): CLKCTRL ----2.5ns----> din_ff|clk ----350ps+950ps=1.3ns----> din_ff2|d

din_ff2的最快时钟路径为:

[cpp]view plaincopyprint?

Clock(early):CLKCTRL----1.5ns---->din_ff2|clk

Clock(early): CLKCTRL ----1.5ns----> din_ff2|clk

数据路径相对于时钟的延时为(2.5ns+1.3ns-1.5ns=2.3ns),所以最小时钟周期2.3ns,对应fmax为435MHz,与一开始预测的3GHz差别巨大。

细心的朋友会发现,这个最小周期值非常接近于CLKCTRL延时(max-min)的两倍。

****************........我是分割线.......*****************

::手动时钟树 -- 创建共同时钟路径::

OCV的计算引擎会对共同时钟路径不计算min/max,因为物理上同一段路径的延时是固定的,这个在Quartus中称为CCPP,在Cadence中称为CPPR,在Synopsys中称为CRPR。。。

既然CLKCTRL延时巨大,那我们可以在CLKCTRL到两个寄存器这段路径上创建共同时钟路径,减小CLKCTRL延时(max-min)对时序的冲击。我们对原代码作以下修改:

[cpp]view plaincopyprint?

moduletop(inputclk,din,outputdout);

wireclk_buf/*synthesiskeep*/;

assignclk_buf=clk;

regdin_ff,din_ff2;

always@(posedgeclk_buf)

begin

din_ff<=din;

din_ff2<=din_ff;

end

assigndout=din_ff2;

endmodule

module top(input clk,din,output dout);

wire clk_buf/*synthesis keep*/;

assign clk_buf = clk;

reg din_ff,din_ff2;

always@(posedge clk_buf)

begin

din_ff <= din;

din_ff2 <= din_ff;

end

assign dout = din_ff2;

endmodule

通过Location规则把clk_buf节点放在与两个寄存器同一个LAB内,取得最大的共同时钟路径和最小的分离时钟路径。此时再计算一下Hold Time(假定clk_buf到寄存器时钟端的延时min=300ps,max=400ps):

[cpp]view plaincopyprint?

Data(early):clk_buf----300ps---->din_ff|clk----250ps---->din_ff2|d Clock(late):clk_buf----400ps---->din_ff2|clk

Data(early):clk_buf ----300ps----> din_ff|clk ----250ps----> din_ff2|d

Clock(late):clk_buf ----400ps----> din_ff2|clk

(300ps+250ps>400ps)可见Hold Time无违规,不需要插Buffer。此时计算Setup余量:

[cpp]view plaincopyprint?

Data(late):clk_buf----400ps---->din_ff|clk----350ps---->din_ff2|d Clock(early):clk_buf----300ps---->din_ff2|clk

Data(late):clk_buf ----400ps----> din_ff|clk ----350ps----> din_ff2|d

Clock(early):clk_buf ----300ps----> din_ff2|clk

数据路径相对延时为(400ps+350ps-300ps=450ps),如不考虑Minimum Pulse Width约束,则最小周期450ps,fmax为2.2GHz。这就是手动时钟树 -- 创建共同时钟路径的威力。

****************........我是分割线.......*****************

::手动时钟树 -- 手动Skew调整::

Quartus的Fitter中有很多优化Clock Skew的选项,其实选了根本没有任何效果。。。Quartus自动PR对时钟的优化就是这么弱。

我们还能进一步对时序进行优化,那就是Clock Skew手工调整,平衡(Tco+线延时+Tsu/-Th)那段250ps~350ps的数据延时。代码继续修改如下:

[cpp]view plaincopyprint?

moduletop(inputclk,din,outputdout);

wireclk_buf/*synthesiskeep*/;

wireclk_buf2/*synthesiskeep*/;

assignclk_buf=clk;

assignclk_buf2=clk_buf;

regdin_ff,din_ff2;

always@(posedgeclk_buf)

din_ff<=din;

always@(posedgeclk_buf2)

din_ff2<=din_ff;

assigndout=din_ff2;

endmodule

module top(input clk,din,output dout);

wire clk_buf/*synthesis keep*/;

wire clk_buf2/*synthesis keep*/;

assign clk_buf = clk;

assign clk_buf2 = clk_buf;

reg din_ff,din_ff2;

always@(posedge clk_buf)

din_ff <= din;

always@(posedge clk_buf2)

din_ff2 <= din_ff;

assign dout = din_ff2;

endmodule

假定clk_buf到clk_buf2的延时为250ps~300ps(如需更大Skew,在SDC中用set_net_delay -min/max对clk_buf到clk_buf2的延时进行约束即可):

[cpp]view plaincopyprint?

Data(early):clk_buf----300ps---->din_ff|clk----250ps---->din_ff2|d Clock(late):clk_buf----300ps---->clk_buf2----400ps---->din_ff2|clk

Data(early):clk_buf ----300ps----> din_ff|clk ----250ps----> din_ff2|d

Clock(late):clk_buf ----300ps----> clk_buf2 ----400ps----> din_ff2|clk

(300ps+250ps<300ps+400ps)可见Hold Time违规,工具需要插150ps(min)的Buffer。假设Buffer的延时为150ps~200ps,此时计算Setup余量

[cpp]view plaincopyprint?

Data(late):clk_buf----400ps---->din_ff|clk----350ps+200ps---->din_ff2|d Clock(early):clk_buf----250ps---->clk_buf2----300ps---->din_ff2|clk

Data(late):clk_buf ----400ps----> din_ff|clk ----350ps+200ps----> din_ff2|d

Clock(early):clk_buf ----250ps----> clk_buf2 ----300ps----> din_ff2|clk

(400ps+350ps+200ps-250ps-300ps=400ps), 如不考虑Minimum Pulse Width约束, 则最小周期缩短到400ps,fmax可达2.5GHz。

这就是手动时钟树 -- 手动Skew调整,这个手段在优化对外控制器模块时非常有用,用于平衡内部时钟输出到Pad的巨大延时。

****************........我是分割线.......*****************

在顶楼的DDR2-1066控制器实现过程中,大量应用了“手动布局、手动时钟树 -- 创建共同时钟路径、手动时钟树 -- 手动Skew调整”三项PR技术,使得用内部ALUT搭的控制器/PHY电路,最高频率得以赶超片内硬核。

提醒:《FPGA为什么跑不快》最后刷新时间 2024-03-14 01:08:20,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《FPGA为什么跑不快》该内容的真实性请自行鉴别。