从大学年代第一次触摸FPGA至今已有10多年的时刻。至今记住最初第一次在EDA试验渠道上完结数字秒表,抢答器,密码锁等试验时,那个振奋劲。其时因为没有触摸到HDL硬件描绘言语,规划都是在MAX+plus II原理图环境下用74系列逻辑器材树立起来的。后来读研究生,作业陆陆续续也用过Quartus II,Foundation,ISE,Libero,并且学习了verilogHDL言语,学习的进程中也渐渐领会到verilog的妙用,本来一小段言语就能完结杂乱的原理图规划,并且言语的移植性可操作性比原理图规划强许多。
作业过的朋友必定知道,公司里是很着重规范的,特别是关于大的规划(不管软件仍是硬件),不依照规范走简直是不行完结的。逻辑规划也是这样:假如不按规范做的话,过一个月后调试时发现有错,回头再看自己写的代码,估量许多信号功用都忘了,更不要说检错了;假如一个项目做了一半一个人走了,接班的估量得从头开端规划;假如需求在本来的版别基础上添加新功用,很或许也得从头来过,很难做到规划的可重用性。在逻辑方面,我觉得比较重要的规范有这些:
1.规划有必要文档化。要将规划思路,具体完结等写入文档,然后经过严厉评定通往后才干进行下一步的作业。这样做乍看起来很花时刻,可是从整个项目进程来看,必定要比一上来就写代码要节省时刻,且这种做法能够使项目处于可控、可完结的状况。
2.代码规范。
假如在另一个规划中的时钟是40ns,复位周期不变,咱们只需对CLK_PERIOD进行从头例化就行了,然后使得代码愈加易于重用。 b.信号命名要规范化。
1) 信号名一概小写,参数用大写。
2) 关于低电平有用的信号结束要用_n符号,如rst_n。
3) 端口信号摆放要一致,一个信号只占一行,最好按输入输出及从哪个模块来到哪个模块去的联系摆放,这样在后期仿真验证找错时后 便利许多。
4) 一个模块尽量只用一个时钟,这儿的一个模块是指一个module或许是一个entity。在多时钟域的规划中触及到跨时钟域的规划中最好有专门一个模块做时钟域的阻隔。这样做能够让归纳器归纳出更优的成果。
5) 尽量在底层模块上做逻辑,在高层尽量做例化,顶层模块只能做例化,制止呈现任何胶连逻辑(glue logic),哪怕仅仅是对某个信号取反。理由同上。
6) 在FPGA的规划上制止用纯组合逻辑发生latch,带D触发器的latch的是答应的,比方装备寄存器便是这种类型。
7) 一般来说,进入FPGA的信号有必要先同步,以进步体系作业频率(板级)。
8) 一切模块的输出都要寄存器化,以进步作业频率,这对规划做到时序收敛也是极有优点的。
9) 除非是低功耗规划,不然不要用门控时钟–这会添加规划的不稳定性,在要用到门控时钟的当地,也要将门控信号用时钟的下降沿 打一拍再输出与时钟相与。
10)制止用计数器分频后的信号做其它模块的时钟,而要用改成时钟使能的方法,不然这种时钟满天飞的方法对规划的可靠性极为晦气,也大大添加了静态时序剖析的杂乱性。如FPGA的输入时钟是25M的,现在体系内部要经过RS232与PC通讯,要以rs232_1xclk的速率发送数据。
时序是规划出来的
我的boss有在华为及峻龙作业的布景,天然就给咱们讲了一些华为及altera做逻辑的一些东西,而咱们的项目规范,也根本上是按华为的那一套去做。在作业这几个月中,给我感受最深的是华为的那句话:时序是规划出来的,不是仿出来的,更不是湊出来的。在咱们公司,每一个项目都有很严厉的评定,只需评定经过了,才干做下一步的作业。以做逻辑为例,并不是一上来就开端写代码,而是要先写整体规划计划和逻辑具体规划计划,要等这些计划评定经过,以为可行了,才干进行编码,一般来说这部分作业所占的时刻要远大于编码的时刻。
整体计划首要是触及模块区分,一级模块和二级模块的接口信号和时序(咱们要求把接口信号的时序波形描绘出来)以及将来怎样测验规划。在这一级计划中,要确保在往后的规划中时序要收敛到一级模块(最终是在二级模块中)。什么意思呢?咱们在做具体规划的时分,关于一些信号的时序必定会做一些调整的,可是这种时序的调整最多只能涉及到本一级模块,而不能影响到整个规划。记住曾经在校园做规划的时分,因为不懂得规划时序,常常因为有一处信号的时序不满意,成果不得不将其它模块信号的时序也改一下,搞得人很抑郁。
在逻辑具体规划计划这一级的时分,咱们现已将各级模块的接口时序都规划出来了,各级模块内部是怎样完结的也根本上确认下来了。因为做到这一点,在编码的时分天然就很快了,最重要的是这样做后能够让规划会一向处于可控的状况,不会因为某一处的过错引起整个规划从头进行。
怎样进步电路作业频率
关于规划者来说,咱们当然期望咱们规划的电路的作业频率(在这儿如无特别阐明,作业频率指FPGA片内的作业频率)尽量高。咱们也常常传闻用资源换速度,用流水的方法能够进步作业频率,这确实是一个很重要的方法,今日我想进一步去剖析该怎样进步电路的作业频率。
咱们先来剖析下是什么影响了电路的作业频率。
咱们电路的作业频率首要与寄存器到寄存器之间的信号传达时延及clock skew有关。在FPGA内部假如时钟走长线的话,clock skew很小,根本上能够疏忽, 在这儿为了简略起见,咱们只考虑信号的传达时延的要素。信号的传达时延包含寄存器的开关时延、走线时延、经过组合逻辑的时延(这样区分或许不是很精确,不过对剖析问题来说应该是没有能够的),要进步电路的作业频率,咱们就要在这三个时延中做文章,使其尽或许的小。咱们先来看开关时延,这个时延是由器材物理特性决议的,咱们没有方法去改动,所以咱们只能经过改动走线方法和削减组合逻辑的方法来进步作业频率。
1.经过改动走线的方法削减时延。
以 Altera的器材为例,咱们在quartus里边的timing closure floorplan 能够看到有许多条条块块,咱们能够将条条块块按行和按列分,每一个条块代表1个LAB,每个LAB里有8个或许是10个LE。它们的走线时延的联系如下:同一个LAB中(最快) 同列或许同行 不同行且不同列。
咱们经过给归纳器加恰当的束缚(不行贪心,一般以加5%裕量较为适宜,比方电路作业在100Mhz,则加束缚加到105Mhz就能够了,贪心作用反而欠好,且极大添加归纳时刻)能够将相关的逻辑在布线时尽量布的接近一点,然后削减走线的时延。(注:束缚的完结不完满是经过改善布局布线方法去进步作业频率,还有其它的改善方法)
2.经过削减组合逻辑的削减时延。
上面咱们讲了能够经过加束缚来进步作业频率,可是咱们在做规划之初可万万不行将进步作业频率的美好愿望寄托在加束缚上,咱们要经过合理的规划去防止呈现大的组合逻辑,然后进步电路的作业频率,这才干增强规划的可移植性,才干够使得咱们的规划在移植到另一平等速度等级的芯片时还能运用。
咱们知道,现在大部分FPGA都根据4输入LUT的,假如一个输出对应的判别条件大于四输入的话就要由多个LUT级联才干完结,这样就引进一级组合逻辑时延,咱们要削减组合逻辑,无非便是要输入条件尽或许的少,,这样就能够级联的LUT更少,然后削减了组合逻辑引起的时延。
咱们平常传闻的流水便是一种经过切开大的组合逻辑(在其间刺进一级或多级D触发器,然后使寄存器与寄存器之间的组合逻辑削减)来进步作业频率的方法。比方一个32位的计数器,该计数器的进位链很长,必然会下降作业频率,咱们能够将其分割成4位和8位的计数,每逢4位的计数器计到15后触发一次8位的计数器,这样就完结了计数器的切开,也进步了作业频率。
在状况机中,一般也要将大的计数器移到状况机外,因为计数器这东西一般是常常是大于4输入的,假如再和其它条件一同做为状况的跳变判据的话,必然会添加LUT的级联,然后增大组合逻辑。以一个6输入的计数器为例,咱们原期望当计数器计到111100后状况跳变,现在咱们将计数器放到状况机外,当计数器计到111011后发生个enable信号去触发状况跳变,这样就将组合逻辑削减了。
上面说的都是能够经过流水的方法切开组合逻辑的状况,可是有些状况下咱们是很难去切开组合逻辑的,在这些状况下咱们又该怎样做呢?
状况机便是这么一个比方,咱们不能经过往状况译码组合逻辑中加入流水。假如咱们的规划中有一个几十个状况的状况机,它的状况译码逻辑将十分之巨大,毫无疑问,这极有或许是规划中的要害途径。那咱们该怎样做呢?仍是老思路,削减组合逻辑。咱们能够对状况的输出进行剖析,对它们进行从头分类,并根据这个从头界说成一组组小状况机,经过对输入进行挑选(case句子)并去触发相应的小状况机,然后完结了将大的状况机切开成小的状况机。在ATA6的规范中(硬盘的规范),输入的指令大概有20十种,每一个指令又对应许多种状况,假如用一个大的状况机(状况套状况)去做那是不行幻想的,咱们能够经过case句子去对指令进行译码,并触发相应的状况机,这样做下来这一个模块的频率就能够跑得比较高了。
总结:进步作业频率的实质便是要削减寄存器到寄存器的时延,最有用的方法便是防止呈现大的组合逻辑,也便是要尽量去满意四输入的条件,削减LUT级联的数量。咱们能够经过加束缚、流水、切开状况的方法进步作业频率。
做逻辑的难点在于体系结构规划和仿真验证
刚去公司的时分BOSS就和我讲,做逻辑的难点不在于RTL级代码的规划,而在于体系结构规划和仿真验证方面。现在国内对可归纳的规划着重的比较多,而对体系结构规划和仿真验证方面好像还没有什么材料,这或许也从一个旁边面反映了国内现在的规划水平还比较低下吧。曾经在校园的时分,总是觉得将RTL级代码做好就行了,仿真验证仅仅方式罢了,所以对HDL的行为描绘方面的语法嗤之以鼻,对testbench也一向不愿意去学–因为觉得画波形图便利;关于体系结构规划更是一点都不懂了。到了公司触摸了些东西才发现彻底不是这样。
其实在国外,花在仿真验证上的时刻和人力大概是花在RTL级代码上的两倍,现在仿真验证才是百万门级芯片规划的要害途径。仿真验证的难点首要在于怎样建模才干彻底和精确地去验证规划的正确性(首要是进步代码掩盖),在这进程中,验证速度也是很重要的。
验证说白了也便是怎样发生满足掩盖率的鼓励源,然后怎样去检测过错。我个人以为,在仿真验证中,最根本便是要做到验证的自动化。这也是为什么咱们要写testbench的原因。在我现在的一个规划中,每次跑仿真都要一个小时左右(这其实算小规划)因为画波形图无法做到验证自动化,假如用经过画波形图来仿真的话,一是画波形会画死(特别是关于算法杂乱的、输入呈计算散布的规划),二是看波形图要看死,三是检错率简直为零。那么怎样做到自动化呢?我个人的水平还很有限,只能简略地谈下BFM(bus function model,总线功用模型)。
以做一个MAC的core为例(背板是PCI总线),那么咱们需求一个MAC_BFM和PCI_BFM及PCI_BM(PCI behavior model)。MAC_BFM的首要功用是发生以太网帧(鼓励源),随机的长度和帧头,内容也是随机的,在发送的一起也将其仿制一份到PCI_BM中;PCI_BFM的功用则是仿PCI总线的行为,比方被测收到了一个正确帧后会向PCI总线发送一个恳求,PCI_BFM则会去呼应它,并将数据收进来;PCI_BM的首要功用是将MAC_BFM发送出来的东西与PCI_BFM接纳到的东西做比较,因为它具有了MAC_BFM的发送信息和PCI_BFM的接纳信息,只需规划合理,它总是能够自动地、彻底地去测验被测是否作业正常,然后完结自动检测。 华为在仿真验证方面估量在国内来说是做的比较好的,他们已树立起了比较好的验证渠道,大部分与通讯有关的BFM都做好了,听我朋友说,现在他们只需求将被测放在测验渠道中,并装备好参数,就能够自动地检测被测功用的正确与否。
在功用仿真做完后,因为咱们做在是FPGA的规划,在规划时现已根本确保RTL级代码在归纳成果和功用仿真成果的一致性,只需归纳布局布线后的静态时序陈述没有违背时序束缚的正告,就能够下到板子上去调试了。事实上,在华为中兴,他们做FPGA的规划时也是不做时序仿真的,因为做时序仿真很花时刻,且作用也不见得比看静态时序剖析陈述好。
当然了,假如是AS%&&&&&%的规划话,它们的仿真验证的作业量要大一些,在触及到多时钟域的规划时,一般仍是做后仿的。不过在做后仿之前,也一般会先用方式验证东西和经过静态时序分序陈述去检查有没有违背规划要求的当地,这样做了之后,后仿的作业量能够小许多。
在HDL言语方面,国内言语许多人都在争辩VHDL和verilog哪个好,其实我个人以为这并没有多大的含义,外面的大公司根本上都是用verilog在做RTL级的代码,所以仍是主张我们尽量学verilog。在仿真方面,因为VHDL在行为级建模方面弱于verilog,用VHDL做仿真模型的很少,当然也不是说verilog就好,其实verilog在杂乱的行为级建模方面的才干也是有限的,比方现在它还不支持数组。在一些杂乱的算法规划中,需求高档言语做笼统才干描绘出行为级模型。在国外,仿真建模许多都是用System C和E言语,用verilog的都算是很落后的了,国内华为的验证渠道好像是用System C写。
在体系结构规划方面,因为我做的规划还不够大,还谈不上什么经历,仅仅觉得有必要要具有一些计算机体系结构的知识才行。区分的首要根据是功用,之后是挑选适宜的,总线结构、存储结构和处理器架构,经过体系结构区分要使各部分功用模块明晰,易于完结。这一部分我想过段时刻有一点领会了再和我们共享,就先不误导我们了。
最终简略说一下领会吧,归结起来就多实践、多考虑、多问。实践出真知,看100遍他人的计划不如自己去实践一下。实践的动力一方面来自爱好,一方面来自压力,我个人觉得后者更重要。有需求会简单构成压力,也便是说最好能在实践的项目开发中训练,而不是为了学习而学习。在实践的进程中要多考虑,多想想问题呈现的原因,问题处理后要多问几个为什么,这也是经历堆集的进程,假如有写项目日志的习气更好,把问题及原因、处理的方法都写进去。最终还要多问,遇到问题思索后还得不到处理就要问了,究竟个人的力气是有限的,问同学搭档,问搜索引擎,问网友,都能够,一篇文章、朋友们的指点都或许协助自己快速处理问题。