我们来说说综合,通常意义上的综合指的是,将RTL风格的描述转化为逻辑网标,通俗点说,就是把你的代码转化成真实的电路,我们以EDA工具Design Compiler为例来说说如何进行综合,对于综合我推荐的资料为《Design Compiler User Guide》(synopsys)(书1),《Optimization Reference Manual》(synopsys)(书2),《高级ASIC芯片综合》(书3),《专用集成电路设计实用教程》(虞)(书4)这些资料只要你知道了名字,网上下载到还是没有什么困难的。
以上推荐的书读了之后就可以对综合有一个大体上的认识,下面同往常一样,我来进行一下抛砖引玉的事情,首先我来说说整个综合大体流程以及命令,然后在挑一挑上述推荐书籍中的难点,先有个整体的概念。
图片节选自《专用集成电路设计使用教程》,我们设计的电路是上图中中间部分(标有TO_BE_SYNTHESIZED部分),前后为整个系统的其他部分,这两个部分可能是自己设计的其他模块,只是没有在一起综合,或者干脆是团队其他人设计的模块。我们看中间部分的模块,这个模块是你设计的,在没有综合之前,根据你自己的代码就应该心里很清楚你的电路结构是什么样的(这个在前面的篇章中已经提到过),很清楚你的设计里面有哪些是N哪些是X而哪些结构是A或者S,即使设计太过复杂,也应该知道自己的设计中存在上面ANXS中的哪些类型的路径。我们假设待综合设计中同时存在上述NXAS四种类型的路径,这里可能会问,为什么仅仅对组合逻辑划定类型而不对寄存器划分类型,实际上如果像前面推荐的那样认真的学过了寄存器部分《数字电路、数字集成电路》部分就应该知道是为什么。
在这里不得不提到寄存器的建立时间(保持时间由于STA比较不重要所以接下来我们仅仅进行建立时间的分析),我们来画一个图示说明,必须满足建立时间是什么意思:
如果上图中的setup time为0.3ns,那么数据必须在时钟上升沿之前0.3ns就已经保持稳定,上图中黑色部分在时钟沿前0.3ns前已经稳定,所以其满足建立时间要求,电路可以正常工作,而红色部分将导致电路产生故障,要么采样到错误的逻辑值,要么寄存器将进入亚稳态,这里可以自己分析,因为你已经有了集成电路基础了。好我们来看右边的电路,这个电路是两个寄存器中间连接了一段组合逻辑云,其中两个寄存器有着相同的时钟,设计目标要求我们电路能够工作在1Ghz,那么可以知道中间的逻辑不能超过1ns-setuptime(这里已经忽略了时钟偏差以及寄存器延迟的复杂因素),我们来做一个数字计算,如果逻辑云的延迟为1.2ns,那么当时钟沿到达时,黄色逻辑云还没有稳定,所谓没有稳定,就是还在不停的变化,那么这个时候采样得到的可能是错误的逻辑值。从这一点就可以看出之前介绍的《数字集成电路》第七章的作用。
这里我们先来说说约束,为了简化起见,我们在接下来的论述中将忽略所有影响不大,并且比较难懂的地方,毕竟这些地方书中已经有非常详细的介绍,在这里我们忽略时钟偏差、寄存器延迟、建立时间等,因为要么这些时间因素比较小可以忽略。例如建立时间或者寄存器延迟时间,或者比较复杂而不容易说清楚,比如时钟偏差。
所谓给综合加时序约束就是说要给综合器一个要求,比如我要求某条时序路径的最大延迟不能超过5ns,那么我可以用如下命令进行约束:
set_max_delay 5 -from {路径起点} -to {路径终点}
那么综合器收到这条指令之后,它会尽它所能去综合出延迟小于5ns的电路,如果它的最终结果为1ns,那么意味着电路的时序满足要求,否则,不满足时序约束,电路不能正常工作。
下面我们结合DC具体流程来同时进行时序约束的分析:
首先我们在工作目录下面建立.synopsys_dc.setup文件,这个文件指定综合所使用的目标库,综合库,符号库以及链接库,至于这些库都代表什么,有什么作用,《User Guide》在Working with library中有详细的讲解,而一般如果你发现你的.synopsys_dc.setup已经配置好了,那么我们在工作目录下dc_shell启动DC工具,这里我们需要说一说几个开关的作用,最主要的就是这个-topo,也就是dc_shell -topo,普通的综合仅仅综合出逻辑网表而不进行布局布线,其中的连线延迟也是基于厂商的经验,这就会导致不准确,而加上-topo开关之后,综合会进行到布局布线阶段,用真实的互连延迟,而不是估计的连线延迟,所以这大大增加了精确性,但是综合时间毫无疑问也会增加,而第二个是-gui,这个开关用来打开图形界面,用design_vision进行操作,我们接下来讨论的是用命令行方式进行操作。
接下来启动DC后我们要读入所有的设计文件,可以用命令read_file -format verilog (-format ddc) xxx.v 注意read_file会根据文件的扩展名自动进行识别类型从而可以省略-format开关,而如果你的设计为带参数传递的,那么必须使用如下的命令读入文件,首先分析文件analyze -format verilog (-format ddc) xxx.v 然后在建立设计 elaborate xxx(xxx.v)的模块名,好了,现在已经读入了所有的设计文件,但是如果你仔细发现就可以看到,你最后读入的文件为current_design(当前设计),如果你指定了current_design,那么DC所有的命令都是针对这个当前设计,所以如果你指定当前设计为某个子设计(current_design xxx)注意这个xxx是模块名,(以后我们用xxx表示模块名,xxx.v表示文件名)那么接下来的所有操作都是针对这个xxx而其他模块不受影响,无论你是设置约束还是综合都是针对这个xxx自设计的,所以如果你采用自顶向下的综合策略,那么一定要指定top为current_design,这个命令current_design会显示当前设计名称,如果你想把top设置为当前设计,那么使用下面的命令current_design top,好了这个时候假设top设计已经为当前设计,那么下一步是要对这个设计加上约束,如何加约束呢?这要看你的设计是否存在ANXS中的哪些路径,当你设计完代码之后,这件事情是应该很清楚的或者说在设计代码之前就已经清楚的知道自己的设计中有哪些路径,我们先看如果我们的设计仅仅有N,也就是一段纯组合逻辑,你可以用set_max_delay 3 -from [all_inputs] -to [all_outputs]来指定从所有输入开始到所有输出的最大延迟,那么所有以输入为时序路径起点的和所有以输出节点为时序路径终点的路径都被约束为3ns,注意,DC内嵌的STA工具是以时序路径来分析的,关于这个时序路径,我推荐资料为《PrimTime Fundermental User Guide》,或者你可以通过设置虚拟时钟来进行约束,可以想象把上面的四条路径那幅图片,里面仅仅留下A而去除其他所有的路径:
上图中将用红笔划去不存在的地方,我们看到前面和后面两个寄存器之间的组合路径为M -> A -> T,所以如果你约束了时钟周期为5ns,而输入延迟(M的延迟)为2ns,同样输出延迟(T的延迟)为2ns,那么你给A留下的余地最大延迟为5-2-2=1ns,这就是对A组合逻辑路径进行了约束,要求其综合结果最大延迟不得超过1ns,如果综合结果为0.7ns,恭喜你,电路满足时序约束,否则,你可能要修改电路结构了。那么实际上这种约束方法同set_max_delay 1 -from [all_inputs] -to [all_outputs]没有什么两样,都是将其约束为最大延迟1ns,下面写出完整的虚拟时钟设置方法:
create_clock -period 5 -name VCLK (这个VCLK是你给起的名字)
set_input_delay -max 2 [all_inputs]
set_output_delay -max 2 [all_outputs]
那么如果同时具有上述四条路径呢?那么让我们来仔细看看到底是如何进行约束的,我写出几个简单的约束命令然后解释代表什么:
create_clock -period 5 -name CLK [get_ports clk] (CLK是起的名字,而clk是设计中的时钟端口)
set_input_delay -max 1 -clock CLK [remove_from_collection [all_inputs] [get_ports clk]] (remove...表示从所有的输入端口中除去clk端口之后剩下的端口)
set_output_delay -max 1 -clock CLK [all_outputs]
我们对照图中的路径来解释上述约束代表什么:
第一句是设置了时钟周期为5ns,那么这就是说X的延迟不能超过5ns这个约束已经加上了,为什么,因为它直接处于两个寄存器之间
第二句的input_delay就是指M的延迟为1ns,那么留给N的延迟余地就是5-1=4ns,这就相当于要求了N的最大延迟不能超过4ns
同理第三句是指T的延迟为1ns,这样S的延迟就被约束了,其不能超过4ns,因为S和T两者串联处于两个寄存器之间
第三句同时规定了A的约束,因为MAT同时串联处于两个寄存器之间,那么三者的延迟和不能超过5ns,那么A的延迟不能超过5-1-1=3ns
而上面分析反复提到的两个寄存器之间的延迟不能超过时钟周期的约束就是上面分析的两个寄存器之间的黄色组合逻辑不能超过时钟周期减去建立时间,那个时候是考虑了建立时间的,但是这里为简便表述忽略了建立时间,还是那句话,我仅仅是负责简化简化再简化,以便能让初学者快速掌握个大概,而细节去推荐书里自己学,里面的描述要严谨的多。
下面我们已经建立了约束,实际上这个约束是极其简单的,实际上的约束要比这个复杂的多,包括很多set_max_transition之类的设计规则约束,可能还存在多周期路径,或者在跨时钟域中涉及到的虚假路径,所有这些推荐教材中已经有了完备的介绍,值得一提的是,其余的复杂约束要求对集成电路的知识有着扎实的理解才可以,否则可能会对很多东西迷茫,比如说确定了逻辑门的输入转换时间和输出电容,就可以确定本级逻辑门的延迟和输出转换时间,这类似的东西可能比较迷惑,如果你愿意花费时间去弄清楚,钥匙就在集成电路那些教材中,因为原教材的描述并不是很通俗,但是如果你是数字前端设计人员,可以不是很着急掌握这些东西。
好了,假设我们已经约束好了设计,下面就是综合命令了,使用compile_ultra即可,如果你有license的话,就等着综合结果吧,综合完毕之后记得输入gui_start来用图形界面进行查看综合结果,里面有综合的网表图,还有柱状统计图,各种路径延迟,延迟的组成部分都十分详细,靠你自己的实践,将会越来越熟练。
DC的命令和综合脚本都是用TCL语言的基础上,结合了synopsys的一些东西而发展起来的,那么最好的方法是去简单学一学TCL,TCL入门书籍不必推荐,因为好像就一本入门书籍,而且还是只有电子版,书名我忘记了,下面来说说综合比较重要的综合策略问题。所谓综合策略就是说怎么综合,可能会说就是把一堆层次化设计扔到DC内存中,找到顶层,约束再编译就完事了,那么如果电路规模很大,那么这种方法会花费相当长的时间,甚至无法接受,那么就需要自下而上的综合策略(之前介绍的叫做自顶向下的综合策略)也就是先分别综合子模块,然后在top设置约束,如果你想综合子设计A,那么用current_design A设置当前设计为A,然后设置A的约束并且综合,之后再依次current_design其他的自设计,最后current_design top,注意这个时候如果没有glue logic(胶合逻辑)也就是自设计之间没有逻辑连接,那么在top层只需要设置约束即可,不需要再compile_ultra,所以,综合模块划分也都是不建议有胶合逻辑的。
最后我再来说说模块划分中的寄存器输出问题,假设你的设计团队遵守自己设计的模块都以寄存器输出,那么我们看看约束脚本是否简化了,或者说大大简化了?
好,如果你的模块是上面红色的部分,你把所有的输出都寄存输出了,而且你的同事也是寄存输出的,那么红色部分的约束可以简化为如下:
create_clock -period 5 -clock CLK [get_ports clk]
set_input_delay -max 0.01 -clock CLK [remove_from_collection [all_inputs] [get_ports clk]]
而且input_delay的数字就是寄存器的延迟,这部分可以从vendor提供的target_library中选择一个驱动强度比较弱的寄存器来进行,十分的方便,没有了之前的时序预算
好了,综合的问题就说到这里,希望我抛出的这块砖,可以让你更快的更容易的学习推荐资料。
下面我们来看看形式验证,说到形式验证之前就不得不说一说SVA,这个全称为SystemVerilog Assertion,其中的Assertion就是断言的意思,就是认为什么是对的,比如我设计一个电路如下,插一句,在说之前我还是推荐教材,这部分可以用命令$ cdnshelp -gui 来调出cadence帮助文档来进行学习,方法是在搜索栏搜索sva,并且以其中的Writing SVA来进行入门,但是这种入门方法不如下面这边教材,已经被翻译成中文版,可以说入门非常好用,《S》
原文地址:https://www.cnblogs.com/HIT1719292537/p/9196612.html