Verilog代码风格

注意代码的可读性和移植性 养成良好的代码风格
工程文件的分类:core dev sim doc src



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


2
module:
端口定义按照输入,输出,双向的顺序:
模块名、模块例化名统一,例化名前加小写u_以区分 ( 多次例化另加标识 ),三者关系:
文件名 :xxx .v      (小写)
模块名 :xxx        (小写)
例化名 :u_xxx_xxx  (小写)
TestBench:xxx_xxx_TB (小写)
工程文件夹名:XXX_Xxx (大写)


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


3
A. 一致的缩排,统一的缩排取4个空格宽度,输入输出信号的宽度定义与关键字之间,信号名与宽度之间要用空格分开;所有宽度定义对所有信号名对齐
B.一致的 begin end 书写方式
C.if else 中仅有一个语句行时,不要使用begin end; 如果有多个语句行时,begin end和if ()或else ()空四个格。


/////////////
if  (…)

else if (…)
else 
/////////////


if  (…)

else if (…)
       begin
         …
       end
else
////////////


4
简洁,清晰,有效是基本的信号命名规则,详见命名规范。
a.端口、信号、变量名的所有字母小写:函数名、宏定义、参数定义用大写
b.使用简称、缩略词(加上列表)
c.基于含义命名(避免以数字命名的简单做法),含义可分段(最多分三段),每一小段之间加下划线”_”,如tx_data_val;命名长度一般限制在20个字符以内。
d.低电平有效信号,加后缀”_n”,如 rst_n
e.无条件寄存的寄存信号在原信号上加ff1、ff2… 如原信号 data_in, 寄存一拍data_in_ff1,寄存两拍data_in_ff2
f.不能用 ”reg”,作为最后的后缀名,因为综合工具会给寄存器自动加上_reg, 如果命名里就用_reg作为后缀名则扰乱了网表的可读性。




5
统一的表达式书写
A. 括号的使用
如果一个表达式的分组情况不是很明显时,加上括号有助于理解。
B.适当的使用空格
一般表达式在运算符的两侧要各留出一个空格,但定义比较长的表达式,去掉预先级高的运算符前的空格,使其与运算对象紧连在一起,可以更清晰的显示表达式结构。
C.赋值要指明比特宽度
赋值或者条件判断时要注明比特宽度,注意表达式的位宽匹配。


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


A. 条件的完整性
   If else搭配使用,对于缺省的条件要写”else;”;
   If elsed 条件判别式要全面,比如if(a == 1’b0);
   Case中的缺省条件要写”default”;
B.”if  else”结构:适用于复杂条件判断的语句
    但对于复杂的条件判断,使用?:如果不仔细分析条件的每一条路径,就让读代码搞不清它是到底要做什么。
    即使是简单的条件判断,我们也必须使用IF-ELSE,当涉及复杂的条件判断,使用IF-ELSE结构以获得清晰的结构便于理解和维护。因此必须使用IF-ELSE。


C.”IF ELSE”结构VS”CASE”结构
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 ==1,0’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@(posedge 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块中使用非阻塞赋值
当使用always语句进行组合逻辑建模时,always块中使用阻塞赋值
如果要使用always语句同时进行时序与组合逻辑建模时,一定使用非阻塞赋值


B.always中变量赋值的唯一性
    组合always块一定要注意敏感量列表中的触发项完整且不冗余;如果不是这样,综合的电路会与实际设计不符合,会报warning;
    不要再多个always模块中对同一个reg型变量进行赋值;
    更不能再同一个always中随一个变量双重赋值;
    推荐不要在一个always块里给多个变量赋值。如果将一组条件相同的变量写在一个always块中更有利于可读性的提高和功能的实现时候     ,可有例外情况,但请尽量多加注释,以增加可读性,并注意在组合always块中不要出现LATCH(不如对状态机的组合always块及它 对    条件相似的多个变量赋值);


C.always中复位的书写,复位的条件表达式及命名要和always敏感列表中的描述相统一,并且一定要使用异步复位。所有的复位必须低有效
D.always的注释
    要在每一个always块之前加一段注释,增加可读性和便于调试。




8
合理的注释
      代码中应采用英文作详细的注释,注释量应达到代码总量的50%以上。
       指示应该与代码一致,修改程序的时候一定要修改相应的注释;
       注释不应重复代码已经表明的内容,而是简介的点明程序的突出特征;
       注释应该整个一个程序的线索和关键词,它连接整个程序中分散的信息并它帮助理解程序中不能表明的部分。




9
重用化设计
    层次结构与模块划分
       层次设计的原理以简单为主――尽量避免不必要的层次;层次结构设计得好,在综合中就不需要太多的优化过程;
       模块的划分根据层次设计来决定――模块化对于布线有很大帮助,模块化的设计中要尽量减少全局信号的使用;
       通用的部分尽量提取出来作为一个共用模块,同时为了适应需求的更改也应提供用户定制模块入库的方式。
    参数传递
       需要传递参数的模块,在多次例化的时候统一都传递参数,不要例化同一个模块,有的传参数,有的不传。


    模块划分的技巧:
        将不同的时钟域分离开来;
        按照不同的设计目标划分成块,分块式应在数据流方向上切分;
        在同一模块中实现逻辑资源和算术资源的共享。




Review目的:
发现缺陷
        降低成本
        提高质量

你可能感兴趣的:(FPGA)