FPGA-coding style

当前数字电路设计越来越复杂,一一个项目需要的人越来越多,当几十号设计同事完成同一个项目时候,大家需要互相检视对方代码,如果没有一个统- -的编程规范,那么是不可想象的,大家的风格都不一-样,如果不统- -的话,后续维护、重用等会有很大的困难,即使是自己写的代码,几个月后再看也会变的很陌生,也会看不懂(您可能不相信,不过笔者和同事交流发现大家都是这样的,时间长不看就忘记了),所以编程规范的重要性显而易见。另外养成良好的编程规范,对于个人的工作习惯、思路等都有非常大的好处。可以让新人尽快融入项目中,让大家更容易看懂您的代码。
 

1 标准的文件头

 在每一个版块的开头一定要使用统一的文件头,其中包括作者名,模块名,创建日期,概要,更改记录,版权等必要信息。

// **************************************************************
// COPYRIGHT(c)2005, Hislicon Technologies Co, Ltd
// All rights reserved.
//
// IP LIB INDEX :  IP lib index just sa UTOPIA_B
// IP Name      :  the top module_name of this ip, usually, is same
//                as the small ip classified name just as UTOPIA	
// File name     :  file_name of the file just as “tx_fifo.v”
// Module name  :  module_name of this file just as “TX_FIFO”
// Full name     :  complete Emglish nme of this abbreviated
//
// Author        :  Athor/ID 
// Email         :  Author’s email
// Data          :   
// Version        :  V 1.0 
// 
//Abstract        :
// Called by       :  Father Module
// 
// Modification history
// ------------------------------------------------------------------------------------------------------
// //
// $Log$
//
// *********************************************************************

2 标准的module格式(module整体结构)

对于模块的书写采用统一的格式便于项目内部成员的理解和维护,我们用批处理建立了一个MODULE模块,其内容解释如下:

  1. 端口定义按照输入,输出,双向的顺序:
  2. 模块名、模块例化名统一,例化名前加大写U_以区分 ( 多次例化另加标识 ),三者关系:

      文件名 :xxx .v    (小写)

      模块名 :XXX   (大写)

      例化名 :U_XXX  (大写)

// *****************************
//  DEFINE MODULE PORT  //
// ******************************
//
// module  MODULE_NAME  (
                            // INPUT
                            input_port_1,
                            …
                            input_port_m, 

                            // OUTPUT
                            output_port_1,
                            …
                            output_port_m, 
                           );

// *****************************
//  DEFINE PARAMETER  //
// ******************************
parameter…

// ******************************
// DEFINE INPUT
// ******************************
input            rst_n   ;    // reset, active low .
input            clk_*   ;    // clock signal , 50M .
input  [n:0]     a_din   ;    // *****
input  [k:0]     b_din   ;    // *****

// ******************************
// DEFINE OUTPUT  //
// ******************************
output  [m:0]     a_dout   ;    // *****
output  [i:0]     b_dout   ;    // *****

// ******************************
// OUTPUT ATRRIBUTE  //
// ******************************
// REGS
reg   [m:0]     a_dout   ;     // *****
//WIRES
wire  [i:0]     b_dout   ;     // *****
    

// ******************************
// INSTSNCE MODULE   //
// ******************************
MODULE_NAME_A  U_MODULE_NAME_A(
                                         .A(A),
                                         .B(B),
                                         .C(C)
                                         ); …

// ******************************
//MAIN CODE  //
// ******************************
… …
… …
… …
// ******************************  //
  Endmodule

3 一致的排版

一致的缩排

统一的缩排取4个空格宽度

输入输出信号的宽度定义与关键字之间,信号名与宽度之间要用空格分开;所有宽度定义对所有信号名对齐。

B 一致的 begin end 书写格式

always 中,一定要用begin end 区分,格式和代码风格统一如下:

always @ (postedge clk or negedge rst_n)
begin
  if (rst_n==1’b0)
    syn_rst<= ‘DLY 1’b0;
  else
      begin
         if (a==b)
          syn_rst<= ‘DLY 1’b1;
         else
           syn_rst<= ‘DLY 1’b0;
       end
end

4 统一的书写格式

A. 括号的使用

如果一个表达式的分组情况不是很明显时,加上括号有助于理解。

例如下面的代码加上括号就清晰很多。

    if (&a==1’b1&&!flag==1’b1 || b==1’b1)               

改为:

    if ((&a==1’b1)&&(!flag==1’b1)||( b==1’b1))

B 适当的使用空格

适当地在代码的不同部分中插入空行,避免因程序拥挤不利阅读。

在表达式中插入空格,避免代码拥挤,包括:

                                                                赋值符号两边要有空格;

                                                                双目运算符两边要有空格;

                                                               单目运算符和操作数之间可没有空格,

a  <=  b;
c  <=  a  +  b;
if (a  ==  b) then ...
a  <=  ~a  &  c;

一般表达式在运算符的两侧要各留出一个空格,但定义比较长的表达式,去掉预先级高的运算符前的空格,使其与运算对象紧连在一起,可以更清晰的显示表达式结构。

C 赋值要指明比特宽度

     赋值或者条件判断时要注明比特宽度,注意表达式的位宽匹配。如:

         reg [4:0] signal_a;

错误:   1  signal_a <= 5;

              2 if(signal_a == 5)

              3 signal_a <= signal_b[3:0]+4;

正确:   1  signal_a <= 5'd5

              2 if(signal_a == 5'd5)

              3 signal_a <= {1’b0, signal_b[3:0]+5'd4

因为工具默认是32位宽,如果不注明位宽,工具检查会报warning,而且这样增加了设计的严谨性。

D 大小写和标识符

  1. 如无特别需要,模块名和信号名一律采用小写字母。
  2. 为醒目起见,常数(`define定义)/参数(parameter定义)采用大写字母。
  3. 标识符采用传统C语言的命名方法,即在单词之间以“_”分开,如:max_delay、data_size等等。
  4. 采用有意义的、能反映对象特征、作用和性质的单词命名标识符,以增强程序的可读性。
  5. 为避免标识符过于冗长,对较长单词的应当采用适当的缩写形式,如用‘buff’代替‘buffer’,‘ena’代替‘enable’,‘addr’代替‘address’等。

5 参数化的设计

为了源代码的可读性和可移植性起见,不要在程序中直接写特定数值,尽可能采用`define语句或paramater语句定义常数或参数。

猜你喜欢

转载自blog.csdn.net/qq_40893012/article/details/106670601