-----------------------摘自《FPGA软件测试与评价技术》 中国电子信息产业发展研究院 | 编著
1、一个单独的文件应该只包含一个单独的module,module名应该和文件名相同;
2、命名必须使用字母、数字以及下划线“”,且第一个字符必须是字母表中的字母;
3、不能使用Verilog-HDL(IEEE 1364)、VHDL(IEEE 1076.X)、EDIF、SDF中的关键字;
4、不能使用包含“VDD”、“VSS”、“VCC”、“GND”或“VREF”的命名(无论是大写、小写或是大小写混合);
5、不要使用字母的大小写来区分命名;
6、不要在端口名和module名的末尾使用“”(下划线),不要使用连续的“_”;
7、极性为负的逻辑信号命名时需在末尾加上标识符号“_N”;
8、不要在不同的module中使用相同的parameter名;
9、只在同一个module中使用`define语句(Verilog),当使用全局宏语句时,综合工具将不可能为每个module单独生成逻辑电路;
10、固定值不应直接连接在输出端口上。优化综合后,在上级层次中,直接连接固定值的端口将会变成未连接,且会产生多余的逻辑;
11、对于参量,需要指明其值‘b、‘h、‘d、‘o;
12、当数值大于32时,需指定位宽。若一个参量值超过32bits,且起位宽未定义,则此参数将会被编译器自动截取;
13、一般使用“CLK”或者“CK”作为时钟信号名字,“RST”或“RESET”作为复位信号名字,可在这些基本名字后加标识符;
14、尽可能使用单时钟但触发沿;
15、不要使用标准原语模块,如AND、OR或RS锁存器或寄存器;
16、不要在组合逻辑电路中使用反馈;
17、寄存器初始化时使用异步复位会更可靠,同时也会使布线阶段复位树的综合更简单;
18、寄存器除了初始化reset,不要使用异步的set/reset管脚;
19、不要在同一个reset线路中既使用异步reset又使用同步reset;
20、不要在局部module的reset中插入逻辑操作运算,用于提供reset线路的电路应该独立划分到单独的模块中;
21、除初始化reset信号外,不要在寄存器异步reset管脚上加其他信号;
22、不要讲寄存器的输出连接到其他寄存器的时钟管脚;
23、除了寄存器时钟输入管脚,不要在其他管教上输入时钟信号;
24、时钟信号不应该在黑盒、双向管脚和reset线路上;
25、为了避免亚稳态,不要在异步时钟区域放置组合逻辑电路;
26、为避免出现亚稳态,不要在第一级准备寄存器和第二级同步寄存器间插入组合逻辑电路;
27、异步时钟间第一个准备寄存器之后不应出现传输反馈回路;
28、不要使用门控时钟;
29、函数语句中的case语句要描述所有可能情况;
30、在always结构中,函数语句不能使用reset线路逻辑;
31、在函数语句中不应使用非阻塞语句;
32、函数语句中必须将所有的输入信号定义为input;
33、在RTL描述中不能使用Task语句;
34、在Task语句中不要使用时钟沿描述;
35、函数语句中的input生命的位宽应与输入变量的位宽相一致;
36、使用assign语句,应匹配左右信号的位宽;
37、在函数语句中,不要使用全局信号赋值语句;
38、若条件语句没有被完全描述,则会产生锁存器。注意:不要产生锁存器;
39、使用always结构构造组合逻辑时,所有条件表达式,赋值语句右边表达式中的信号需要在信号敏感列表定义;
40、一个always中有且只能有一个时钟时间控制语句;
41、不要在组合电路的always结构中混用阻塞赋值(=)和非阻塞赋值(<=);
42、不要在组合逻辑电路中使用非阻塞赋值语句重复赋值同一个信号;
43、不要在一个时序电路always结构中给相同的信号重复赋值;
44、对于always结构的FF,使用非阻塞赋值;
45、当多个时钟以门控时钟的方式存在时,会产生竞争现象。一个可行的方法是在D输入端赋值时插入时延值,但在异步reset赋值时不插入时延。在赋值时插入时延的目的是防止RTL仿真时出现竞争问题(在综合阶段时延量被忽略);
46、‘always’组合逻辑电路中不要使用时延量;
47、寄存器使用异步reset时,需注意异步reset信号的触发沿。若敏感信号列表中的触发沿与‘if’语句中的极性不同,则不能被大多数逻辑综合工具综合;
48、不要同时使用带一部set和reset的锁存器,大多数供应商的库中都不提供同时带异步set和reset的锁存器;
49、避免包含锁存器的组合逻辑环路。当门信号无效时,锁存器是透明的,D输入端的数据穿过锁存器到达输出端。因此,若组合逻辑环路包含锁存器,意味着它是一个异步环;
50、在一个always结构中不要描述超过一个的if或case语句,最好使用相互分离的模块来描述。描述中若使用了多个‘if’结构,会导致信号间的关系不清晰,降低了调试效率,且有可能产生不必要的优先级电路;
51、在always结构中被赋值的信号不应该在该always结构的敏感信号列表中出现。会认为此‘always’结构反复执行,没有终止;
52、组合逻辑电路中的‘if’语句必须以else结尾,避免产生锁存器;
53、减少if语句中相同的条件表达式。具有相同内容的条件表达式为每个条件表达式产生相同的比较电路。一般来说,他们会在逻辑综合时被优化,但是初始优化电路将变得极大,从而降低优化性能;
54、尽量避免无效的条件分支。无效的条件分支(分支中没有语句)会引起潜在的错误,组合逻辑会产生一个锁存器,时序逻辑可能在编写其它条件时造成错误;
55、避免case语句的重叠。如果在case语句中存在重叠,综合工具将综合一个if语句的优先级电路。但是,若case语句中不存在重叠,综合工具可以综合成一个并行的电路;
56、注意case语句的可选范围以及每一项的位宽(仅限于Verilog)
57、不要使用‘X’信号作为‘if’语句的条件表达式;
58、在‘case’语句末尾描述default项;
59、当case语句没有在default项中赋值为‘X’时,赋值‘X’的信号不能用于其他选择表达式;
60、不要在case语句的选择表达式中使用固定值;
61、不要在case语句选项中使用变量(或者变量表达式);
62、不要在case表达式选择语句中使用逻辑和算术运算符;
63、除非是简单的重复语句,否则不要使用for语句。‘for’语句会导致逻辑的层叠从而危及电路的运行;
64、for语句的初始值和条件应为常数,另外,不要在for语句主体内改变循环变量值;
65、for语句除了循环变量和常数,不要描述任何算术运算;
66、分别对reset和逻辑部分使用for循环。综合工具不支持同一个‘for’循环语句中描述带异步控制的寄存器,会导致产生非期望的电路;
67、不要使用‘X‘或’Z‘值进行比较;
68、相关运算符的左右端表达式位宽应匹配;
69、赋值语句的右端位宽应大于等于左端位宽;
70、为常数指定基数格式(‘d,‘b,‘h,‘o);
71、为条件语句中的常数指定位宽(仅适用于Verilog);
72、不要使用除reg、wire和integer外的数据类型;
73、将一个整数赋值给reg和wire型时注意位宽;
74、不要为整数赋负值。当给一个大于32bit的变量赋值时,即使整数的最高比特位为负值,变量的最高位的值也会根据使用工具的不同而不同,有可能会变成正值;
75、不要给定义为reg和wire型的型号赋负值。负值应看作有符号变量,但某些逻辑综合工具会产生错误的电路;
76、在赋值语句中不要使用条件操作符来描述算术运算符(将不会进行资源共享);
77、运算结果赋值信号需考虑到进位后的位宽;
78、有符号数运算时,赋值语句目标信号的位宽应与每一个自变量相匹配。符号位应该扩展至最高位,位宽应该相同;
79、语句中不应同时使用有符号运算和无符号运算;
80、不要在RTL描述中使用大型的乘法器,而应该通过逻辑运算来描述乘法器内容或者使用厂家提供的core;
81、不要对输入信号赋值;
82、不要引用输出信号;
83、不要在非阻塞语句前使用延迟。有可能不是上一个仿真周期的值;
84、在RTL设计中不要使用多个顶层;
85、每一个module均需有输出。除非是testbench,一个module应该有输出端口。没有输出端口的RTL会在多个不同设计模块互联时引起混淆;
86、在always模块内位case语句加入default分支;