|
良好的verilog HDL代码编写风格
良好的代码编写风格可以满足信、达、雅的要求。在满足功能和性能目标的前提下,增强代码的可读性、可移植性,首要的工作是在项目开发之前为整个设计团队建立一个命名约定和缩略语清单,以文档的形式记录下来,并要求每位设计人员在代码编写过程都要严格遵守。良好代码编写风格的通则概括如下:
对所有的信号名、变量名和端口名、都用小写,这样做是为了和业界的习惯保持一致;对常量名和用户定义的类型用大写。
使用有意义的信号名、端口名、函数名和参数名。例如模块端口名用a2b_data、a2c_ctrl,而不是直接用data1、ctrl1等。
信号名长度不要太长。对于超过28个字符的信号名,有些EDA工具不能够识别,再者太长的信号名也不容易记忆。因此,在描述清楚的前提下,尽可能采用较短的信号命名。
对于时钟信号使用clk作为信号名,如果设计中存在多个时钟,使用clk作为时钟信号的前缀,如clk1、clk2、clk_interace等。
对来处同一驱动源的信号在不同的子模块中采用相同的名字这要求在芯片总体设计时就定义好顶层子模块间连线的名字,端口和连接端口的信号尽可能采用相同的名字。
对于低电平有效的信号,应该以一个下划线跟一个小字母b或n表示(a2b_req_n、a2b_req_b)。注意在同一个设计中要使用同一个小写字母表示低电平有效。
对于复位信号使用rst作为信号名,如果复位信号是低电平有效,建议使用rst_n。
当描述多比特总路线时,使用一致的定顺序,对于verilog建议采用bus_signal[x:0]的表示。
尽量遵守业界已经习惯的一些约定。如*_r表示寄存器输出,*_a表示异步信号,*_pn表示多周期路径第n个周期使用的信号, *_nxt表示锁存前的信号,*_z表示三态信号等。
在源文件、批处理文件的开始应该包含一个文件头,文件头一般包含的内容如下例所示:文件名作者,模块的实现功能概述和关键特性描述,文件创建和修改的记录,包括修改时间,修改的内容等。
文件头内容示例:
//File : Dwpci_core.v
//Autour : Jeff Hackett
//Date : 09/17/96
//version : 1.0
//Abstrace : This file realized the PCI 2.1 Macrocell core
// module.The core module has the interface
// with config、initiator and target top-level
// modules
//Modification History:
// Date By Version Change Description
// 9/17/96 JDH 1.0 Original
// 11/13/96 SKC 1.1 Change ism_ad_en_ffd_n
and tsm_data_ffd_n
使用适当的注释所有的always进程、函数、端口含义、信号含义、变量含义或信号组。变量组的意义等。注释的代码附近,要求简明扼要,只要足够说明设计意图即可,避免过于复杂。
每一行语句独立成行。尽管VHDL和Verilog都允许一行可以写多个语句,但是每个语句独立成行可以提高代码的可读性和可维护性。同时保持每行小于或等于72个字符,这样做都是为了提高代码的可读性。
建议采用缩进提高续行和嵌套语句的可读性。缩进一般采用两个空格,如果空格太多则在深层嵌套时限制行长。同时缩进避免使用TAB键,这样可以避免不同的机器TAB键的设置不同限制代码的可移植能力。
在RTL源码的设计中任何元素包括端口、信号变量函数、任务、模块等的命名都不能取Verilog和VHDL语言的保留字。
在进行模块的端口申明时,每行只申明一个端口,并建议采用以下顺序:输入信号的clk、rst、enables other control signals、data and address signals。然后再申明输出信号的clk、rst、enables other control signals、data signals。
在例化模块时,使用名字显式映射而不要采用位置相关的映射,这样可以提高代码的可读性和方便debug连线错误。
如果同一段代码要重复多次,尽可能使用函数,如果有可能,可以将函数通用化,以使得它可以复用。注意,内部函数定义一般要添加注释,这样可以提高代码的可读性。
尽可能使用循环语句和寄存器组来提高源代码的可读性,这样可以有效地减少代码行数。
对一些重要的always语句块定义一个有意义的标号,这样有助于调试。注意标号名不要与信号名、变量名重复。
代码编写时的数据类型只使用IEEE定义的标准类型,在VHDL语言中,设计者可以定义新的类型和子类型,但是所有这些都必须基于IEEE的标准。例如,使用std_logic而不使用std_ulogic,使用std_logic_vector而不要使用std_ulogic_vector,不要使用bit或bit_bector,许多仿真器没有为这种类型提供内部的数学函模型。总之,在设计中要尽可能少地定义子类型,使用太多的子类型会使得代码难于理解。
在设计中不要直接使用数字,作为例外,可以使用0和1。建议采用参数定义代替直接的数字。同时,在定义常量时,如果一个常量依赖于另一个常量,建议在定义该常量时用表达式表示出这种关系。
不要在源代码中使用嵌入式的dc_shell综合命令。这是因为其他的综合工具并不认得这些隐含命令,从而导致错误的或较差的综合结果。即使使用Design Compiler,当综合策略改变时,嵌入式的综合命令也不如放到批处理综合文件中易于维护。这个规则有一个例外的综合命令,即编译开关的打开和关闭可以嵌入到代码中。
在设计中避免实例化具体的门级电路。门级电路可读性差,且难于理解和维护,如果使用特定工艺的门电路,设计将变得不可移植。如果必须实例化门电路,我们建议采用独立于工艺的门电路,如SYNOPSYS公司提供的GTECH库包含了高质量的常用的门级电路。
避免冗长的逻辑和表达式。如z=a*c+a*d+b*c+b*d应该改写为z=(a+b)*(c+d).
避免采用内部三态电路,建议用多路选择电路代替内部三态电路。 |
|