设计逻辑芯片是个大工程,设计师描述芯片内部逻辑的方法是一种叫做HDL(硬件描述语言)的语言,工业界目前广泛使用Verilog和VHDL
正如软件中,同一种编程语言在描述同一逻辑功能时采用不同的写法会在可读性、性能等方面存在差别,在硬件中,同样是Verlog语言采用不同编码风格设计的同颗芯片在各方面指标上都会存在差距
下面让我们从Verlog的编码风格出发,探讨上述问题延申出来的两种派别
中立派 vs. 传统派
数字电路总体而言是在描述寄存器之间的传递关系(即RTL),至于传递关系的描述方式可以分为两种:纯粹地用门电路描述电路,以及从行为建模上描述电路
前者没什么好说的,只是单纯的用与或非等基础门电路去描述电路,这种方式在Verilog中的体现就是仅用& | ~
等逻辑运算符,相应的综合器就只会将其综合成对应的门电路。用这种方式描述电路会强制设计者在描述之前就做到心中有电路图,有点类似数电实验时先画好了电路图再用一个个门搭好电路
后者则可以认为是在门电路之上对于数字逻辑抽象了一个层级,体现到代码上就是不再只是用逻辑运算符,还可以使用if else
、case
等更高级的语法来描述逻辑(当然相比如今的高级编程语言,Verilog的语法相当的朴素),这种方式虽然便利的设计者,但综合器的最终目的是将代码综合为门电路形式的网表文件,这就意味着要将高层次的行为“翻译”成低层次的门电路,而“翻译”就代表可能出错,引用南京大学《数字逻辑与计算机组成 课程实验》中的话:
Verilog一开始并不是为了设计可综合电路而提出的,它的本质是一门基于事件队列模型的电路建模语言。因此,行为建模很容易会让初学者偏离描述电路的初衷: 开发者需要看着电路图,心里想象电路的行为,然后转化成事件队列模型的思考方式,最后再用行为建模方式来描述电路的行为,综合器再来根据这样的描述推导出相应的电路。从这个过程来看,这不仅是没有必要的,而且还很容易引入错误:
如果开发者心里本身就已经有电路图,直接描述它是最方便的
如果开发者心里本身就已经有电路图,而开发者对行为建模方式的理解所有偏差,可能会采用了错误的描述方式,从而设计出非预期的电路
如果开发者心里没有电路图,而是期望通过行为建模方式让综合器生成某种行为的电路,这就已经偏离“描述电路”的本质了。大部分同学非常容易犯这样的错误,把行为建模当作过程式的C语言来写,尝试把任意复杂的行为描述映射到电路,最终综合器只会生成出延迟大,面积大,功耗高的低质量电路
所以,直到大家掌握“描述电路”的思维而不被行为建模误导之前,我们强烈建议初学者远离行为建模方式,仅通过数据流建模和结构化建模方式直接描述电路。例如,上文关于if和always的说法从某种程度上来说是正确的,但下面的问题可以帮助大家测试自己是否已经掌握了Verilog的本质:
在硬件描述语言中,“执行”的精确含义是什么?
是谁在执行Verilog的语句? 是电路,综合器,还是其它的?
if的条件满足,就不执行else后的语句,这里的“不执行”又是什么意思? 和描述电路有什么联系?
有“并发执行”,又有“顺序执行”,还有“任何一个变量发生变化就立即执行”,以及“在任何情况下都执行”,它们都是如何在设计出来的电路中体现的?
回到我们的讨论,所谓中立派,那就是Verilog提供了怎样的编写语法,我就可以怎样用,既可以是从门电路上描述,也可以是从行为上描述,至于会不会出问题,我选择相信综合器。相对的,保守派就是只从门电路上描述,这样至少综合器会忠诚地按照我的描述输出电路。
从这个方面来看,中立派与保守派的关系十分类似软件中的C语言与汇编语言的关系,可能更恰当的类比是:中立派是C语言,而保守派是在C语言中只使用内联汇编(毕竟他们都是Verilog),综合器就是C编译器。而软件发展历史告诉我们,C语言迅速打败了汇编语言,但在硬件中我们却无法简单断言说中立派会打败保守派,原因便出在“编译器”上
此处省略综合器的内容,涉及:数字逻辑、时序、电气特性、物理 …..
当然有时也不只是综合器的锅,作为一门相当老的语言,Verilog的语法可能已经过时了,至少在使用行为模式描述时,生成的电路在某些细节上可能与你心中想的不同:
由于在IC设计领域中,设计一个芯片时逻辑设计可能只占到时间成本的二成,其他的八成都在验证上。保守派的想法是:虽然可能带来更低的可读性与更长的设计时间,但有益于在后续验证与设计的修改,甚至对于PPA来说这样做是十分值得的
但笔者认为,综合器在未来越来越智能是必然的,大部分设计者硬编码的门电路逻辑的性能还比不上综合器根据行为描述综合出的电路性能(简单的例子,自己费劲心思手写的超前进位加法器可能还不如在Verilog直接使用+
运算符),这一点软件行业已经告诉过我们
激进派
考虑到中立派与保守派的缺点——使用高级语法导致的问题、单纯采用门电路描述的长设计周期,何不设计一门新的HDL语言?
设计周期长?那就从高级编程语言那里拿来类、函数式编程等概念来减轻重复性工作,从更高的抽象层次描述电路
更高的抽象层级存在的翻译问题?那就先将高级语言描述的电路翻译到只使用门电路方式描述的Verilog代码(当然,其中存在很多细节),再交给综合器去综合成真正的网表电路
当真正这样去做时,我们就得到了CHISEL
,一个基于Scala语言的高级HDL
此处省CHISEL的介绍和其优势...
CHISEL虽说使得数字设计的敏捷开发成为可能,但对于验证来说可能会引入更多的痛苦。还记的上面设计和验证分别占时间成本的二八成吗?CHISEL先将Scala代码编写的高层次电路翻译成Verilog,综合器再将Verilog生成为网表电路,这意味着在验证环节出问题时,设计者需要通过——Scala与Verilog中的信号、Verilog与网表中的信号,这样的两层转换才能定位出错问题的信号,从而拉长验证的时间周期,可谓“设计一时爽,反工火葬场”。
但笔者认为,如果EDA厂商能拥抱CHISEL,上述问题其实也不是大问题。总所周知,Verilog和VHDL文件在输入综合器后会被翻译成和工艺相关的RTL级中间代码(听起来像是跟LLVM一类的东西),然后才是进一步的优化和映射成网表文件,而CHISEL代码在翻译成Verilog之前也会被翻译成被称为FIRRTL的RTL级中间代码(不过这一步CHISEL可能已经做了一部分的优化工作),然后再生成Verilog文件。也就是说如果EAD厂商能使用FIRRTL作为中间代码,上述可读性的问题就会得到大幅度缓解。
关于FIRRTL之于CHISEL,可以参考: