当前位置: 首页 > news >正文

Synopsys Datapath Coding 指南

内容参考Synopsys的《Coding Guidelines for Datapath Synthesis》,网上可以直接搜到。针对数据通路给出了写代码的指导。

文档总结了解决 datapaths 综合的编码准则:
有助于在 RTL 中实现功能正确性和算术表达式预期行为的准则法典;帮助 Datapath synthesis 实现最佳 QoR (Quality of results) 的指南。

涉及到有符号无符号的操作规则,操作中位宽的确定规则等。
其中有很多在写代码过程中需要注意的点,也帮助我们更加了解工具对其的
处理方式,以及如何使用工具进行检查和优化。

General Guidelines

1、使用signed类型做有符号数运算, 不要使用无符号操作数或自己操作来模拟有符号算术。

举例:
在这里插入图片描述

!在看例子的时候首先需要明确乘法操作时,需要判断被乘数是有符号数还是无符号数,两者结果是不同的。
具体有符号数乘法操作参见 Verilog – 有符号与无符号的加法和乘法运算。注意下面被乘数的负数符号位乘出来的一行数要取反加一

  • 下面左边第一个自行拓宽了被乘数的符号位,把无符号类型的输入当成有符号数去算了,拓展符号位之后,两个16*16的数相乘会得到32位结果,但是这里只会取后16位,这样计算的结果和按有符号乘法计算的结果一致。
  • 正常应该是直接定义signed类型的有符号数然后直接相乘。
  • 第二行的操作结果和扩位是一样的,后几位并没有变,只是前面加了符号位,但这样DC无法直接识别为简单的有符号乘法, 应该就是按无符号乘法来算了。这样会导致电路体积增⼤。

以-5和-7为例,下面是仿真结果:
z,z_1,z_sign都是15bit位宽,可以看到实例中的几个结果都是一致的,而直接将a*b的结果不对。
对比z_23_32和z_24_32的结果可以发现,按无符号去算和有符号乘法算的结果不一样,但因为只取后几位,所以结果一致,和直接按有符号数算的结果相同。

assign  z = {{8{a[7]}},a}*{{8{b[7]}},b};
assign  z_1 = a*b;
assign  z_11 = $unsigned({{8{a[7]}},a})*$unsigned({{8{b[7]}},b});
wire  signed [7:0] a_sign;
wire  signed [7:0] b_sign;assign a_sign = $signed(a);
assign b_sign = $signed(b);
assign z_sign = a_sign * b_sign;
wire [15:0] temp_a = (a[6:0] - (a[7]<<7));
wire [15:0] temp_b = (b[6:0] - (b[7]<<7));
wire [15:0] z_22 = temp_a * temp_b;
wire [15:0] z_23 = $signed(temp_a) * $signed(temp_b);
wire [15:0] z_24 = $unsigned(temp_a) * $unsigned(temp_b);
wire [31:0] z_23_32 = $signed(temp_a) * $signed(temp_b);
wire [31:0] z_24_32 = $unsigned(temp_a) * $unsigned(temp_b);

示例图片
在这里插入图片描述

2、如果可能的话, 不要手动sign/零扩展,通过使用适当的无符号/有符号类型, 正确的扩展可以按以下方式完成:

  • VHDL: Use standard functions (‘resize’ in ‘ieee.numeric_std’, ‘conv_*’ in ‘ieee.std_logic_arith’).
  • Verilog: Extension is automatically done.

示例:
在这里插入图片描述

Verilog Guidelines

3、不要混合使用有符号和无符号数。混合表达式在 Verilog 中被解释为无符号表达式。

如果⼀个操作数无符号, Verilog 会将整个表达式解释为无符号,可能会导致和预期不符。

示例:
在这里插入图片描述
这里尤其需要注意有符号数和常数相乘的时候,常数要注明是有符号的。

4、部分选择或拼接中,无论操作数是什么, 结果都是无符号的。即使部分选择了整个向量。

示例:
在这里插入图片描述

5、 Verilog 中表达式的宽度确定如下:

  • 上下文确定的表达(Context-determined expression): 在赋值中, 左侧提供确定右侧表达式宽度的上下文(即,表达式具有其被赋值的向量的宽度)。
  • 自确定表达式(Self-determined expression): 没有上下文的表达式(例如, 括号中的表达式) 根据操作数的宽度确定其宽度。 对于算术运算, 自确定表达式的宽度等于最宽操作数的宽度。

根据上下文确定的:
在这里插入图片描述
自确定的:
在这里插入图片描述
这里很容易出错!$signed、>、{ }这些不是直接赋值的操作都会导致结果位宽由本身的操作数决定,很容易出现结果与预期不相符
比如verilog乘法结果位宽求助中就是因为拼接导致的结果有误。
正确的做法是把每一步运算写开,每一步都写明结果位宽,再进行下一步运算。

VHDL Guidelines

6、 数值包Numeric packages (VHDL)

  • 数值包的选择规则:
    推荐使用IEEE标准包ieee.numeric_std进行数值运算,ieee.std_logic_arith (Synopsys包)可作为替代选择,禁止同时使用多个数值包(避免冲突)。
  • 数值类型的使用规则:
    在算术表达式中应使用signed(有符号)或unsigned(无符号)类型,目的是明确指定算术运算是无符号还是有符号(2的补码)运算。
    在这里插入图片描述

Guidelines for QoR

下面是关于QoR的指南

7、Cluster datapath portions

规则: 集群相关的数据路径部分在 RTL 代码中将其合并到一个组合块中, 不要将它们拆分成不同的块。 特别是:

  • 将相关数据路径部分保留在单⼀层次组件。 不要将它们分布到设计层次结构的不同级别或⼦组件中。
  • 做未放置寄存器相关数据路径部分之间。 如果数据路径块内需要寄存器来满⾜ QoR 要求, 请使⽤ 重定时将寄存器移动到最佳位置后整个数据路径块已经实现。

相关数据路径部分是 RTL 代码中描述数据路径功能的部分, 如果⼀起实现, 则允许某些优化/共享(也就是,因为可以提取和合成更⼤的数据路径块,所以由更好的QoR)。 这包括共享公共输⼊或相互馈送(即,一个数据路径的输出用作另⼀个数据路径的输⼊) 的数据路径部分, 以及具有互斥操作但可能共享的数据路径部分。

对datapath的检查:
在这里插入图片描述
在这里插入图片描述
HDL-121针对的是寄存器,当一个模块中的数据路径之间存在寄存器的时候会报告出来,但是如果数据路径在不同的层次(即不同模块中),则工具无法报告,除非用ungroup打破。

8、混合⽆符号/有符号数据路径

不要在一个datapath cluster中混用有符号和无符号类型,都是用有符号,或者把无符号转成有符号。因为无符号和有符号运算不能合并在⼀起形成⼀个单⼀的数据路径块(综合限制)。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

9、可切换无符号/有符号运算的数据路径(Switchable unsigned/signed datapath)

核心思想是通过选择性零扩展/符号扩展来合并无符号和有符号运算的硬件电路,从而优化设计质量(QoR)。某些场景需要数据路径既能处理无符号数(unsigned)又能处理有符号数(signed),通常由控制信号(如tc)切换。

直接实现两种独立数据路径(如下左图)会导致面积和功耗翻倍。而选择性扩展根据控制信号动态选择对输入数据进行零扩展(无符号)或符号扩展(有符号),统一使用单一的有符号数据路径完成计算,实现了硬件资源共享。
在这里插入图片描述

10、乘积和(POS) 表达式

规则: 利⽤ POS 表达式(即加法-乘法结构,“(a+b)*c")。
理由: 综合可以通过使⽤ 进位保存乘法器(例如, 允许⼀个输⼊为进位保存格式的乘法器) 来有效地实现 POS 表达式, ⽽⽆需在乘法之前执⾏进位传播。

举例:
在这里插入图片描述

11、组件实例化

在RTL设计中,不要手动例化DesignWare算术运算IP(如Synopsys提供的专用加法器、乘法器模块),也不要用基本逻辑门(AND/OR/XOR等)手动搭建算术电路。相反,应直接用高级算术表达式(如assign z = a + b * c;)描述运算,让综合工具自动优化。

)
在这里插入图片描述

12、流水线

为了数据路径流⽔线, 将流⽔线寄存器放置在 RTL 数据路径代码的输⼊或输出处, 并使⽤ 重定时将它们移动到最佳位置(‘optimize_registers’ in Design Compiler; see “Design Compiler Reference Manual: Register
Retiming”)。 不要使⽤ DesignWare 组件实例并⼿动放置寄存器。

下面是示例脚本:
在这里插入图片描述

13、 对操作数求补

不要通过反转所有位并添加“1”来⼿动对操作数求补(求反) (例如,“a_neg=~a+1”)。 相反, 使⽤ ‘-’ 运算符(例如,“a_neg=-a")。

原因:手动取补码操作可能无法被识别为算术运算,从而限制数据路径提取并导致更差的QoR(质量结果)。算术取补的操作数可以轻松作为更大数据路径的一部分被提取。

工具支持:(部分)Design Compiler会将简单的手动取补操作(如 a_neg = ~a + 1)转换为取负/减法操作(a_neg = -a),但无法优化更复杂的情况(如下例所示)。
注意:当涉及取补和乘法运算时,通常更优的做法是在输入侧而非输出侧进行取补操作(参见下一条指南中的示例)。在简单情况下,Design Compiler会自动完成此优化。

14、特殊算术优化

有⼀些特殊的算法优化⽬ 前⽆法由数据路径综合⾃ 动执⾏, 但这些优化可能会提升 QoR。 通过对数据路径综合功能有⼀定的了解并积累⼀些算法经验, 可以找到不同的解决⽅案, 从⽽获得更好的结果。

举例:
在这里插入图片描述
第一个例子是sign控制ab的结果加不加负号,sign是1就输出
-a
b+c,否则就是a*b+c。第一种写成取反加一了,没写成sop的形式,写成(sign?$signed(2b11) : $signed(2`b01))ab+c 也可以,但是要mux,而好的QoR直接用拼接来做的。

15、并⾏常数乘法器

笔记: 如下例所⽰, 并⾏常数乘法器可以通过使⽤ 移位和加法以及共享公共常数项来实现⾯积优化。

在这里插入图片描述

上述针对⾯积(功耗) 优化的转换在 Design Compiler 中⾃动完成。 ⽆需在 RTL 代码中优化并⾏常数乘法器。

16、 公共⼦表达式共享和取消共享

不同算术表达式之间的公共⼦表达式可以共享(以改善⾯积) 或不共享(以改善时间)。

在这里插入图片描述
⼯具⽀持: (full) ⽆论 RTL 代码中是否进⾏了共享, Design Compiler 都会根据时序上下⽂⾃ 动执⾏取消共享(以优化时序) 和共享(以优化⾯积)。 因此, 这两个代码⽰例将产⽣相同的 QoR

17、四舍五⼊

笔记: 舍⼊模式的选择及其实现⽅式会影响数据路径的提取。
所有⾮对称舍⼊模式都可以通过在某些位置添加常量位来实现, 从⽽实现最佳的数据路径提取。 然⽽, 对称(⽆偏) 舍⼊模式需要访问待舍⼊操作数的各个(变量) 位, 这反过来⼜要求该操作数采⽤ ⼆进制表⽰, 因此会阻⽌提取。
在这里插入图片描述
(1 << 7)是常量,工具可将其合并到乘法器的部分积中。综合后可能生成单级乘加结构(如DSP块的MAC单元)。

在这里插入图片描述

18、避免过度饱和(Avoid Excessive Saturation)

在数据路径(Datapath)设计中,饱和操作(Saturation,即限制数据位宽以防止溢出)的使用位置和频率会直接影响电路的质量(QoR)。

  • 适度饱和可减少后续操作的位宽→更好的 QoR;
  • 可能会阻⽌数据路径提取, 因为饱和需要⼆进制转换→更差的 QoR(会将数据从进位保留格式转换为完整的二进制表示(即所有位稳定,无悬空进位),不能用CSA等来进行进位保留计算)

因此, 饱和是⼀种 QoR 权衡。 在数据路径中可以显著减少操作数宽度的某些位置进⾏饱和可能会带来好处。 然⽽, 如果操作数过多, 宽度减少幅度不⼤, 那么饱和对 QoR 的损害可能⼤于益处。
避免过度饱和在内部操作数上减少操作数宽度。 最好额外进位⼀些位, 并在最后进⾏饱和。 只有当宽度减少显著时才进⾏饱和。

在这里插入图片描述

19. 避免数据路径泄漏datapath leakage

数据路径泄漏是指内部操作数的宽度不⾜以存储运算结果, 但稍后需要完整结果的情况。 这是由于⾼位截断后进⾏后续扩展造成的。

在这里插入图片描述

  • 数据路径泄漏的类型

    • True Leakage 中间操作数位宽不足,无法覆盖所有可能的运算结果(如8位存储16位乘法的结果)。会导致仿真和硬件行为错误
    • False Leakage 中间操作数位宽足够,但工具无法验证其安全性,保守处理。会阻断数据路径优化
      所以两种都不推荐,因为综合无法区分两者
  • 存在泄漏的操作数必须为二进制形式(不能是进位保留格式),所以会中断进位保留格式的连续性,阻止工具将多个操作合并为单一数据路径块(如乘加融合)。

    • 泄漏一定发生在数据路径块(DP block)的边界。
    • 数据路径块(DP Block):综合工具将连续的算术操作(如a*b + c)识别为一个可优化的整体单元(如DSP块)。
    • 若泄漏(如截断或符号转换)发生在数据路径内部(如中间变量),会强制拆分DP Block,生成独立逻辑。
    • 泄漏会阻止与驱动操作的提取(优化)。
    • 驱动操作(Driven Operation):指生成泄漏操作数的前一级运算(如a*b是truncated = p的驱动操作)。工具无法将被截断的操作数与其驱动操作合并优化(如无法将a*b和后续+c融合为乘加)。原因:截断后的操作数已是二进制,与进位保留格式不兼容。
  • 因为符号混合造成数据路径泄露

  • 将有符号操作数转换为⽆符号操作数→操作数始终具有⾼位截断。(会把符号位去掉)

  • ⽆符号减法→操作数始终具有⾼位截断。 (因为无符号数的减法可能产生负数,但无符号数无法表示负数)

建议:

  • 避免导致⾼位截断数据路径泄漏内部结果。 确保内部操作数⾜够宽, 以容纳驱动操作的结果(也适⽤ 于假泄漏)。
  • 避免将有符号操作数转换为⽆符号操作数。
  • 对于⽆符号减法, 请确保结果操作数与数据路径的最终结果⼀样宽(即, 它后⾯没有会导致泄漏的扩展)。
    在这里插入图片描述
    上面的例子中左边因为截断把进位链打断了,所以有两次carry传播,右边只有一次。

在这里插入图片描述

Synthesis Reports

1、流程

在这里插入图片描述

2、RTL Elaboration Warnings

在这里插入图片描述
在这里插入图片描述

3、Datapath Extraction Analysis

在这里插入图片描述

4、Datapath Content Report

在这里插入图片描述

5、Resources Report

在这里插入图片描述
在这里插入图片描述

http://www.dtcms.com/a/288223.html

相关文章:

  • 【ExtendScript Toolkit CC】【PR插件开发】获取当前序列的所有剪辑片段名
  • 技术文章:PCB基板的介电强度
  • RT-Thread的概念和移植
  • 141. 环形链表
  • 智慧资产管理系统需求文档
  • Java从入门到精通!第九天, 重点!(集合(一))
  • 机器视觉为触摸屏装上“智慧之眼”,打造智能化生产!
  • 仓库源MySQL安装教程
  • aosp15上SurfaceFlinger的dump部分新特性-无Layer相关详细信息输出如何解决?
  • 【Keil5-map文件】
  • 初入了解渗透
  • 【SVM smote】MAP - Charting Student Math Misunderstandings
  • P1816 忠诚 题解
  • leetcode_53 最大子数组和
  • MySQL(145)如何升级MySQL版本?
  • 研华PCI-1285/1285E 系列------(一概述)
  • VIT速览
  • 用 Numpy 手动实现矩阵卷积运算
  • 汽车ECU控制器通信架构
  • 车载诊断架构 --- 故障码DTC严重等级定义
  • LVS部署模式NAT集群案例
  • WSL在 Windows 上使用 Linux 工具链和开发环境
  • 慕尼黑工业大学具身机器人实时环境探索!FindAnything:基于开放词汇对象中心映射的机器人任意环境认知与导航
  • FLASH:GPU 集群全连接通信的近最优极速调度
  • Keil编译文件格式转换全解析
  • 5 基于STM32单片机的绝缘检测系统设计(STM32代码编写+手机APP设计+PCB设计+Proteus仿真)
  • QT窗口(5)-对话框
  • 基于朴素贝叶斯的姓名性别预测系统
  • 如何构建未来的人-AI-环境智能教育生态系统
  • Java并发8--并发安全容器详解