优化时序之补全if else
时序优化中重要的一项就是提高模块的最高工作频率,工作频率由关键路径决定,通常的提高工作频率的步骤是:利用时序分析工具找到关键路径,分析关键路径主要延迟是布线延迟还是逻辑延迟,然后轮番十八般武器,如果是逻辑延迟过大就用逻辑切割,插入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的更多相关文章
- VS Code Java 3月更新|代码补全、Maven 以及 Java 插件预览版本新升级!
Nick Zhu Senior Program Manager, Developer Division at Microsoft 大家好,欢迎来到 Visual Studio Code Java 的 ...
- ADT开发中的一些优化设置:代码背景色、代码字体大小、代码自动补全
初学Android开发,在网上找到一些ADT工具的优化,自己设置好了,截图保存下来.免得以后忘了. 1. 设置背景颜色: 色调85.饱和度90.亮度205 RGB:199.237.204 2. 设置代 ...
- eclipse自动补全的设置
eclipse自动补全的设置 如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的 ...
- eclipse自动补全的设置(自动提示)
如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为e ...
- 仿Google首页搜索自动补全
仿Google自动补全,实现细节: 后台是简单的servlet(其实就是负责后台处理数据交互的,没必要非跌用个struts...什么的) 传输介质:xml 使用jQuery js框架 功能实现: 如果 ...
- IntelliJ IDEA 设置代码提示或自动补全的快捷键 (附IntelliJ IDEA常用快捷键)
修改方法如下: 点击 文件菜单(File) –> 点击 设置(Settings- Ctrl+Alt+S), –> 打开设置对话框. 在左侧的导航框中点击 KeyMap. 接着在右边的树型框 ...
- (转)eclipse自动补全的设置
如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为ecl ...
- jupyter notebook安装/代码补全/支持golang 踩坑记
安装(不要用root) 安装anaconda3,然后ln -s bin目录下的jupyter命令到/usr/bin目录下 生成密码备用 敲ipython进入交互终端 In [1]: from note ...
- ES系列十三、Elasticsearch Suggester API(自动补全)
1.概念 1.补全api主要分为四类 Term Suggester(纠错补全,输入错误的情况下补全正确的单词) Phrase Suggester(自动补全短语,输入一个单词补全整个短语) Comple ...
随机推荐
- Python中编写精美图形界面(PyQt5)
纯代码,布局的讲解 见: https://cloud.tencent.com/developer/article/1345469 Qt designer设计文件 .ui转 .py文件,进阶使用 注:不 ...
- docker-ce-17.03.2 离线安装RPM包
[root@docker05 docker]# ll total 20796 -rw-r--r-- 1 root root 75032 Mar 26 23:52 audit-libs-pytho ...
- echars 在vue v-if 切换会 显示不出来或者显示出来但是不是百分百显示
我也是百度看别人写的原因,然后自己总结,以后用到的时候来复制就可以将 v-if换成 v-show 第二不是百分百显示 可以用 this.$nextTick(function() { this.in ...
- android mvp高速开发框架介绍(dileber使用之小工具使用)
android mvp框架:dileber(https://github.com/dileber/dileber.git) 继续为大家介绍android mvp开源框架 dileber 官方交流qq群 ...
- sage开发url替换字符串
/// <summary> /// Url字段值替换,无该字段则加入 /// </summary> /// <param ...
- angularjs 服务供应商
<!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...
- MDNS DDoS 反射放大攻击——攻击者假冒被攻击者IP向网络发送DNS请求,域名为“_services._dns-sd._udp.local”,这将引起本地网络中所有提供服务的主机都向被攻击者IP发送DNS响应,列举网络中所有服务
MDNS Reflection DDoS 2015年3月,有报告叙述了mDNS 成为反射式和放大式 DDoS 攻击中所用媒介的可能性,并详述了 mDNS 反射式攻击的原理和相应防御方式.Q3,Akam ...
- [poj 2773] Happy 2006 解题报告 (二分答案+容斥原理)
题目链接:http://poj.org/problem?id=2773 题目大意: 给出两个数m,k,要求求出从1开始与m互质的第k个数 题解: #include<algorithm> # ...
- Nginx服务器的反向代理proxy_pass配置方法讲解
Nginx的配置还是比较简单的,如: 1 2 3 4 location ~ /* { proxy_pass http://127.0.0.1:8008; } 或者可以 1 2 3 4 loca ...
- 18.查询效率最高的unordered_map
#include <string> #include <iostream> //查询性能最高 //增删查改与map是一样的,但是本质区别就是unordered_map底层是ha ...