逻辑级数与逻辑延时优化实战

综述

      FPGA设计无可避免的会在FF之间穿插组合逻辑,那么这些组合逻辑如何量化分析?如何优化收敛?如何从RTL设计时就预估到可能产生的延时大小?

      接下来就通过一个简单的工程,进行实战演示。

原始工程

定义一个32的计数定时器,定时计数80S,假设主时钟频率50M,代码如下:

    module TEST_TOP(input                clk_sys,    // 50Minput                rst  ,input                plus ,output reg  [15:0]   d ); function [31:0]count_s(  input  [7:0]   s_n        );count_s = 50_000_000* s_n ;endfunctionreg [31:0]  cnt_s ;always@(posedge clk_sys or negedge rst)beginif(rst)begincnt_s <= 'd0 ;end else if(cnt_s >= count_s(80)) begincnt_s <= 'd0 ;end else begin cnt_s <= cnt_s + 1 ;endend  reg  plus_d1,plus_d2;always@(posedge clk_sys)beginplus_d1    <= plus ;plus_d2    <= plus_d1 ;end always@(posedge clk_sys)beginif(s_carry_en)d <= d + plus_d2 ;end
endmodule

上述这段代码,我们如何获取各路径的延时呢?Xilinx提供一种评估方式叫逻辑级数(logic_level),简单来讲就是组合逻辑串联的个数,那么如何获取当前设计的逻辑级数呢?

打开这段代码综合后的文件,在Tcl consol 中运行前面的查询命令可得到当前设计各逻辑级数的路径数,

逻辑级数查询命令

report_design_analysis -logic_level_distribution 
-logic_level_dist_paths 5000 -name design_analysis_prePlace

如下图所示,最高逻辑级数有12,共有4条逻辑级数为12的路径。

一般优先分析级数最高的路径,通过report 命令可获得具体的路径信息:

 以Path1为例,选中路径,快捷键F4,可获取该路径的原理图:

从原理图可以看到,两个FF之间,共经过1LUT5+2LUT6+8CARRY4 = 11 logic_level ;

首先科普一个概念:

什么是LUT?什么是CARRY?

LUT : look up table,查找表,是FPGA实现组合逻辑的一种方式,具体会在其他讲解底层资源的博

          客详细说明;

CARRY:进位链,进位溢出,这个在大学微机原理都学过,为了连接一个过大位宽累加器而存在

          的逻辑工具;

if-else的判定条件需要LUT实现,累加器的进位需要靠CARRY实现。

若两个FF直连,则logic_level = 1;

上图中插入了11个逻辑单位,所以logic_level = 12;

该路径的总共传输延时3.015ns,逻辑延时1.46ns。

第一步优化----拆分大位宽累加器

我们再换一种写法,将32位的计数器拆分成两个16位的计数器:

    function [15:0]count_ms(  input  [7:0]   ms_n        );count_ms = 50_000*ms_n ;endfunctionfunction [15:0]count_s(  input  [7:0]   s_n        );count_s = 1_000* s_n ;endfunctionreg [15:0]   cnt_ms ;reg [15:0]   cnt_s ;always@(posedge clk_sys or negedge rst)beginif(rst)begincnt_ms <= 'd0 ;end else if(cnt_ms >= count_ms(1)) begincnt_ms <= 'd0 ;end else begincnt_ms <= cnt_ms + 1 ;endendalways@(posedge clk_sys or negedge rst)beginif(rst)begincnt_s <= 'd0 ;end else if(cnt_ms >= count_ms(1)) beginif(cnt_s >= count_s(80))cnt_s <= 'd0 ;else cnt_s <= cnt_s + 1 ;endend  reg  plus_d1,plus_d2;always@(posedge clk_sys)beginplus_d1    <= plus ;plus_d2    <= plus_d1 ;end always@(posedge clk_sys)beginif(cnt_ms >= count_ms(1))d <= d + plus_d2 ;end

重新综合后,输出分析报告我们发现,新设计的最大逻辑级数只有7,

 打开逻辑级数为7的路径

  传输路径变成2LUT + 4 CARRY4;逻辑单元相对原来减少1个LUT6,和 4个CARRY4。

逻辑延时由之前的1.46ns 降到1.16ns,减少0.3ns ,减少20% ;

CARRY减少很好理解,因为我们将32位的累加器拆成两个16位的累加器,

原来1级累加,拆分后变成两级累加;拆分后每一级只有16位宽;所以每一级FF之间所需要的进位链也相应的减少了;

通过这一步我们可以发现:

1、CARRY4是4输入的,如果累加器或计数器的位宽每超过4就会多消耗一个CARRY4:

比如:例1中,计数器定义32bit,最后消耗了8个进位链;而例2优化成16bit后,就只消耗4个进位链了。

2、正常情况下,布线延时与逻辑延时整体是接近1:1,当降低逻辑级数,减少了逻辑延时,也相应的减少了布线延时。

再看一下路径的具体时序报告,可以看到具体的每一级逻辑的延时:

Incr为增加的延时,Path为中间每个节点的时刻;

第二步优化----简化if-else判定条件

从前面我们可以发现,减少累加器位宽,可以极大减少进位链的级数,进而减少逻辑延时与布线延时,除此之外是否还有别的方法可以达到减少组合逻辑延时呢?从前面看组合逻辑延时主要由两部分组成:1、进位链 ; 2、LUT。

进位链的级数由累加器的位宽决定,那么LUT的个数呢?我们知道LUT是用来实现组合逻辑,且一个LUT只有6个输入,当组合逻辑的复杂度较高和输入信号的位宽数较大时,自然所需要消耗的LUT数量就更多。以前面的工程为例,我们并没有使用assign 这种组合逻辑赋值语句,那么是哪里使用了组合逻辑呢?

答案就是if-else 的逻辑判定条件。if-else 判定条件涉及多位宽数据对比,以及多条件嵌套都会增加实现该判定功能的组合逻辑复杂度。

这是原始代码的always 块书写方式:

    always@(posedge clk_sys or negedge rst)beginif(rst)begincnt_s <= 'd0 ;end else if(cnt_ms >= count_ms(1)) beginif(cnt_s >= count_s(80))cnt_s <= 'd0 ;else cnt_s <= cnt_s + 1 ;endend 

我们修改一下:

module TEST_TOP(input                clk_sys,    // 50Minput                rst  ,input                plus ,output reg  [15:0]   d );function [15:0]count_ms(  input  [7:0]   ms_n        );count_ms = 50_000*ms_n ;endfunctionfunction [15:0]count_s(  input  [7:0]   s_n        );count_s = 1_000* s_n ;endfunctionreg   ms_carry_en ;always@(posedge clk_sys)beginif(cnt_ms == count_ms(1)-1)ms_carry_en <= 'd1 ;else ms_carry_en <= 0 ;end   reg   s_carry_en ;always@(posedge clk_sys)beginif(cnt_s == count_s(80)-1)s_carry_en <= 'd1 ;else s_carry_en <= 0 ;end  reg [15:0]   cnt_ms ;reg [15:0]   cnt_s ;always@(posedge clk_sys or negedge rst)beginif(rst)begincnt_ms <= 'd0 ;end else if(ms_carry_en) begincnt_ms <= 'd0 ;end else begincnt_ms <= cnt_ms + 1 ;endendalways@(posedge clk_sys or negedge rst)beginif(rst)begincnt_s <= 'd0 ;end else if(ms_carry_en) beginif(s_carry_en)cnt_s <= 'd0 ;else cnt_s <= cnt_s + 1 ;endend  

再看一下综合后的效果:

最大的逻辑级数只有6,较例2减少了1级,由原来的LUT4+LUT5减少为1个LUT1(优化后的判定条件只有1bit输入);

总延时由之前的2.356,降至1.451,减少0.9ns ,减少比例达到38%;

 逻辑延时由之前的1.16,减少量并不多,通过对比data path数据发现,优化后主要减少了一个LUT5、以及该LUT5前后级的连线。

第三步优化----拆分赋值表达式(面积换速度)

其实这个很好理解,就是将一步运算拆分成多步运算,构建流水线;

例如:S = A + B+ C ;

可以设计成:

S1 = A+B ;

S = S1+C 。

这一步的目的与第二步其实类似,赋值等式右边的实现方式,也是通过LUT与进位链的组合实现,过于复杂的赋值表达式会带来过长的组合逻辑级联。

由于我们的原始例程并没很冗长的赋值表达式,而且这种情况非常常见,也很好理解,暂时不单独举例分析。

总结

1、FF之间的data_delay主要由两部分构成逻辑延时和布线延时;逻辑级数增多、布线节点

增加,布线延时也会相应的增加;

2、布线延时与逻辑延时的占比应该是接近1:1;

当逻辑延时 > 布线延时的50%,请优化逻辑延时;

当布线延时 > 逻辑延时的50% ,请优化布线延时;(参考UG1292)

当延时不满足时,建议先优化逻辑延时,因为这是我们能做的,

布线延时只能靠工具的策略优化,很多时候组合逻辑不合理,可能会导致同一个信号组 被布局到不同列的CLB,导致布线困难。

3、过大的计数器位宽会带来过多的进位链,从而造成过多的逻辑级数;

尽量避免大位宽计数器,250M以内的设计,最好不要超过16bits;

4bits位宽会占用一个进位链;

4、复杂的if - else 判定条件,需要多级LUT实现,也会造成过多的逻辑级数;

设计中尽量避免if-else 嵌套、if-case嵌套;

尽量避免if-else判定条件的输入变量位宽过大;

尽量避免在判定条件处实现多条件的逻辑运算,可以提前打一拍转换成单bit条件;

5、当赋值表达式过于冗长,可以考虑拆分成多级处理,以提高设计性能;

6、组合逻辑级数的合理经验值:≤2N(N为当前时钟域的时钟周期)。

最后,逻辑级数并不是越低越好,一定程度上优化逻辑级数会带来额外的资源消耗,但是当设计不满足性能要求是,优化是必须的。最好是在设计的时候就做到心中有数,避免最后无法实现设计收敛,再回过头来一个个修改,浪费时间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/452850.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32F407 CAN参数配置 500Kbps

本篇CAN参数适用 芯片型号&#xff1a;STM32F407xx系统时钟&#xff1a;168MHz&#xff0c;CAN挂载总线APB1为42M波 特 率 &#xff1a;500Kpbs引脚使用&#xff1a;TX_PB9&#xff0c;RX_PB8&#xff1b;修改为PA11PA12后&#xff0c;参数不变。 步骤一、打勾开启CAN&#xf…

企业级大数据安全架构(九)FreeIPA管理员密码忘记后如何修改

作者&#xff1a;楼高 1重置Directory Server管理员密码 1.1停止directory server服务 [rootipa schema]# start-dirsrv HDP-HADOOP 如果你不知道你的实例名&#xff0c;可以通过如下方式获取 1.2生成一个新的HASH密码 停止服务后使用pwdhash命令生成一个新的HASH密码 [r…

Android电动汽车充电服务vue+uniAPP微信小程序

本系统利用SSM和Uniapp技术进行开发电动汽车充电服务系统是未来的趋势。该系统使用的编程语言是Java&#xff0c;数据库采用的是MySQL数据库&#xff0c;基本完成了系统设定的目标&#xff0c;建立起了一个较为完整的系统。建立的电动汽车充电服务系统用户使用浏览器就可以对其…

使用maven对springboot项目进行瘦身

目录 一、什么是Maven 二、springboot 项目 三、springboot 项目瘦身 一、什么是Maven Maven是一个基于Java的项目管理和构建工具。它通过提供一个一致的项目结构、自动化构建脚本和依赖管理系统&#xff0c;简化了Java项目的构建过程。 Maven使用一种称为POM&#xff08;…

Axure Cloud for Business On-Premises 本地服务端部署说明(支持Axure8/9/10)

Axure9不再⽀持SVN&#xff0c;只能通过AxureCloud进⾏团队协作&#xff0c;众所周知&#xff0c;因为国内没有服务器&#xff0c;所以速度非常的慢&#xff0c;为了解决这个问题&#xff0c;本⽂指导如何在公司内⽹或者服务器私有化部署Axure Cloud for Business On-Premises。…

flask+pyinstaller实现mock接口,并打包到exe运行使用postman验证

flask代码 from flask import Flask, request, jsonifyapp Flask(__name__)app.route("/login", methods[POST]) def login():username request.json.get("username").strip() # 用户名password request.json.get("password").strip() # 密…

计算机网络-数据链路层概述(功能概述 链路 数据链路 物理通道 逻辑通道)

文章目录 总览数据链路层的研究思想数据链路层的基本概念数据链路层功能概述 总览 封装成帧指的是数据链路层将来自上层的网络层数据包&#xff08;如IP数据报&#xff09;添加上自己的帧头和帧尾&#xff0c;形成一个完整的帧。这个过程包括了对数据的封装&#xff0c;以便于在…

MacBook有必要装清理软件吗?CleanMyMac的一些主要特点

MacBook是苹果公司的一款高端笔记本电脑&#xff0c;但是&#xff0c;随着使用时间的增长&#xff0c;MacBook也会出现一些问题&#xff0c;比如运行缓慢、卡顿、垃圾文件堆积、磁盘空间不足等。这些问题不仅影响了用户的使用体验&#xff0c;也可能对MacBook的寿命和安全性造成…

后端程序员入门react笔记(一)

相关参考 react 首先&#xff0c;我们先大概了解一下什么是react以及react可以干什么。 React 是 Facebook 开源的一个用于构建用户界面的一款 JavaScript 库&#xff0c;主要用于构建 UI。 react的特点 声明式编程 react使用jsx进行渲染&#xff0c;这是一种类似html的语法…

前端框架学习 Vue(3)vue生命周期,钩子函数,工程化开发脚手架CLI,组件化开发,组件分类

Vue 生命周期 和生命周期的四个阶段 Vue生命周期:一个Vue实例从创建 到 销毁 的整个过程 生命周期四个阶段 :(1)创建 (2)挂载 (3)更新 (4)销毁 Vue生命周期函数(钩子函数) Vue生命周期过程中,会自动运行一些函数,被称为[生命周期钩子] ->让开发者可以在[特定阶段] 运行自…

视频美颜SDK开发指南:从入门到精通的技术实践

美颜SDK是一种强大的工具&#xff0c;它不仅仅可以让用户在实时视频中获得光滑的肌肤和自然的妆容&#xff0c;从简单的滤镜到复杂的人脸识别&#xff0c;美颜SDK涵盖了广泛的技术领域。 一、美颜SDK的基本原理 美颜SDK包括图像处理、人脸检测和识别、滤镜应用等方面。掌握这些…

vue2 el-table新增行内删除行内(两种写法)里面第一个是树组件,第二个是数字组件,第一个数组件只能勾选最后一个节点

第一种 <template><div class"time_table"><div style"margin-bottom: 10px"><el-button click"addRowFn">新增</el-button></div><el-form ref"costForm" :model"formData">&l…