微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > FPGA,CPLD和ASIC > 关于verilog coding style对逻辑综合结果的影响之讨论及如何更好地写verilog

关于verilog coding style对逻辑综合结果的影响之讨论及如何更好地写verilog

时间:10-02 整理:3721RD 点击:

最近看了一些关于verilog coding style的文章,产生了一些疑问,还请论坛里的大牛指点一下。简而言之,我的疑问就是verilog应该怎么写,才能将电路描述的更准确,综合以后产生的电路更合理?
我先把我看到的一些文章里的想法说一说,供大家讨论。如果论坛里的大牛能结合语言和工具将这个问题深入浅出地阐述一下,那就再好不过了。在此,小弟先谢过了!
1. Partition the design into small functional blocks, and use a behavioural style for each block. Avoid gate level descriptions except for critical parts of the design.------"The Veriolg Golden Reference Guide", DOULOS, Version 1.0, August 1996.
这句话的字面意思是:把系统按照功能划分成小的子模块,每个子模块用行为级描述,除了关键部分外,避免使用门级描述。为什么避免用门级描述?我的理解是,门级描述已经将电路的结构细化到各种逻辑门(如与非,或非,反相器等),不利于综合工具的进一步优化。更直白地来讲,门级描述对于综合工具来讲就是“所见即所得”,这降低了综合工具在综合过程中所付出的努力(effort),但同时也关上了综合工具对电路进行优化的大门。当然,对于有特殊的设计考虑或者经过精心设计的模块,本来就不希望综合工具对电路做出任何改变,这种情况采用门级描述就恰好。
2. Where possible, register module outputs and keep the critical path in one block. Placing the registers on module out-puts also simplifies the compilation process because timing budgets for registered module outputs are not needed. Instantiating a set of pre-compiled basic building blocks can reduce the complexity of the design and the associated compile effort even for larger modules. The last point is to keep most of the logic in the leaf modules.This simplifies the compilation process because the top-level modules will need little or no compilation and constraints can more easily be propagated down the hierarchy. ------“Writing Successful RTL Descriptions in Verilog”, Mike Parkin, Sun Microsystems, Inc.
这里所说的register module outputs是指模块的输出采用reg型,还是说在模块的输出端加上register?我比较倾向于后一种,因为并不是说把输出的数据类型定义为reg型,实际的输出就一定是经过寄存的。我们知道,always语句中必须用reg型,但电平敏感的always语句实际上是被综合成组合逻辑的,而组合逻辑的输出是不经过寄存的,组合逻辑在任何时候都是输入变则输出跟着变(除了存在一些门延时和连线延时)。那么具体到写verilog,具体到一个module,register module outputs这个tip应该如何实现呢?当然,上面也提到了register module outputs的好处:如果一个module的outputs被register了,那么在综合的时候,就不用对这个module的outputs做时序分析了?这显然涉及到了综合工具的行为,希望论坛里的大牛指点迷津。上面还提到,如果一个大的module中包含一些已经综合过的基本模块,就可以降低这个module的复杂性以及对这个module综合时所花费的effort。我对pre-compiled的理解是经过综合的,即已经被综合成了门级网表。最后两句话的字面意思是把绝大多数的电路都放在最小,最基本(leaf)的模块中,这样顶层模块在综合的时候就几乎不费effort,并且综合时所设置的约束可以很容易传递到设计的底层。那么,结合前面的那个pre-compiled,我是不是可以这样理解:要把一个设计尽量分解到一些小模块,使设计层次化,大的module由一些小的module例化而成,而顶层的module又是由这些大的module例化而成。另外,这些所谓的leaf module应该被细分到什么程度呢?显然,第1条中不赞成门级描述,那么这里的leaf modules指的是不是诸如编译码器、多路选择器、加法器等基本的组合电路以及触发器、计数器、移位寄存器等基本的时序电路?
3.One goal of logic synthesis is to produce an optimal netlist that is independent of the original structure. Until this goal is achieved, controlling the structure of a logic description is one of the best ways to ensure an optimal implementation.
------“Writing Successful RTL Descriptions in Verilog”, Mike Parkin, Sun Microsystems, Inc.
第一句话好像在说综合工具能够得到一个不受verilog源代码结构影响的最佳的电路网表,但这貌似只是综合工具的一个目标而已,还没实现。所以,后一句又说,设计人员必须清楚地知道自己的代码所描述的电路是什么,这样才能确保得到一个好的设计。更直白地来说,你要告诉综合工具你写的代码是个什么电路,是decoder?还是mux?不能写一个四不像的东西让综合工具自己去判断,这样得到的电路可能逻辑上没有问题,但性能可能上不去。也就是说,一段代码必须规范、标准、干脆、利索,是组合电路就是组合电路,是时序电路就是时序电路,不要拖泥带水。但是这貌似又跟第二条中register module outputs有点儿矛盾,因为组合电路本身的输出是不register的。register组合电路的输出,那得到的个什么东西?
4.The use of structure to control the synthesis process is the main ingredient for success when writing RTL descriptions. The designer should code the RTL to reflect the desired hardware structure.
------“Writing Successful RTL Descriptions in Verilog”, Mike Parkin, Sun Microsystems, Inc.
这两句话说明了系统结构的划分对电路的重要性,设计者应该清楚代码所描述的电路结构。简单来说,如何将一个设计划分成若干个module,这对于最终的电路有重要的影响。
5.最后我说一下我自己以前写verilog的习惯。我以前习惯于把电路分解到基本的组合电路和时序电路,比如说编译码器、多路选择器、计数器、触发器等,这些基本的组合和时序电路用行为级描述。top-level是几个大module的例化,大module是按照功能划分的,然后大的module里就是这些基本电路的例化。也就是说,整个设计是三个层次的。我不知道我这样子做是否合理,因为,在这种情况下,貌似综合工具的优化功能就没有用武之地了。
个人觉得好的coding style对于数字前端设计很重要,可以规避潜在的问题,更重要的是能提高电路的性能;另外,模块的划分对于最终的电路也有很大的影响,这貌似跟综合工具对于电路边界的处理有关。对于上述的问题,我觉得很大程度上是因为对综合工具在综合过程中的行为不甚了解而导致的,希望论坛里的大牛能指点一二,不胜感激!
如果要找一个最能体现电路设计灵魂的词,应该就是tradeoff了,这是很多大牛的共识。上面的这些问题,应该也没有绝对的正确或错误,归根结底仍然是一个折中的问题,任何事情都是过犹不及。
最后,所有的这些也可以归结为一个词,那就是experience,如果有业界的大牛能谈一谈业界的经验和做法,那就真的是感激涕零了。
最后的最后,希望大家能积极地就以上问题发表意见,如果能把以上问题理的比较清楚,虽然谈不上国家幸甚,民族幸甚,最起码如我一样的小白和菜鸟,真的是幸甚了。

也是菜鸟,一起讨论,我觉得你能静下心写这么多文字去思考挺好,我也说说自己的想法
针对你的疑问:我觉得就是在写代码时要想这段代码会翻译成怎样的电路
2、3:register module outputs,这个就是你理解的那个,做代码检查时,一些组合逻辑的输出,它通常都会建议你打一拍出来,这样输出给其他模块时可以保证时序,但有时我们就是需要组合输出,所以不用打一拍,只要你能够保证不会出现时序问题就行。
那些leaf模块,比如同步电路,上升沿检查电路,最好做成小模块调用,这样方便后端做优化。比如两级dff同步电路吧,你做成一个模块,后端就会把这两个dff靠的很近保证时序,但如果你直接写在大module里,两个dff有可能隔得很远,时序就不能保证了。



    谢谢haimo的回复!关于register module outputs,如果说每一个块组合逻辑的输出端都寄存,那么多个这样的模块连起来,实际上就形成了两端是寄存器,中间是组合逻辑的结构,这其实就是流水线。而时序分析里所谓的建立保持时间,以及组合逻辑的传播延时,貌似都是根据典型的流水线结构来定义的。这也让我回想起最初接触DC的时候,如果能在电路中找到这种典型的流水线结构,那么时序约束就会比较好写,因为每一个建立保持时间的定义都很明确;相反,如果找不到这种典型的流水线结构,那么就会感觉时序约束无从下手,因为根本就找不到建立保持时间的确切含义。另外,haimo关于leaf模块的阐述,也对我很有启发:对系统模块的划分,并不是要细分到电路的最小单元,而是要细分到功能的最小单元,虽然可操作性仍不强,但这个感性的认识很重要。最后,再次感谢haimo参与讨论!

可以搜一下STARC,是东芝、松下、瑞萨、富士通几家公司合编的rtl风格教材,里面对需要怎么写、为什么要这么写、不这么写会有什么后果都说得很详细,比较靠谱。



    非常感谢orlye推荐的资料,我觉得这种大公司出的教材应该是很有权威性和实用性的,所以特地把这个资料放到论坛上,大家如有需要的话可以下下来看,或者给我个邮箱,我发给大家。http://bbs.eetop.cn/viewthread.php?tid=439090&extra=



   十分的感谢啊

小编有心了,资料先拿走学习了,赞一个!


高手啊,赞,我觉得需要整个代码设计风格的专题

thank you for your sharing,

谢谢小编的分享,小白拿去学习一下,再次感谢

受益匪浅啊



   加下我的QQ吧,我有个FPGA的问题,困扰好久了,多谢51512474

最近看了一些关于verilog coding style的文章,产生了一些疑问,还请论坛里的大牛指点一下。简而言之,我的疑问就是verilog应该怎么写,才能将电路描述的更准确,综合以后产生的电路更合理?
我先把我看到的一些文章里的想法说一说,供大家讨论。如果论坛里的大牛能结合语言和工具将这个问题深入浅出地阐述一下,那就再好不过了。在此,小弟先谢过了!
1. Partition the design into small functional blocks, and use a behavioural style for each block. Avoid gate level descriptions except for critical parts of the design.------"The Veriolg Golden Reference Guide", DOULOS, Version 1.0, August 1996.
这句话的字面意思是:把系统按照功能划分成小的子模块,每个子模块用行为级描述,除了关键部分外,避免使用门级描述。为什么避免用门级描述?我的理解是,门级描述已经将电路的结构细化到各种逻辑门(如与非,或非,反相器等),不利于综合工具的进一步优化。更直白地来讲,门级描述对于综合工具来讲就是“所见即所得”,这降低了综合工具在综合过程中所付出的努力(effort),但同时也关上了综合工具对电路进行优化的大门。当然,对于有特殊的设计考虑或者经过精心设计的模块,本来就不希望综合工具对电路做出任何改变,这种情况采用门级描述就恰好。
        避免使用Gate Level來寫critical parts.這個部份我說一下我的想法.在很久之前,電路合成軟體還不是做的很好時,你用Gate level去寫RTL Code,會干擾到電路合成的結果.但是現在的科技己經進步了,所以這個問題應該是有解決了.並不是不能用Gate level 去寫,只是是因為電路合成軟體的關係.那試想在沒有Verilog HDL 之前,電子工程師是如何開發電路呢,那個時候可是用Gate一個一個拼出來的.
2. Where possible, register module outputs and keep the critical path in one block. Placing the registers on module out-puts also simplifies the compilation process because timing budgets for registered module outputs are not needed. Instantiating a set of pre-compiled basic building blocks can reduce the complexity of the design and the associated compile effort even for larger modules. The last point is to keep most of the logic in the leaf modules.This simplifies the compilation process because the top-level modules will need little or no compilation and constraints can more easily be propagated down the hierarchy. ------“Writing Successful RTL Descriptions in Verilog”, Mike Parkin, Sun Microsystems, Inc.
这里所说的register module outputs是指模块的输出采用reg型,还是说在模块的输出端加上register?我比较倾向于后一种,因为并不是说把输出的数据类型定义为reg型,实际的输出就一定是经过寄存的。我们知道,always语句中必须用reg型,但电平敏感的always语句实际上是被综合成组合逻辑的,而组合逻辑的输出是不经过寄存的,组合逻辑在任何时候都是输入变则输出跟着变(除了存在一些门延时和连线延时)。那么具体到写verilog,具体到一个module,register module outputs这个tip应该如何实现呢?当然,上面也提到了register module outputs的好处:如果一个module的outputs被register了,那么在综合的时候,就不用对这个module的outputs做时序分析了?这显然涉及到了综合工具的行为,希望论坛里的大牛指点迷津。上面还提到,如果一个大的module中包含一些已经综合过的基本模块,就可以降低这个module的复杂性以及对这个module综合时所花费的effort。我对pre-compiled的理解是经过综合的,即已经被综合成了门级网表。最后两句话的字面意思是把绝大多数的电路都放在最小,最基本(leaf)的模块中,这样顶层模块在综合的时候就几乎不费effort,并且综合时所设置的约束可以很容易传递到设计的底层。那么,结合前面的那个pre-compiled,我是不是可以这样理解:要把一个设计尽量分解到一些小模块,使设计层次化,大的module由一些小的module例化而成,而顶层的module又是由这些大的module例化而成。另外,这些所谓的leaf module应该被细分到什么程度呢?显然,第1条中不赞成门级描述,那么这里的leaf modules指的是不是诸如编译码器、多路选择器、加法器等基本的组合电路以及触发器、计数器、移位寄存器等基本的时序电路?
現在的合成軟體己經很進步了.先把電路做pre-compile是否有必要,可以看一下你所使用的電路合成軟體的說明文件.十年前是需要這樣做會加快電路合成的速度,但是十年過去了,我想電路合成軟體演算法應該己經進步了.至於電路的output要做register處理.這個部份我說一個觀念的問題.RTL Level Code.什麼是RTL ,RTL是指Register-Transfer Level,所以當我們常在說我在寫RTL Code指的就是在寫Register-Tranfer Level層級的Code.即然是在寫RTL Code,就是你的輸出都是由Register Output.所以Module output應該是要Register的,這樣比較符合你在寫RTL Code.而電路合成軟體都是希望使用者的Module output都是有Register的.這樣合成演算法會比較單純,但是你如果硬要把Module output用wire來寫,也是可以,我相信現在的軟體應該都可以解決.在很久以前會限定每一個Module應該要多大,也是因為軟體的關係,但是現在應該這個限制都很少了.我還是建議去看一下你所使用的合成軟體的說明文件,裏面會有很多有用的東西.

3.One goal of logic synthesis is to produce an optimal netlist that is independent of the original structure. Until this goal is achieved, controlling the structure of a logic description is one of the best ways to ensure an optimal implementation.
------“Writing Successful RTL Descriptions in Verilog”, Mike Parkin, Sun Microsystems, Inc.
第一句话好像在说综合工具能够得到一个不受verilog源代码结构影响的最佳的电路网表,但这貌似只是综合工具的一个目标而已,还没实现。所以,后一句又说,设计人员必须清楚地知道自己的代码所描述的电路是什么,这样才能确保得到一个好的设计。更直白地来说,你要告诉综合工具你写的代码是个什么电路,是decoder?还是mux?不能写一个四不像的东西让综合工具自己去判断,这样得到的电路可能逻辑上没有问题,但性能可能上不去。也就是说,一段代码必须规范、标准、干脆、利索,是组合电路就是组合电路,是时序电路就是时序电路,不要拖泥带水。但是这貌似又跟第二条中register module outputs有点儿矛盾,因为组合电路本身的输出是不register的。register组合电路的输出,那得到的个什么东西?
        你所說的觀念完全正確.但是我再補充一點.我是比較極端.我都把MUX,DECODER,COUNTER的RTL Code都背起來了.雖然寫成這些電路功能的RTL Code寫法可能有千百種,但是我只背下可以讓電路合成軟體正確合成出我想要電路的coding style.所以我寫的RTL Code都是固定的,這雖然會增加Code的行數,但是這也確保了我寫出來的RTL Code經過電路合成之後,是百分之百正確變成我所想要的電路.
       我覺得你不要太拘泥於組合電路是不是有register輸出.其實組合電路也是時序電路的一部份,數位電路設計有大部份是在寫FSM(有限狀態機).在FSM中就同時有組合電路及時序電路.你可以把你的格局放到FSM上,這樣對你的Verilog Coding會有很大的幫助.
4.The use of structure to control the synthesis process is the main ingredient for success when writing RTL descriptions. The designer should code the RTL to reflect the desired hardware structure.
------“Writing Successful RTL Descriptions in Verilog”, Mike Parkin, Sun Microsystems, Inc.
这两句话说明了系统结构的划分对电路的重要性,设计者应该清楚代码所描述的电路结构。简单来说,如何将一个设计划分成若干个module,这对于最终的电路有重要的影响。
5.最后我说一下我自己以前写verilog的习惯。我以前习惯于把电路分解到基本的组合电路和时序电路,比如说编译码器、多路选择器、计数器、触发器等,这些基本的组合和时序电路用行为级描述。top-level是几个大module的例化,大module是按照功能划分的,然后大的module里就是这些基本电路的例化。也就是说,整个设计是三个层次的。我不知道我这样子做是否合理,因为,在这种情况下,貌似综合工具的优化功能就没有用武之地了。
        非也.綜合工具優化的功能並不是在這裏,而是在把你寫的RTL Code準備地轉變成Gate Level Code.其實有時候fatten mode也是一個選項.你的Module分的好的好處主要是module reuse.不然如果改天老闆要你改一個小功能,結果因為你的功能partition做的不好,需要重寫整個電路,那真的是太沒有效率了.
个人觉得好的coding style对于数字前端设计很重要,可以规避潜在的问题,更重要的是能提高电路的性能;另外,模块的划分对于最终的电路也有很大的影响,这貌似跟综合工具对于电路边界的处理有关。对于上述的问题,我觉得很大程度上是因为对综合工具在综合过程中的行为不甚了解而导致的,希望论坛里的大牛能指点一二,不胜感激!
如果要找一个最能体现电路设计灵魂的词,应该就是tradeoff了,这是很多大牛的共识。上面的这些问题,应该也没有绝对的正确或错误,归根结底仍然是一个折中的问题,任何事情都是过犹不及。
最后,所有的这些也可以归结为一个词,那就是experience,如果有业界的大牛能谈一谈业界的经验和做法,那就真的是感激涕零了。
最后的最后,希望大家能积极地就以上问题发表意见,如果能把以上问题理的比较清楚,虽然谈不上国家幸甚,民族幸甚,最起码如我一样的小白和菜鸟,真的是幸甚了。
從你的文字中表達出你太拘泥coding style了.這樣會讓你在未來做電路設計時,在寫RTL Code時,會礙手礙腳.經驗很重要沒錯,但是也要有犯錯的勇氣,及學習的肚量.建議你可以掌握幾個原則,也是你之前提到的,我幫你整理一下.
第一點:什麼是好的coding style.語意清楚的RTL Code就是好的RTL Code.人們常可以寫出語法正確的RTL Code(軟體思維),但是卻不知道自己寫的東西會讓綜合軟體會錯意.但是能讓綜合軟體看得懂(語意清楚)的RTL Code其實是很固定的(硬體思維). 回應到你文章裏所說的.设计者应该清楚代码所描述的电路结构.
第二點:讀一下綜合軟體的參考文件(reference manual).每一家EDA做出來的綜合軟體能力大不同.有時因為公司財力的關係,無法使用到最好的綜合軟體時,更應該去看看你們公司用的綜合軟體的文件,因為其中會講一些使用的限制或是建議的coding style.

感觉楼上的是位台湾同胞,看完您之回复,受益匪浅...

非常感谢你们都是分享

非常感谢你们的分享

感谢!~

来自第2.1.1
In the case of function statements, latches will not be generated even if the conditions are
not completely defined. In this case, however, it behaves like a latch during simulation,
but logic gates generated by logic synthesis tools have the result of don’t care, so that it is
uncertain whether the value takes 0 or 1. As a result this description can be very hazardous since the RTL simulation and gate simulation results will no longer match.[2]
请问这一段可以这样理解吗:function语句内部的case就算是没有default语句,综合时也不会生成锁存器,但是仿真时,由综合器生成的逻辑门有无关的状态,所以会造成前仿真和后仿真不一致的情况?

高手点拨,豁然开朗

谢谢小编


更高层次的。代码首先是易读、好理解。所以1、分Module时候端口要清晰、简练。
2、状态机最关键,和控制信号要在一个Module,控制信号通常是关键路径。
3、data path不用太担心综合问题,只要不是多时钟。
4、+/-/*这些不需要单独module,注意输入共享就可以,DC很强大了。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top