在之前的文章里面介绍了Canny算法的原理和基于Python的参考模型,之后呢在FPGA上完成了Canny算法的实现,可是遇到了时序不收敛的问题,记录一下。
可以看到时序的建立时间不满足。
我们在约束的主时钟频率是200MHz,也就是5ns,但是建立时间是-2.12ns,也就是说这个工程只能跑到7.12ns也就是140.45MHz,远远不能满足我们预先的设计。
在之前文章里面介绍过怎么在SpinalHDL里面估计一个模块可以跑到的最大频率,可以参见:SpinalHDL--快速评估代码性能
怎么根据时序约束和建立保持时间裕量来分析工程能跑到的最大频率可以参考下面:
首先来看一下PR之后是哪条路径不收敛,究竟是同一时钟域下的还是跨时钟域的路径,两者的处理方式不一样。
可以看到是Intra-clock paths爆红了,也就是同一时钟域下的路径时序不收敛。
接下来看具体的时序路径:
可以看到logic delay远远比net delay大,那么我们就需要去降低logic delay,也就是要把我们的组合逻辑搞简单一点。如果是net delay比较大就要考虑是不是布线拥塞的问题了,两者的处理方式不太一样。
再来看一下它的电路图,可以看到在左边的寄存器输出之后经过LUT,Carry等组合逻辑之后,给到DSP的输入端。一般来说DSP的几级pipline最好的都用上,这样DSP可以跑到更高的频率。
再来看一下具体的路径报告:
可以看到logic的延时占到了82%,因此如果要解决这个时序为例,就必须要把logic delay给降低。
两者的比例可以参考,七系列的FPGA和UltraScale系列的FPGA不太一样:
来看一下这一个时序为例对应的代码:
可以看到其实挺复杂的,有减法,有乘法。其中减法是被vivado用LUT+Carry搭了起来,乘法用的DSP。
要解决这个问题,就是把这一大段代码进行流水拆开嘛,把减法拆一级流水,乘法器拆为三级流水。
将代码修改为以下的样子,再来综合一下
可以看到时序就收敛了。
再来看一下生成电路结构:
可以看到FDCE之后仍然是LUT+Carry的形式,用于做减法运算,然后再接入DSP的输入,在源码里面做完减法之后还有这两级寄存器,但是在电路图里面看不到他们了,这是因为这两级寄存器被DSP给吸收掉了,用于提高DSP的时钟频率,这两级寄存器会利用DSP单元内部的寄存器来实现,并不会增加我们的资源占用,DSP核里面的资源不用也是浪费。
上图为DSP单元里面的寄存器排布,可以看到有六级。
本篇介绍了一次时序调优的过程,就是重新计算流水线,看看哪里是时序瓶颈。这种重新计算流水线的方式代价还是比较大的,需要重新修改代码,所以在设计初期就应该考虑到这个问题,比如DSP的流水线寄存器,BRAM的输出寄存器这些在设计初期就考虑使用到它们,来获取更好的时序。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !