在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 2295|回复: 7

[资料] coding style

[复制链接]
发表于 2017-11-29 08:44:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
//****************************//copynoright(c):萌新转载的,大家还请见谅
//file name        :coding style
//data               :2017-11-29
//author            :ZzItachi
//****************************


[size=15.0000pt]一、 RTL CODE 规范


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         :  Authors email

// Data          :   

// Version        :  V 1.0

//

//Abstract        :

// Called by       :  Father Module

//

// Modification history

// ------------------------------------------------------------------------------------------------------

// //

// $Log$

//

// *********************************************************************


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

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

[size=10.5000pt]l 端口定义按照输入,输出,双向的顺序:

[size=10.5000pt]l 模块名、模块例化名统一,例化名前加大写U_以区分 ( 多次例化另加标识 ),三者关系:

文件名 xxx .v    (小写)

模块名 XXX   (大写)

例化名 U_XXX  (大写)

IP 内部所有的模块名都要加IP名或者IP名简称作前缀,如USB_CTRLUSB_TX_FIFO


// *****************************

//  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.一致的排版

A. 一致的缩排

[size=10.5000pt]l 统一的缩排取4个空格宽度

[size=10.5000pt]l 输入输出信号的宽度定义与关键字之间,信号名与宽度之间要用空格分开;所有宽度定义对所有信号名对齐,代码风格统一如下:


input   [3:0]    input_a   ;    // *****

    input           input_b   ;    // *****

       …

       output [128:0]  output_a ;

output [15:0]   output_b ;

output          output_c ;

A. 一致的 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

if else 中仅有一个语句行时,不要使用begin end; 如果有多个语句行时,begin endif ()或else ()空四个格。

格式如下:

if  (…)

else if (…)

else

********************************************************************


if  (…)

else if (…)

       begin

         …

…(

       end

else

4. 一致的信号命名风格

简洁,清晰,有效是基本的信号命名规则,详见命名规范。



全称[size=10.5000pt]

缩写[size=10.5000pt]

中文含义[size=10.5000pt]

acknowledge[size=10.5000pt]

ack[size=10.5000pt]

应答[size=10.5000pt]

adress[size=10.5000pt]

addr(ad)[size=10.5000pt]

地址[size=10.5000pt]

arbiter[size=10.5000pt]

arb[size=10.5000pt]

仲裁[size=10.5000pt]

check[size=10.5000pt]

chk[size=10.5000pt]

校验,如CRC校验[size=10.5000pt]

clock[size=10.5000pt]

clk[size=10.5000pt]

时钟[size=10.5000pt]

config[size=10.5000pt]

cfg[size=10.5000pt]

Configuration,装置[size=10.5000pt]

control[size=10.5000pt]

ctrl[size=10.5000pt]

控制[size=10.5000pt]

count[size=10.5000pt]

cnt[size=10.5000pt]

计数[size=10.5000pt]

data in[size=10.5000pt]

din(di)[size=10.5000pt]

数据输入[size=10.5000pt]

data out[size=10.5000pt]

dout(do)[size=10.5000pt]

数据输出[size=10.5000pt]

decode[size=10.5000pt]

de[size=10.5000pt]

译码[size=10.5000pt]

decrease[size=10.5000pt]

dec[size=10.5000pt]

减一[size=10.5000pt]

delay[size=10.5000pt]

dly[size=10.5000pt]


disable[size=10.5000pt]

dis[size=10.5000pt]

不使能[size=10.5000pt]

error[size=10.5000pt]

err[size=10.5000pt]

错误(指示)[size=10.5000pt]

enable[size=10.5000pt]

en[size=10.5000pt]

使能[size=10.5000pt]

frame[size=10.5000pt]

frm[size=10.5000pt]

[size=10.5000pt]帧[size=10.5000pt]

[size=10.5000pt]generate[size=10.5000pt]

gen[size=10.5000pt]

生成,如CRC生成[size=10.5000pt]

grant[size=10.5000pt]

gnt[size=10.5000pt]

申请通过[size=10.5000pt]

increase[size=10.5000pt]

inc[size=10.5000pt]

加一[size=10.5000pt]

input[size=10.5000pt]

in(i)[size=10.5000pt]


length[size=10.5000pt]

len[size=10.5000pt]

(帧、包)长[size=10.5000pt]

nmport[size=10.5000pt]

nm[size=10.5000pt]

网管相关[size=10.5000pt]

output[size=10.5000pt]

out(o)[size=10.5000pt]


packet不推荐packet[size=10.5000pt]

pkt[size=10.5000pt]

与帧相同[size=10.5000pt]

priority[size=10.5000pt]

pri[size=10.5000pt]

优先级[size=10.5000pt]

pointer[size=10.5000pt]

ptr[size=10.5000pt]

指针[size=10.5000pt]

rd enable[size=10.5000pt]

ren[size=10.5000pt]

读使能[size=10.5000pt]

read[size=10.5000pt]

rd[size=10.5000pt]

读(操作)[size=10.5000pt]

ready[size=10.5000pt]

rdy[size=10.5000pt]

应答信号或准备好[size=10.5000pt]

receive[size=10.5000pt]

rx[size=10.5000pt]

(帧数据)接收[size=10.5000pt]

request[size=10.5000pt]

req[size=10.5000pt]

(服务、仲裁)请求[size=10.5000pt]

reset[size=10.5000pt]

rst[size=10.5000pt]


segment[size=10.5000pt]

seg[size=10.5000pt]


souce[size=10.5000pt]

scr[size=10.5000pt]

源(端口)[size=10.5000pt]

ststistics[size=10.5000pt]

stat[size=10.5000pt]

统计[size=10.5000pt]

timer[size=10.5000pt]

tmr[size=10.5000pt]

定时器[size=10.5000pt]

switcher[size=10.5000pt]

sf[size=10.5000pt]

Switch fabric[size=10.5000pt]

temporary[size=10.5000pt]

tmp[size=10.5000pt]

临时[size=10.5000pt]

transmit[size=10.5000pt]

tx[size=10.5000pt]

发送(帧数据)相关[size=10.5000pt]

Valid[size=10.5000pt]

vld(v)[size=10.5000pt]

有效、校验正确[size=10.5000pt]

wr enable[size=10.5000pt]

wen[size=10.5000pt]

写使能[size=10.5000pt]

write[size=10.5000pt]

wr[size=10.5000pt]

写操作[size=10.5000pt]

a. 端口、信号、变量名的所有字母小写:函数名、宏定义、参数定义用大写

b. 使用简称、缩略词(加上列表)

c. 基于含义命名(避免以数字命名的简单做法),含义可分段(最多分三段),每一小段之间加下划线”_”,tx_data_val;命名长度一般限制在20个字符以内。

d. 低电平有效信号,加后缀”_n”,rst_n

e. 无条件寄存的寄存信号在原信号上加ff1ff2… 如原信号 data_in, 寄存一拍data_in_ff1,寄存两拍data_in_ff2

[size=10.5000pt]f. 不能用
”reg”,作为最后的后缀名,因为综合工具会给寄存器自动加上_reg, 如果命名里就用_reg作为后缀名则扰乱了网表的可读性。


5.统一的表达式书写

A. 括号的使用

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

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

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

改为:

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

B. 适当的使用空格

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


还是上面的例子:

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

改为:

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

”<=”, ”==”前后都要加空格。


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 <= 5d5

2 if(signal_a == 5d5)

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

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


6.统一的语句书写――条件判断结构书写方式

A. 条件的完整性


If else搭配使用,对于缺省的条件要写”else”;


If elsed 条件判别式要全面,比如ifa == 1’b0;


Case中的缺省条件要写”default”;

B.if  else结构:适用于复杂条件判断的语句

    但对于复杂的条件判断,使用?:如果不仔细分析条件的每一条路径,就让读代码搞不清它是到底要做什么。例如:


  C = (!Ic&&!rc)?0(Ic?rc:Ic)  //                          (?

    改为:

always @(Ic or rc)       //                          if else

begin

   if ((Ic==0)&&(rc==0))

      c = 0;

   else if (Ic==1)

      c = rc;

   else

      c = Ic;

end

即使是简单的条件判断,我们也必须使用IF-ELSE,当涉及复杂的条件判断,使用IF-ELSE结构以获得清晰的结构便于理解和维护。因此必须使用IF-ELSE

C.IF ELSE结构VSCASE结构

IF ELSE结构综合的结构可能是与或非门构成的,也可能是一组多路选择器,而case结构综合结果一般会是多路选择器,但对于可以优化的case综合工具会综合出更简单的结构。

所有对于可以写出平行结构的条件,优先写成case结构,例如地址译码等,条件之间有重复和嵌套的情况则是写成if else结构。

D. Finite State Machine

     不允许有模糊不清的状态机模式,所有的状态机必须清晰明了。

     我们要求将状态机的时序部分和组合逻辑部分分开。

     例如:


   module state4 (

clock

reset

out

);

          input         reset

          input         clock;

          output  [1:0]  out;

          parameter [1:0]  stateA=2’b00;

          parameter [1:0]  stateB=2’b01;

          parameter [1:0]  stateC=2’b10;

          parameter [1:0]  stateD=2’b11;

          reg     [1:0]   state;

          reg     [1:0]   nextstate;

reg     [1:0]   out;

always @ (posedge clock)

begin

   if (reset ==10’b0)

      state <= stateA;

   else

      state <= nextstate;

end


always @ (state)

begin

   case (state)

      stateA: begin

        nextstate = stateB;

      end

      stateB: begin

        nextstate = stateC;

      end

      stateC: begin

        nextstate = stateD;

      end

      stateD: begin

        nextstate = stateA;

      end

             endcase

           end

           always@(postdge clock or negedge reset)

           begin

              if (reset==1’b0)

                out <= 2’b0;

              else begin

                if (state==…)

                   out <= …;

                else

                   out <= …;

            end

          end

          endmodule        

7. 统一格式的always程序块的书写


A. always 中的变量的赋值方式――阻塞与非阻塞赋值

    当进行时序逻辑建模时,always块中使用非阻塞赋值――NON_BLOCKING;

    参加如下代码:

always @(posedge clk or negedge rst_n)

begin

if (rst_n == 1b0;

     myreg <= 1b0;

   else

     myreg <= DLY1b1;

end

always块中使用的NON_BLOCKING赋值时在”<=”前要加上#DLY,如上例;

当使用always语句进行组合逻辑建模时,always块中使用阻塞赋值――BLOCKING

   参见如下代码:


always @addr

       begin

          case (addr)


                 2’b00 : cs0_n=1’b0;

         2’b01 : cs0_n=1’b1;

         2’b10 : cs0_n=1’b0;

         2’b11 : cs0_n=1’b1;

         default: cs0_n=1’b1;

      endcase

end

·
如果要使用always语句同时进行时序与组合逻辑建模时,一定使用非阻塞赋值;例如:

     //组合逻辑与时序逻辑在同一个always块中


  always@(posedge clk or negedge reset_n)

     begin

        if(reset_n==1’b0)

           out<=1’b0;

        else

           begin

              case(count)

                 2’b00 : out<= `DLY in_a;

                 2’b01 : out<= `DLY in_b;

                 2’b10 : out<= `DLY in_c;

                 2’b11 : out<= `DLY in_c;

                 default: out<= `DLY in_a;

           end

end

B.always中变量赋值的唯一性

·    组合always块一定要注意敏感量列表中的触发项完整且不冗余;如果不是这样,综合的电路会与实际设计不符合,会报warning;

·    不要再多个always模块中对同一个reg型变量进行赋值;

·    更不能再同一个always中随一个变量双重赋值;

        例如:


  always@(posedge clk or posedge reset_n)

      begin

         if(reset_n==1’b0)

            out<=1’b0;

         else

            out<=   `DLY1’b1;      //out      1  0

            out<=   `DLY1’b0;

      end

·    推荐不要在一个always块里给多个变量赋值。如果将一组条件相同的变量写在一个always块中更有利于可读性的提高和功能的实现时候,可有例外情况,但请尽量多加注释,以增加可读性,并注意在组合always块中不要出现LATCH(不如对状态机的组合always块及它对条件相似的多个变量赋值);

C.always中复位的书写


复位的条件表达式及命名要和always敏感列表中的描述相统一,并且一定要使用异步复位。所有的复位必须低有效。

    例如:


   //

    always@(posedge clk ot negedge rst_n) //

    begin

        if(rst_n==1’b0)

            …

        else

            …

    end

D.always的注释


要在每一个always块之前加一段注释,增加可读性和便于调试。


//cm carry count which  …

      always@(posedge clk_xc or negedge rst_n)

      begin

          if(rst_n==1’b0)

              cm_carry_cnt<=1’b0;

          else

              cm_carry_cnt<=#`DLY1’b1;

      end

8.合理的注释


·   代码中应采用英文作详细的注释,注释量应达到代码总量的50%以上。


·   指示应该与代码一致,修改程序的时候一定要修改相应的注释;


·   注释不应重复代码已经表明的内容,而是简介的点明程序的突出特征;


·   注释应该整个一个程序的线索和关键词,它连接整个程序中分散的信息并它帮助理解程序中不能表明的部分。

9.重用化设计


层次结构与模块划分


·   层次设计的原理以简单为主――尽量避免不必要的层次;层次结构设计得好,在综合中就不需要太多的优化过程;


·   模块的划分根据层次设计来决定――模块化对于布线有很大帮助,模块化的设计中要尽量减少全局信号的使用;


·   通用的部分尽量提取出来作为一个共用模块,同时为了适应需求的更改也应提供用户定制模块入库的方式。


参数传递


·   需要传递参数的模块,在多次例化的时候统一都传递参数,不要例化同一个模块,有的传参数,有的不传。


    模块划分的技巧:

        将不同的时钟域分离开来;

        按照不同的设计目标划分成块,分块式应在数据流方向上切分;

        在同一模块中实现逻辑资源和算术资源的共享。

二.关于REVIEW


1.Review目的


         发现缺陷

         降低成本

         提高质量



2.流程


[size=10.5000pt]1. 完成第一个字模块时,请提交该模块代码,进行规范检查评审。

[size=10.5000pt]2. Coding 期间 每两星期 提交依次代码和review报告。


         Review报告主要包括内容:


·   Review工作时,review的代码模块


·   参与人


·   发现的缺陷和解决情况。


         Review建议:

[size=10.5000pt](1) 制定review计划;(2) 每次review代码不超过500行。





































ANNEX


CODE STYLE TEMPLATE


This a template of verilog code file, including file header and the main body of code in which some coding rules are demonstrated.

//********************************************************

//

//   Copyright(c)2005, Hisilicon Technologies Co., Ltd

//   All rights reserved

//

//   IP LIB INDEX    :   IP lib index just as 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 this file just as tx_fifo.v

//   Module name     :   module_name of this file just as TX_FIFO

//   Full name        :   complete English name of the abbreviated module_name

//   Author          :   Author

//   Email           :   Authors email

//   Data            :   2005/07/20

//   Version          :   current version, just this: v1.0, must same as the CVS version

//

//   Abstract         :   

//

//   Called by         :   Father module just as TX_PROC

//

//   Modification history

//   ----------------------------------------------------------------------------

// Version       Data(yyyy/mm/dd)   name

// Description

//

// $Log$

//

//*************************************************************


//*******************

//DEFINE(s)

//*******************

//`define UDLY 1    //Unit delay, for non-blocking assignments in sequential logic


//*******************

//DEFINE MODULE PORT

//*******************

module MODULE_NAME(

                   //INPUT

                    rest_n         ,

                    clk_*          ,

                    a_din          ,

                    b_din          ,


                   //OUTPUT

                    a_dout         ,

                    b_dout


                        );


//*******************

//DEFINE PARAMETER

//*******************

//Parameter(s)


//*******************

//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 ATTRIBUTE

//********************

//REGS

reg   [m:0]     a_dout     ;    //*****


//WIRES

wire  [i:0]      b_dout     ;    //*****


//*********************

//INNER SIGNAL DECLARATION

//*********************

//REGS

reg   [3:0]       counter     ;    //*****


//WIRES

wire  [7:0]       temp1      ;    //*****


//*********************

//INSTANTCE MODULE

//*********************


//**************************************************************

//instance of module MODULE_NAME_A filename:module_name_a.v

//**************************************************************

MODULE_NAME_A  U_MUDULE_NAME_A(

                  .A               (A              ),

                  .B               (B              ),

                  .C               (C              )

                   );


//*********************

//MAIN CORE

//*********************


//Sequential logic style

always@(posedge clk_* or negedge rest_n)

begin : SEQ_BLOCK_NAME

    if (rst_n==1b0)

        counter<=4b0;

    else

        begin

            if (expression)

                counter <= #`DLY siginal_b;

            else;

        end

end // SEQ_BLOCK_NAME


//Combinational logic style

always@(signal_a or signal_b)

begin:COM_BLOCK-NAME

    case (expression)

        item1    :begin

                     signal_c=*****;

                  end

        item2    : //statement;

        default   ://statement;

    endcase

end // COM_BLOCK_NAME


//*********************

endmodule



    MACRO DEFINE TEMPLATE

//********************************************************

//

//   Copyright(c)2005, Hisilicon Technologies Co., Ltd

//   All rights reserved

//

//   IP LIB INDEX    :   IP lib index just as 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        :   macro.v

//   Module name     :   

//   Full name        :   complete English name of the abbreviated module_name

//   Author          :   Author

//   Email           :   Authors email

//   Data            :   2005/07/20

//   Version          :   current version, just this: v1.0, must same as the CVS version

//

//   Abstract         :   

//

//   Called by         :   Father module .

//

//   Modification history

//   ----------------------------------------------------------------------------

// Version       Data(yyyy/mm/dd)   name

// Description

//

// $Log$

//

//*************************************************************


//*******************

//DEFINE(s)

//*******************

`define UDLY               1    //Unit delay, for non_blocking assignments in sequential logic

`define DATA_WIDTH       32   //AHB data width

`define ADDR_WIDTH       32   //AHB address width



发表于 2017-12-16 20:59:38 | 显示全部楼层
顶一个
发表于 2017-12-18 14:48:16 | 显示全部楼层
回复 1# 244603253


   顶一个
发表于 2017-12-22 16:36:07 | 显示全部楼层
Great, thanks!
发表于 2017-12-23 16:10:19 | 显示全部楼层
如果有对应的pdf文档作为附件就更好了
发表于 2017-12-26 10:30:51 | 显示全部楼层
很好的资料,谢谢
发表于 2017-12-26 14:49:37 | 显示全部楼层
回复 1# 244603253


   thank you.
发表于 2018-1-4 16:36:23 | 显示全部楼层
支持一下
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

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

×

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

GMT+8, 2024-4-20 07:04 , Processed in 0.037070 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表