减少关键路径的逻辑等级 本文节选自特权同学的图书《FPGA设计实战演练(逻辑篇)》 下面要列举的代码示例是一些能够起到系统性能提升的代码风格。在逻辑电路的设计过程中,同样的功能,可以由多种不同的逻辑电路来可以实现,那么就存在这些电路中孰优孰劣的讨论。因此,带着这样的疑问,我们也一同来探讨一下几种常见的能够提升系统性能的编码技巧。请注意,本知识点所涉及的代码更多的是希望能够授人以“渔”而非授人以“鱼”,大家重点掌握前后不同代码所实现出来的逻辑结构,在不用的应用场合下,可能会有不同的逻辑结构需求,那么大家就要学会灵活应变并写出适合需求的代码。(特权同学,版权所有) ① 减少关键路径的逻辑等级 在时序设计过程中遇到一些无法收敛(即时序达不到要求)的情况,很多时候只是某一两条关键路径(这些路径在器件内部的走线或逻辑门延时太长)太糟糕。因此,设计者往往只要通过优化这些关键路径就可以改善时序性能。而这些关键路径所经过的逻辑门过多往往是设计者在代码编写时误导综合工具所导致的,那么,举一个简单的例子,看看两段不同的代码,关键路径是如何明显得到改善的。(特权同学,版权所有) 这个一个简单的例子要实现如下的逻辑运算: y = ((~a & b& c) | ~d) & ~e; 他们的运算真值表如表5.2所示。(特权同学,版权所有) 表5.2 运算真值表 注:x表示可以任意取0或1。(特权同学,版权所有) 按照常规的思路,我们可能会写出如下的代码: // Verilog例程 module example(a, b, c, d, e, y); input a,b,c,d,e; output y; wire m,n; assign m = ~a & b & c; assign n = m | ~d; assign y = n & ~e; endmodule 使用Quartus II自带的综合工具,我们可以看到它的RTL视图如图5.10所示,和我们的代码相吻合。(特权同学,版权所有) 图5.10 未优化前综合结果 而现在假定输入a到输出y的路径是关键路径,影响了整个逻辑的时序性能。那么,下面我们就要想办法从这条路径着手做一些优化的工作。很简单,我们的目标是减少输入a到输出y之间的逻辑等级,目前是3级,我们可以想办法减少到2级甚至1级。(特权同学,版权所有) 我们来分析公式“y = ((~a & b & c) | ~d)& ~e;”,把~a从最里面的括号往外提取一级就等于减少了一级逻辑。我们简单的分析,当a=0时,y = ((b & c) | ~d) & ~e;当a=1时,y = ~d & ~e。由此我们不难得到“y = ((~a | ~d) & ((b &c) | ~d)) & ~e;”与前式是等价的。我们可以修改前面的代码如下: // Verilog例程 module example(a, b, c, d, e, y); input a,b,c,d,e; output y; wire m,n; assign m = ~a | ~d; assign n = (b & c) | ~d; assign y = m & n & ~e; endmodule 经过修改后的代码综合结果如图5.11所示,虽然b和c到y的逻辑等级还是3,但是关键路径a到y的逻辑等级已经优化到了2级。与前面不同的是,优化后的d信号多了一级的负载,也多了一个逻辑门,这其实也是一种“面积换速度”思想的体现。正可谓“鱼和熊掌不可兼得”,在逻辑设计中我们往往需要在“鱼和熊掌”间做抉择。(特权同学,版权所有) 图5.11 优化后综合结果 上面的这个实例,只是一个也许未必非常恰当的“鱼”的例子。在前面的章节里已经介绍过,在实际工程应用中,类似的逻辑关系可能在映射到最终器件结构时并非以逻辑门的方式来表现,通常是四输入查找表来实现,那么它的优化可能和单纯简单逻辑等级的优化又有些不同,不过希望大家能在这个小例子中学到“渔”的技巧。(特权同学,版权所有)
|