时序优化中重要的一项就是提高模块的最高工作频率,工作频率由关键路径决定,通常的提高工作频率的步骤是:利用时序分析工具找到关键路径,分析关键路径主要延迟是布线延迟还是逻辑延迟,然后轮番十八般武器,如果是逻辑延迟过大就用逻辑切割,插入D触发器,如果布线延迟太长,则复制触发器,减小负载等等,按部就班后,有时可以明显改善,但很多时候由于设计需求所限不能插入触发器,或是面积受限无法复制触发器,这些程式化的优化方法收效就甚微了,此时,该怎么办呢? 马克思爷爷曾经说过:“世上任何事物都不是孤立的,而是相互联系的,相互制约,相互作用”。受此启发,我们所看到的关键路径,并不是单单由关键路径上的逻辑决定的,而是由工程里所有的逻辑决定的,其中也包括很多和关键路径无关的逻辑。一块FPGA的资源是固定的,如果工程里的一些模块优先占用了风水宝地,剩下的模块只能将就着使用其次的资源,最终很委屈的成为了关键路径。所以,关键路径的形成可能并不是由于自身逻辑的复杂,而是好的资源被其他模块抢走了,我们可以换一换思路,不要局限于关键路径,从系统角度出发,通过简化关键路径之外模块的逻辑,提高工作频率。

最有效的简化方法一般都要基于具体的工程而言,从需求,功能,实现等大方向做减法,这些方法需要很强的专业背景,不具备通用性,而我想从更具普遍性的编码风格细节入手,谈一谈好的编码风格是如何简化逻辑,提高工作频率的。本篇先来讲讲大家再熟悉不过,但又很容易被忽视的if  else。

if else在FPGA工程里可以说是无处不在,在时序逻辑里其主要可以归为两类,一类是补全if else的,主要用于选择器,如下所示,当sel_1有效输出0,sel_2有效时输出1,其他情况都输出0。

always @(posedge clk or negedge rset_n)
begin
if(!rset_n)
d <= 0;
else if(sel_1)
d <= 0;
else if(sel_2)
d <= 1;
else
d <= 0;
end

其RTL图如图一所示,很简单,就是一个选择器加一个D触发器。

图一

另一类是没有补全的if else,主要用于锁存数据,如下所示,和上例不同的是,当sel_1和sel_2无效时,输出会保持上一个状态。

always @(posedge clk or negedge rset_n)
begin
if(!rset_n)
d <= 0;
else if(sel_1)
d <= 0;
else if(sel_2)
d <= 1;
end

其RTL图如图二所示,和图一相比,多了一个选择器,并将D触发器的输出反馈到了选择器的输入端,实现锁存的功能。

图二

从上述可知,补全if else实现的逻辑会比if else不全的逻辑少一条反馈路径和一个选择器,如果是更复杂的应用,后者消耗的资源可能还会更多。

至此,如能根据具体的应用,需要选择器时使用补全的if else,需要锁存功能时,使用不全的if else,那就没有任何问题了,但是,我想重点提醒下,很多人在使用时,对这两种编码风格混淆不清,特别是在一段式状态机里,造成了不必要的浪费,拉低了最高工作频率,下面举一个工作中实际的例子。

工程需要跑到200MHz,但在优化前只有174MHz,查看关键路径如图三所示。

图三

oe_width到fast_rd_wait_fifo是当前的速度瓶颈,由于设计所限,无法在这条路径内插入D触发器,开启quartus的寄存器复制优化项,效果也不明显...常用的优化方法都试过一遍了,但都没太多疗效。按照开篇提到的马克思爷爷的"万事万物都有联系"的思路,撇开关键路径,查看工程里其他的模块是否有可以简化之处,寻找了良久,终于找到了一个貌似可以优化的状态机,截取了其中的关键代码如下。

....
case(fast_rd_state) fast_rd_st0:
begin
if(executive_cmd)
begin
fast_rd_busy <= 1;
if(!count_en)
begin
fast_rd_ok <= 0;
rdaddr_add <= 1;
fast_rd_state <= fast_rd_st1;
end
else
begin
fast_rd_ok <= 0;
rdaddr_add <= 1;
fast_rd_state <= fast_rd_st2;
end
end
else
begin
fast_rd_busy <= 0;
fast_rd_ok <= 0;
rdaddr_add <= 0;
fast_rd_state <= fast_rd_st0;
end
end fast_rd_st1:
begin
rdaddr_add <= 0;
if(rd_count_almost_full)
begin
if(fifo_wrusedw < fifo_rd_deep)
begin
fast_rd_busy <= 0;
fast_rd_ok <= 1;
fast_rd_state <= fast_rd_st0;
end
else
begin
//fast_rd_busy <= 1; /*注意这句话*/
fast_rd_ok <= 0;
fast_rd_state <= fast_rd_st3;
end
end
else
begin
//fast_rd_busy <= 1; /*注意这句话*/
fast_rd_state <= fast_rd_st1;
end
end
.....

注意红色加粗部分,优化前是没有这两句话的,所以优化前,这是一个没有补全的if else,会综合出锁存器,当初没加这两句话的原因是:从逻辑上感觉没有必要,因为从fast_rd_st0状态跳到fast_rd_st1状态后,fast_rd_busy肯定是1了,没有必要再在fast_rd_st1状态机里加上fast_rd_busy  <= 1,让其保持上一个状态的输出就可以了,而且这样还可以省两行代码,关键是实际的执行的结果完全正常。

但是,实际上根本不需要在fast_rd_st1状态锁存fast_rd_st0状态时fast_rd_busy的输出,在红色加粗处补上 fast_rd_busy  <= 1后,将状态机变成补全的if else类型后,奇迹发生了,综合频率提高到了190MHz,虽然还没达到200MHz,但相比没有补全if else的写法,提高了16MHz,再看关键路径报告如图四,oe_width到fast_rd_wait_fifo的关键路径悄无声息的消失了。

图四

这再一次的证明了马爷爷的思想是多么的神奇和伟大,没有使用任何传统的优化方式,仅仅是改变了其他逻辑的编码风格,就显著的提升了工作频率,虽然从程序上看,fast_rd_busy并不直接属于关键路径的逻辑范畴,但fast_rd_busy牵扯到的逻辑资源和关键路径的逻辑有着紧密的间接相互作用关系,继续查找频率提升的原因,用Technology map viewer查看没有补全if else的fast_rd_busy的源端逻辑资源如图五所示。

图五

再看看补全if else情况下fast_rd_busy的Technology map viewer如图六所示。

图六

比较图五和图六,前者具备锁存功能,将fast_rd_busy的输出经过复杂的判断比较逻辑又反馈到了寄存器的输入端,牵扯到的逻辑要明显多于后者,补全if else后,只有选择功能,省去了输出反馈的逻辑,整体的工作频率自然就得到了改善。

使用if else时,我们常常会因为其简单,而混淆了带锁存器和无锁存器这两种编码风格,更甚,在误用了没有补全的if else的写法后,会因其表面的逻辑功能正常和减少的代码量而觉得不以为然,其实,它都在潜移默化的影响着你工程的关键路径,赶紧看看你的工程里是否存在这些没有必要的锁存器吧,统统去掉,定有惊喜等着你奥。

优化时序之补全if else的更多相关文章

  1. VS Code Java 3月更新|代码补全、Maven 以及 Java 插件预览版本新升级!

    Nick Zhu Senior Program Manager, Developer Division at Microsoft 大家好,欢迎来到 Visual Studio Code Java 的 ...

  2. ADT开发中的一些优化设置:代码背景色、代码字体大小、代码自动补全

    初学Android开发,在网上找到一些ADT工具的优化,自己设置好了,截图保存下来.免得以后忘了. 1. 设置背景颜色: 色调85.饱和度90.亮度205 RGB:199.237.204 2. 设置代 ...

  3. eclipse自动补全的设置

    eclipse自动补全的设置   如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的 ...

  4. eclipse自动补全的设置(自动提示)

      如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为e ...

  5. 仿Google首页搜索自动补全

    仿Google自动补全,实现细节: 后台是简单的servlet(其实就是负责后台处理数据交互的,没必要非跌用个struts...什么的) 传输介质:xml 使用jQuery js框架 功能实现: 如果 ...

  6. IntelliJ IDEA 设置代码提示或自动补全的快捷键 (附IntelliJ IDEA常用快捷键)

    修改方法如下: 点击 文件菜单(File) –> 点击 设置(Settings- Ctrl+Alt+S), –> 打开设置对话框. 在左侧的导航框中点击 KeyMap. 接着在右边的树型框 ...

  7. (转)eclipse自动补全的设置

    如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为ecl ...

  8. jupyter notebook安装/代码补全/支持golang 踩坑记

    安装(不要用root) 安装anaconda3,然后ln -s bin目录下的jupyter命令到/usr/bin目录下 生成密码备用 敲ipython进入交互终端 In [1]: from note ...

  9. ES系列十三、Elasticsearch Suggester API(自动补全)

    1.概念 1.补全api主要分为四类 Term Suggester(纠错补全,输入错误的情况下补全正确的单词) Phrase Suggester(自动补全短语,输入一个单词补全整个短语) Comple ...

随机推荐

  1. BZOJ 2141 排队(CDQ分治)

    我们把每一次交换看做两个插入两个删除.然后就是一个三维偏序.时间一维,下标一维,权值一维. #include<iostream> #include<cstring> #incl ...

  2. centos 7.1安装frees witch

    http://blog.sina.com.cn/s/blog_539d6e0c0102zgvm.html

  3. 51nod 1079 中国剩余定理模板

    中国剩余定理就是同余方程组除数为质数的特殊情况 我直接用同余方程组解了. 记得exgcd后x要更新 还有先更新b1再更新m1,顺序不能错!!(不然会影响到b1的更新) #include<cstd ...

  4. 网页里如何使用js禁用F12事件

    接上一篇,突然想起来,类似于网页里如何使用js禁用鼠标右击事件,还有禁用F12事件也可以禁用一下,总所周知,对于Web开发人员来说,常常要进行界面的调试.使用F12调试工具能够很方便地进行调试,查看h ...

  5. 素数计数函数$\pi(x)\sim \Theta(\frac{x}{\log{x}})$的一个初等方法——素数定理的估计

    $\DeclareMathOperator{\lcm}{lcm}$ 本文的方法来源于GTM 190:"Problems in Algebraic Number Theory",给出 ...

  6. 今天遇到的一个诡异的core和解决 std::sort

    其实昨天开发pds,就碰到了core,我还以为是内存不够的问题,或者其他问题. 今天把所有代码挪到了as这里,没想到又出core了. 根据直觉,我就觉得可能是std::sort这边的问题. 上网一搜, ...

  7. 2、java注释、标识符、数据类型、类型转换

    一.三种注释:单行注释.多行注释.文档注释(只能在类前或者方法前,@author作者) 二.java使用的编码为unicode码[0-65535]   包含ASCII码,在0-255中 ASCII码( ...

  8. Object-c Associated Object

    oc的关联的作用在我看来就是将两个对象关联起来,用的时候通过key和对象把和这个对象关联的对象再取出来(我做的项目就是和UITableView里面的一个属性关联起来了) 举个栗子: - (void)v ...

  9. 安卓4.3以上版本已经完美支持BLE(英文版)

    Android 4.3 (API Level 18) introduces built-in platform support for Bluetooth Low Energy in the cent ...

  10. IHttpHandler的学习(0)

    本片文章转自网络 问题1:什么是HttpHandler?(Handler:处理者:那就是对Http请求的处理拉) 问题2:什么是HttpModule? 问题3:什么时候应该使用HttpHandler什 ...