前言
为什么需要介绍逻辑级数呢,因为只有知道了逻辑级数的存在你才知道怎么去优化自己的代码。
一、逻辑级数
什么是逻辑级数?所谓逻辑级数就是指路径起点和重点之间的组合逻辑单元个数,这些逻辑单元可能是查找表(LUT1、LUT2、LUT4、LUT5、LUT6)、进位链(Carry4,进位链:进位溢出,为了连接一个过大位宽累加器而存在的逻辑工具)、数据选择器(F7MUX/F8MUX/F9MUX)、IBUF等。
在Vivado时序报告中逻辑级数为中间的组合逻辑器件个数加一个触发器,可以看见下图所示,中间组合逻辑器件为8个,再加一个触发器,逻辑级数为9。
在时序报告中也确实如此。如图所示:
若不确定也可以看数据路径(Data Path),看紫色的字,便是数据经过的逻辑级数。
二、逻辑级数查找
在TCL控制台输入如下命令即可查看逻辑级数:
report_design_analysis -logic_level_distribution -logic_level_dist_paths 5000 -name design_analysis_prePlace
但是输入命令前需要打开synthesized design或者implemented design
弹出如下操作框,然后左键级数最大的数字,选择Report Design Analysis on Timing Paths
然后2条最长级数路径就像下图所示显示出来,左下方还可以再切换会最长级数报告
如果想看这条路径综合出来就选中路径,然后右键选择Schematic;
但是建议直接看时序报告,里面什么都有,依旧是选择路径然后鼠标右键选择Veiw Path Report
三、为什么要在乎逻辑级数
1、逻辑级数越大,数据从上一个触发器到下一个触发器的延时会变长,经过LUT、CARRY4,以及中间的连线都需要时间;
2、逻辑级数增加生成电路消耗的资源也增加。
那么问题来了,多大的逻辑级数才算逻辑过大呢?通常,一个“LUT+一根走线”的延迟为0.5ns(经验值,适用于Xilinx7系列FPGA和UltraScale/UltraScale+FPGA),假定寄存器时钟周期为T,那么该路径所能承载的最大逻辑级数为T/0.5,也就是2T。如果逻辑级数大于2T,而时序未能收敛,就可以怀疑时序违例跟逻辑级数较高有关。
这里我就举个逻辑级数过大带来的时序违规的例子,之前做DDR的AXI4协议测试的时候图方便将512bit的写数据自动加1,这就导致逻辑级数过大导致时序不收敛。
过大的计数器位宽会带来过多的进位链,从而造成过多的逻辑级数;尽量避免大位宽计数器,250M以内的设计,最好不要超过16bits;4bits位宽会占用一个进位链;下图便是512bit计数器综合出来的布线情况。
对于代码中常见代码产生的逻辑级数可以去公众号上去搜索:FPGA十年老鸟,他对逻辑级数做了一个非常清楚的介绍,是我这几年看过总结得最好的一篇文章。
四、代码优化
如果你有了逻辑级数这个慨念你就能知道怎么去优化自己的代码,怎么去评判代码质量。
4.1 加法器拆分
我们可以看到Vivado中还提供了加法器的IP核,加法器这么简单都要有IP核呢,其实这个加法器IP核就是为了解决大位宽时逻辑级数过大这个问题的,通过设置流水线级数可以拆分逻辑。同时根据IP的实现思路,我们也可以手动对代码进行逻辑拆分。拆分加法器最简单的思路就是二分法流水线,即如果对于32bit加法器,首先想到拆分为两个16bit加法器,中间插入寄存器。
如果将两个32bit数据直接相加逻辑级数会很大,如图所示:
但是如果将32bit加法器拆分成连个16bit加法器,中间插入一个寄存器,虽然消耗的资源增加,但是逻辑级数缺减少了,如图所示:
总结:通过拆分,32bit加法器多了一个时钟的延迟,多了33个触发器(FF),但逻辑级数从10降到了7,如果允许更多时钟的延迟并且使用更多的FF,则逻辑级数还能够更低。这就是所谓的以面积换取速度,这里的速度指整个工程稳定运行所能够达到的最高时钟频率,它不仅和FPGA内部各个寄存器的建立时间余量、保持时间余量有关,也和FPGA与外部芯片接口信号的时序余量有关。
4.2比较器拆分
比较器的拆分比较简单,只要将大位宽的比较器拆分成几个小位宽的比较器即可。比如当位宽为64bit的相等比较器,逻辑层级为9级,可以拆成4个16bit的相等比较器,则逻辑级数降到3。
下图为64bit比较器直接比较产生的逻辑级数和消耗的资源:
现在将64bit比较器拆成4个16bit的比较器,逻辑级数直接下降到4。
后续很多例子就不再展开了,写这篇博客的目的就是想让各位在学FPGA的同道之人有一个逻辑级数的概念,关于逻辑级数的总结FPGA十年老鸟已经总结的很好了,我再怎么写也不过跳梁小丑罢了。