马金鑫的个人空间 https://blog.eetop.cn/1095590 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

verilog代码修养

热度 1已有 1769 次阅读| 2017-3-14 09:24 |系统分类:硬件设计

很多人觉得写verilog是一件很简单的事情,事实上也确实不难,语法上比C还少,就是always和assign倒来倒去,不是reg就是wire。如果对性能和面积要求不大的话,随便写写easy的很。

可是如果你有点追求,打算优化一半的面积,同时timing也要meet,那就有难度了。

简单从方法上讲讲,考虑点有两个地方:

(1)不是reg就是wire,可是究竟用reg还是用wire?

(2)timing是看不见的,写完综合之后才知道。

reg跟wire其实是等价的,表达同一个逻辑,定义成wire,那么就会当T实现,定义成reg就下1T实现。那么究竟用reg还是用wire呢?有人写代码不太注意这些,reg随便用,导致的结果就是设计延时很大,面积也很大。

对于timing无法meet的path,组合逻辑太大,必须用寄存器切开,这个时候寄存器的作用是使得timing meet,跑上一个较高的频率,从而提高性能。

但是对于timing本来就可以meet的path,无端的添加一个reg,不仅浪费了面积,还将整个计算过程多延了1T,性能会下降。

可是在写代码的时候,你又怎么知道timing能不能meet呢?又怎么知道组合逻辑是不是太大,需要切开呢?

你不知道,必须等到综合。而综合的时候,通常你的代码已经写完了。

综合的结果可能好,可能坏。timing可能meet,也可能不meet。

但是你不能因为不知道timing是否meet就不写代码。

所以,写代码不是一次性工作,写完了要check timing,然后修改关键路径的相关逻辑。

但是寄存器究竟使用多少,在写第一版design的时候,仍然是很重要的。

少用寄存器,综合工具会因为timing不meet,给你报path,你还有改进的机会。

多用了寄存器,综合工具可什么都不会告诉你。

所以最优设计的原则是,第一版design要尽可能少用寄存器。

多用一个reg,就多一个always赋值,多几行代码。代码一多,bug就多,trace代码得多一个双击,看代码的人多一次痛苦。

对于一个设计来说,设计规范定下来后,不考虑逻辑复用的话,组合逻辑需要多少基本就确定了,这个是确定值,就算你写得烂点,综合器上来给你一通优化,其实也差不离。但是你插了一级reg之后,将一条完整的组合逻辑一切为二,那么综合器就得分两段分别优化,最后的综合结果可能就不会那么好。

同样一个功能,不同的人来写,模块面积可以完全不一样,而这其中,设计者最需要控制的就是寄存器,因为这体现在每一行的代码中。代码中使用组合逻辑通常不需要理由,但是用寄存器是需要理由的。举个栗子,你做2个32bit数异或,异或门这种组合逻辑自然少不了,没有这个你完成不了这个运算,但是有必要使用寄存器regout计算结果吗?你需要仔细想想。

组合逻辑负责运算,但是寄存器只是负责存储,存储并不完成任何功能,为什么需要存储,你需要思考。比如为了将来使用,为了凑时序,比如防止组合逻辑loop。不管怎么样,你不能没有理由的使用寄存器。


timing坑爹的地方在于,你永远不知道你的代码能不能meet timing需求,必须等综合之后。

举个栗子,你要写一段代码给1200个1bit数相加,满足时钟400M。这1200个数肯定不可能1T之内完成加法,需要多T完成,这就涉及到path的切割。比如分成5级或者10级。问题在于你并不知道究竟是5级还是10级,或者多少级。换句话说,你不知道2.5ns能塞下多少组合逻辑运算。

那些声称自己可以看看RTL代码,来评估自己的timing是否meet,并凭感觉插入寄存器的人都是神棍。

你需要做个实验,写个小加法器,然后综合一下,确定400M的时钟可以允许1T之内做多少bit加法。

reg的一个坑爹的地方在于,它很多时候是为了解决时序不meet的问题,不得不插入的,但是reg带来的1T延时,有时候可能是灾难性的,因为假如你的逻辑已经是严丝密合的,那么突然间,某条path不得不插入一个寄存器,很有可能其他的path同步都会存在问题,你不得不改写很多地方。

这归因于reg的双重属性。它既可以解决timing不meet这种问题,也会带来延时这种搞硬件设计的人最不愿看到的副作用。因为代码写多了,有时候你自己都搞不清,哪个信号在哪1T,有时候需要画波形图辅助记忆。

对组合逻辑过大的path使用寄存器进行切割,听起来是一件很简单的事情。

但是要知道,切割path需要引入很多寄存器,这会增加gatecount。理想情况下的path切割,需要切在path最细的地方,这样插入的寄存器最少,增加的gatecount最小。

但是切割path还有另一个标准,最好是刚好切在path的中间点,这样一条path均匀分割成两半,timing最好。

流水线的频率取决于最慢的一拍,所以最好每拍的组合逻辑一般长。

悲剧的是,以上两个标准通常难以同时实现。

在组合逻辑的中间点切割path,或许timing最好,但是可能引入的寄存器非常多,gatecount很大。

要想切割在path最细的地方,又很有可能不是中间点,导致一半松一半紧,甚至不得不对紧的一半再切一次。

这需要权衡,准确的说,需要
















试。

1

点赞

刚表态过的朋友 (1 人)

发表评论 评论 (3 个评论)

回复 lwdong.chn 2017-3-18 16:31
经验多了还是有点用的!:lol

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 1

    粉丝
  • 0

    好友
  • 1

    获赞
  • 1

    评论
  • 1090

    访问数
关闭

站长推荐 上一条 /2 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-20 04:29 , Processed in 0.026121 second(s), 15 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部