如何写出时序最优的HDL代码?如何写出时序裕量足够的代码?

描述

你想写出可以跑出700M以上的代码吗,直逼FPGA内部PLL的极限。

你想写出时序裕量足够的代码吗,让你的代码不会出现时序违例。

你想在时序违例时能轻松应对吗?让代码轻松越过时序这道门槛。

这篇文章就是一步步向你解释,如何理解代码中的时序,以及如何解决代码中的时序违例问题。

之前的文章中提到过,工程中ISP算法模块轻松跑到了762.5M的频率,整个ISP链路没有优化的情况下跑到400M的时钟频率(xilinx的us+系列)。

PLL电路

这篇文章将逐步解开HDL代码中的时序之谜,并且让你轻松应对FPGA中的时序问题。我将从实际工程的ISP算法模块出发,从设计到时序违例的查找,一步步提高代码的时序性能。

在第一个ISP模块DPC中,我使用了一个在3x3的矩阵中查找中值的模块,也就是大家常用的中值滤波器。是不是很多人都设计过,先不着急觉得是否简单,而是看如何把算法移植和时序的思想灌入到这个模块之中。

首先假设你已经得到了一个3x3的矩阵,简单看看设计思想:

在3x3 窗口中获取9 个数据,对9 这个数据值进行排序,排序步骤如下

A)窗内的每行数据找到最大值、中间值和最小值;

B)把三列的最小值相比较,取其中的最大值;

C)把三列的最大值相比较,取其中的最小值;

D)把三列的中间值相比较,再取一次中间值;

E) 再把B,C,D 中得到的三个值再排序,获取中值。

PLL电路

有了设计思想就有了灵魂,剩下的是如何构建一个有血有肉的躯体了。经过思考不难发现,9个数的中值滤波变成了3次在3个数中找最大值,最小值,中值。

第一次:执行步骤A。

第二次:执行步骤B,C,D .

第三次:执行E 。

第一次三行D1,D2,D3并行,第二次三列Dxmax,Dxmed,Dxmin并行,第三次在剩下的三个数里面找到中值,运算完毕。所以9个数据的中值查找的设计,变成了一个只需要解决三个数据里面找到max,med,min的设计。

是不是觉得这太简单了。别急,听我继续分析:

既然是在三个数据里面排序,那就需要两两比较,于是就是需要比较3次。A 与B ,B与C,A与C。现在假设A

好,此时另一个误区可能就要出现了。因为flag可能为0也可能为1,那么你得到了三个flag,一共有多少种情况呢?可能有人不假思索地回答8种,因为3bit数据,2^3= 8 ,所以就是8 种。其实不是,用概率与统计的知识,三个数据的排序应该是有C31* C21 * C11 = 6 种。真值表如下

A B A  
0 0 0 max=A,min = C
0 0 1 不存在
0 1 0 max=A,min = B
0 1 1 max=C,min = B
1 0 0 max=B,min = C
1 0 1 max=B,min = A
1 1 0 不存在
1 1 1 max=C,min = A

算法分析完毕,剩下的就是代码设计了。首先你需要进行三次比较。

PLL电路

PLL电路

针对上述代码,画出对应的数字电路示意图,(mux的三个输入端省略了datx_reg)

PLL电路

我假设FPGA内部按照上图所示的方式进行布局布线,那么最长数据路径应该是dat2_reg→comp_12 → mux3.  (或者说是dat2_reg→ comp_23 → mux1)这条路径也就被称之为最长路径或者关键路径。时序分析工具干的事情就是,分析这条最长路径(当然其他路径也分析)上的时序是否满足条件。

单独把这条路径抠出来,它就是这样子的。于是,STA静态时序分析的模型就出来了,计算reg到reg之间的延迟,两个reg之间,经历了一个比较器和一个多路选择器这两个组合逻辑。

PLL电路

 如果上述的路径因为走线(linelatency)延迟,或者是因为逻辑延迟(logiclatency)过大导致了时序违例,那么我们就应该在两个组合逻辑之间插入reg。从电路上,应该如下图所示。

PLL电路

那么从代码的角度,应该这样修改,就可以达到上图的效果:

PLL电路

好了,有了这个参考模板,再去看其他的中值滤波代码,你就知道要从哪里去优化了。

为了让大家更好的理解时序,我在网上找了两个用相同的算法思路设计的开源的代码。 看他们的设计方法

三方代码 1

PLL电路

三方代码 2

PLL电路

可以看到数据比较的时候,逻辑明显有冗余,EDA工具不一定能自动优化。

然后我将两个三方的代码,以及我自己的代码放入同一工程中进行编译,故意加大时钟频率,让它们出现时序违例,从而找出关键路径。

三方的两个模块我例化成 median_filter_3x3 ,和 medfilter3by3 ,用vivado2022.1进行编译。得到时序违例报告

PLL电路

再进一步分析关联路径1,得到了如下图所示的路径示意图

PLL电路

可以看到在两个 reg之间有4个逻辑块,然后再去代码中找到相应的位置。然后再追究到代码内部。

PLL电路

PLL电路

 可以看到,代码中多次出现重复性的数据比较,这都是数据优化的方向。具体的位置就是 33-37行, 最后vivado推测出第37行,需要经过4级组合逻辑才能将dat3 赋值给 mid_dat 。

 



审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分