欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

FPGA-coding style

程序员文章站 2022-07-04 15:04:06
...

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

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语句定义常数或参数。

相关标签: FPGA