0 绪论
经过了上篇文章的文档设计,我们这一章开始写代码。码代码这个问题确实是一个必备技能,任何设计不会码代码其实无法实现的。
这块儿流程上包括了两个东西。第一个码代码,第二个是一些必要的代码检查,保证代码不会出现什么歧义导致实现结果和设计意图不一致。具体语法我们就不在这一章讲了,写出来也是千篇一律,此处就简单讲讲HDL的简介,同时讲一下如何提高编码质量,供大家参考。然后简单讲一个代码写完必要的检查工序spyglass检查,这个工具可以避免大部分低级BUG。
1 码代码
1.1 HDL简介
此处的代码主要指的是HDL, hardware design language, 最主流的只有一种:Verilog,以及它的衍生品system verilog。其实还有两种语言,VHDL,属于它的时代已经过去了, 还有一种Chisel为代表的高级语言,属于它的时代似乎还没到来。所以我们这个地方重点讲讲verilog。
verilog 1983年被gateway设计,1990年gateway被candance收购。然后90年代出了第一个标准Verilog-95,定义了最原始的语法。直到现在,部分公司还是只允许使用95中的特性。2001年公布新一代标准,verilog-2001, 这一代标准中加入了generate, 多维数组等等实用的语法,现在是verilog使用最主流的标准,基本上所有的软件工具链都支持该标准,后续verilog更新了一代标准verilog2005, 不过这一代标准开始向着一个独立的方向演变,最后被合并到了systemverilog 2009。system verilog中提供了interface等等一系列面向对象的方法,已经广泛被验证支持了,但是在设计实现中只被支持了少部分特性。具体什么特性允许使用其实各个公司都有自己的看法与标准,你需要注意一下公司的编码标准。从我个人的观点来看,如果确认新特性没问题最好用新特性,减少工作量的同时还能避免代码出低级错误。
verilog代码长这样。下面实现了一个十进制的计数器。
1.2 编码质量
Verilog其实不是一个很难的语言,但是由于比较落后,编码质量很多需要人为来注意。编码质量主要就是两个方面考虑。容易出错的点以及提高后续步骤效率的点。常见容易出错的点大家应该都懂,此处简单总结了一下我觉得需要了解又容易被忽略的点,欢迎大家补充。
1.2.1 容易出错的点
·命名有意义,代码有注释。这个任何编程语言都需要注意,我把它列在第一点,这是一个码农最起码的素质。即可以避免自己出错,又可以避免接手代码的人一头雾水。我也看过不少代码没注释,命名还全是tmp1 tmp2 tmp3, 最后结局只能是自己重写。
·信号不要以Reg以及数字结尾。这个点很容易被忽略,综合时会自动给信号加上reg, 到时候就没办法区分是你写的,还是自动生成的,非要标识这是个寄存器可以用ff结尾。同时,如果多组信号不要命名为xx1,xx2, 这么做非常容易和xx[1]混淆,建议改成xxa, xxb。
·敏感列表用*,不要用具体的信号。always实现组合逻辑的时候一个敏感列表always @(列表),这个列表直接用*,让综合去自动填敏感列表,把信号写进去非常容易出错。
·少用magic numer。设计的时候好多时候需要用到参数,比如fifo的深度,这种东西尽量用参数表示出来,不同地方引用一个参数,否则非常容易出现不一致的情况。
·不要生产latch。latch指的是没有锁存的寄存,生成latch会产生毛刺,所以非必要不允许使用latch。之所以产生latch其原理是你实现了组合逻辑,但是某个周期某个变量值没有发生变化。所以牢记规律,时序逻辑值可以不变,但组合逻辑必须每个周期都赋值。具体点讲,实现组合逻的时候,case必须有default, if必须有else。
·不要生产组合逻辑环。组合逻辑环指的是同周期A变化的条件是B,而B变化依赖于A。相当于软件中的死循环。功能上就不可能正确,所以设计的时候要记得避免组合逻辑环。
·异步信号不要直接打拍。异步信号需要特别注意。在详设的时候应该就要考虑清楚怎么处理。是用多级打拍,DMUX,异步FIFO等等办法,总之,不能当做同步信号给直接处理了,否则必出错。
1.2.2 提高后续效率需要注意的点
·尽量一个模块用一个时钟域。主要是为了后端设计起来比较方便,CTS步骤(见后续文章)较容易。
·大的模块最好reg in和reg out。可以最大程度上避免后端时序上出问题。因为后端模块与模块之间不一定是按着放的,寄存器输出寄存器输入留出足够的时间余量。
·不可综合的与可综合的代码分模块。设计代码的时候有时候可能会用到SRAM cell, 或者其他硬核IP,再或者designware IP。这些东西最好单独封装模块调用。主要是为了后续代码可能会用FPGA或者emulation验证,不可综合的部件直接替换成逻辑版本。
码代码部分内容大致就是这些。其实也不必压力太大,因为代码写出来是要经过多轮工具检查的。尤其经过下面讲的spyglass检查后,想出错也没有那么容易(当然,一旦出错就是非常隐蔽的错误,可能流片后都没发现Orz)
2 Spyglass检查
码完代码,其实我们有一个非常强力的工具可以避免大部分低级错误。这个工具应该是synopsys公司出的。这个工具的GUI长这样。
最主要检查的东西应该有两个,lint检查一些常用的语法错误,CDC (Clock Domain Crossing )检查异步的处理是不是有问题。
lint会检查出所有等号左右位宽不匹配、组合逻辑环、生成了latch, 端口连接不对等等问题。基本上常见的错误都会报出来,一般它会采用宁可错杀不会放过的策略。所以此处会爆出一大堆的错误,需要逐个check一下有没有问题。当然,好多问题也是可以waive掉的,但必须每个waive都要十分确定能不能waive掉。比如计数器,一般计数器到溢出就自动回环了,这种时候lint就会爆出错,你就要检查一下是不是真的要让计数器回环。一般spygalss给你报的错分为四类,fatel, error, warning, info。其中fatel和error是一定不能有的, 有了必然不让你拿去流片,warning可以适当waive,info大多不用管。
CDC会检查异步问题。主要检查是不是所有跨时钟域的信号经过了同步,如果spyglass没检查到跨时钟域的信号没有经过多级打拍或者dmux同步会报错。再比如A时钟域的两个信号同步到了B时钟域,然后合并了,这个时候也会报错,因为这两个信号同步过去以后时序可能会发生变化,要仔细检查。再比如要同步的信号不是寄存器输出的,这种情况由于存在毛刺风险,会增大亚稳态的概率,所以也会报出来。总之, 你能想到的错误基本上都会检查出来。
本部分主要简单介绍了编码完后要用到的最重要的工具之一spyglass。实际使用的时候确实也要有一定的经验积累,什么问题可以waive掉,什么问题必须改。没必要所有问题都改掉,耗费的精力实在是太大,但真的存在风险的问题必须改掉,否则就可能搞出大事儿。。。
3 总结
本节我们讲了芯片实现码代码的部分。主要就是verilog以及后续的检查。芯片流片是一锤子买卖,所以一定要保证写的代码不出错,一方面,在本节讲的编码阶段要尽量少写bug, 另一方面,要经过缜密的验证,最大程度上拦截BUG。
审核编辑 :李倩
-
芯片
+关注
关注
454文章
50689浏览量
423022 -
vhdl
+关注
关注
30文章
817浏览量
128117 -
代码
+关注
关注
30文章
4774浏览量
68505
原文标题:一颗芯片的前世今生:设计(前端之编码)
文章出处:【微信号:IP与SoC设计,微信公众号:IP与SoC设计】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论