您的位置 首页 应用

FPGA研制之道(14)写在coding之前的铁律

写在coding之前的那些铁律(1)注释: 好的代码首先必须要有注释,注释至少包括文件注释,端口注释,功能语句注释。文件注释:文件注释就是一个说明文:这通常在文件的头部注释,用于描

  写在coding之前的那些铁律

  (1)注释: 好的代码首要有必要要有注释,注释至少包括文件注释,端口注释,功用句子注释。

  文件注释:文件注释便是一个阐明文:这通常在文件的头部注释,用于描绘代码为那个工程中,由谁写的,日期是多少,功用描绘,有哪些子功用,及版别修正的标明。这样不论是谁,一望而知。即便不写文档,也能知道大约。

  接口描绘:module的接口信号中,接口注释描绘模块外部接口,例如AHB接口,和SRAM接口等等。这样读代码的人即可能够判别即模块将AHB接口信号线转换成SRAM接口信号。

  功用句子注释: 内部要害逻辑,状况机某状况,读进程、写进程。

  注释的重要性,毋庸置疑,好的注释,能够进步代码的可读性,可维护性等等。总归,养成注释的好习惯,价值不大,可是收益很大。

  (2)句子:

  开端写代码是,在FPGA规划中,特别是在可归纳的模块完成中,verilog的句子是很固定的。在FPGA的规划中,不外乎时序逻辑和组合逻辑,除此之外,别无他法。关于开端功用编码来说,只需知道组合逻辑信号即可收效,时序逻辑在时钟的下一拍起效就够了。

  下面是编码的实例。

  组合逻辑:两种组合逻辑的描绘,其功用是一起的。

  assign A = B ? 1 : D ? 2 :3;

  always@(*)

  if(B)

  A = 1

  else if(D)

  A = 2;

  else

  A = 3;

  组合逻辑 假如是异步复位的话,描绘如下

  always@(posedge sys_clk or negedge rst_n)

  if(!rst_n)

  a <= 0;

  else

  a <= b;

  也便是说,在verilog的可归纳电路的编码中,只需求三种句子,分别是assign, always(*) 及时序的always(`CLOCK_EDGE clk ) 。 `CLOCK_EDGE 可所以上升沿或许下降沿。

  为什么用always@(*) 而不是always(灵敏信号列表)。“*”包括一切灵敏信号列表,假如在coding进程中,漏掉了某个灵敏信号,则会导致仿真不正确,例如本例中,灵敏变量列表中,需求B or C 可是假如漏掉一个,仿真就会在B或C有改变时,输出没有改变。导致仿真和功用不一起,可是关于归纳东西来说,功用仍是能够正常作业的,不会由于灵敏变量列表中的值未列全而不归纳某条句子。某些状况下,灵敏列表的值可能有十几个乃至更多,遗失是可能发生的工作,可是为了防止这种问题,最好选用always(*)而不必灵敏变量列表的方法,来防止仿真成果不一起的状况发生。

  (3)赋值:老话重提,堵塞与非堵塞

  许多同志喜爱研究堵塞赋值和非堵塞赋值,这两种赋值,分别在always块里边用于的堵塞“=”给组合逻辑赋值,非堵塞”<=”给时序逻辑赋值。这应该是铁律,应该在编码进程中被严厉的恪守下来。“为什么?,不这么用程序也能跑”。这句话部分是正确的,疑问永远是工程师最好的教师。

  固然,某些状况下,不严厉的履行也跑,可是在某些状况下,完成二者就不相同。

  关于下面两个例子来阐明,为什么?

 

  关于value1的描绘方法:其归纳后的如下所示

  

 

  假如从实践的编译成果上看 b和b1 及c和c1其运用堵塞赋值和非堵塞赋值终究的成果是一起的,因而,也便是说,某些状况下,二者的编译成果一起。

  

 

  而关于value2的描绘方法:其归纳后的电路图如下所示。

  

 

  而关于第二中描绘方法,堵塞赋值和非堵塞赋值的差异就显现出来了,从归纳后的图中能够看到,c1信号是b1信号的存放,而c信号和b信号为同一信号,都为a信号的存放。

  作为FPGA工程师,一项根本的才能,便是要知道代码归纳后的电路和时序,不要让其体现和你料想的不一起,“不一起”就意味着失利。便是代码的失利,也是工程的失利

  关于堵塞和非堵塞赋值差异和具体阐明来说,其能够编写一本书(如有时刻也可专题胪陈),可是对FPGA工程师,关于verilog的编码而言,则只需求依照时序逻辑用“<=”非堵塞,组合逻辑用堵塞“=”赋值即可。不要应战那些规则,企图经过言语的特性来生成特别电路的测验是不可取的,开个打趣的话,是没有出路的,要把规划的精力放在经过可用的电路来完成需求上,不要舍近求远。在数字电路规划中,咱们需求的是一个确认的国际,“所见及所得”,不要让你所想的和归纳编译东西得知道不一起。这也便是不要乱用和混用这两个赋值的原因。

  (4)一个变量一个“家”

  不要在两个always句子中同一个变量赋值。(这是有必要的)

  也尽量不要在同一个always句子中,对两个变量赋值。(这是可选的)

  假如是一组信号,其有一起的操控条件,则在同一always句子中赋值能够削减代码行数,进步可读性,除此之外,最好分隔来写。假如几个不太相关的信号在同一里边赋值,其可读性极差,在组合逻辑中,还简单发生latch。

  而前者赋值方法,归纳东西肯定会报错,这到不必很忧虑,由于能够报的过错时是最简单被发现的。俗语说:“咬人的狗不叫”,而关于FPGA规划来说“丧命的BUG,从来不报错”。

  (5)锁存

  FPGA中不要有锁存器的发生。最简单发生的是在always(*)句子中,最终必定是一切分支条件都要描绘并赋值,(必定要有最终的else)。状况机中,相同如此,不光需求有default的状况,每个状况的都要有一切的分支都要赋值。

  锁存器,是FPGA规划的大敌,由于会导致非你想要的过错功用的发生,而且导致时序剖析过错,就会发生前述的问题“所见不是所得”,而且归纳东西不会报错。

  假如你规划的电路功用,仿真正确,而实践作业不正常,有一部分的原因是生成了锁存器,假如规划很大,不简单查的话,能够翻开归纳陈述,查找“LATCH”要害词,查看是否有锁存器的发生,一句话“锁存器,必杀之”。

  时序逻辑会发生锁存器吗?当然不会,时序逻辑归纳成果必定是触发器,因而不必查看时序逻辑的分支条件。

  综上:这是写在coding之前的话,编码的首要功用应该是用牢靠的电路来描绘FPGA功用和需求,不要企图经过言语的特性来描绘功用,规划的首要精力应放在用已知的电路(组合逻辑,时序逻辑)描绘不知道功用。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/117667.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部