[Verilog4]代码编写规范

Verilog的代码编写规范

  • 对于代码的编写规范,并没有统一的标准,我也在编写的过程中逐步模仿他人的代码,不断改进自己的代码风格,以下内容只是个人的一些整理总结,不保证足够规范,我也会进行逐步的完善。

常用命名规则

  • 所有的信号(signal),变量(variable)以及模块(module)的名字都用小写字母,常量名(参数(parameter)和宏(macro))用大写字母。不要依赖大小写给标识符增加语义。
  1. 文件名
  • 对象(小写) +功能(小写).v
ddr_ctrl.v
  1. 模块名
  • 对象(大写)+ 功能(大写)
  • 如果该模块为顶层模块,则+TOP
DDR_INST
DDR_CTRL_TOP
  1. 元件例化名
  • 例化名前加大写U_以区分(多次例化可另加标识,如最简单的U1_,U2_)
U_DDR_INST
  1. 常量命名
  • 常数、DEFINE和参数必须用大写字母定义。不允许将大小写字母混用来表示词的间隔,应该用下横线来表示词间隔
  • 命名的总体规则为:对象+含义
DDR_ADDRESS = 8'b0010_1100;
  1. 信号命名
  • 所有信号的命名均采用小写
  • 命名的总体规则为:对象+功能(+极性+特性)
  • 对象为该信号归属的模块,功能为该信号的具体用处
sys_rst_n
fifo_cnt
  1. 时钟和复位信号命名
  • 对于时钟信号,使用前缀clk_*,并使用有含义的缩写构成时钟信号。
  • 对于复位信号,使用前缀rst_*,并使用有含义的缩写构成复位信号。
clk_base_61M44 , rst_lbus_n;

常用功能缩写

全称 缩写 含义
acknowledge ack 应答
adress addr(ad) 地址
check arb 仲裁
arbiter chk 校验,如CRC校验
clock clk 时钟
config cfg 配置
control ctrl 控制
count cnt 计数
data in din(di) 数据输入
data out dout(do) 数据输出
decode de 译码
decrease dec 减1
delay dly 延迟
disable dis 不使能
error err 错误(指示)
enable en 使能
frame frm
generate gen 生成,如CRC生成
grant gnt 申请通过
increase inc 加1
input in(i) 输入
length len (帧/包)长度
output out(o) 输出
priority pri 优先级
pointer ptr 指针
rd_enable ren 读使能
read rd 读操作
ready rdy 应答信号或准备好
receive rx (帧数据)接收
request req (服务/仲裁)请求
reset rst 复位
source src 源(端口)
timer tmr 定时器
transmit tx 发送相关
valid vld(v) 有效,校验正确
wr enable wen 写使能
write wr 写操作

代码书写范例

/**********************************************************************
* Copy(c) 1906, Jinan University
* All right reserved
*
* Company :
* Author :
* Email :
*
* Filename : LED_run  //文件名小写
* Description :
* Call by :
* Revision History :
*
**********************************************************************/

// DEFINE(S)
`define        //函数名、宏定义、参数定义用大写

// TOP MODULE
module MODULE_NAME(  //模块名大写,对应文件名的小写
        //端口定义按照输入,输出,双向的顺序
        //输入输出信号的宽度定义与关键字之间,信号名与宽度之间要用空格分开
        //端口、信号、变量名的所有字母小写
        //基于含义命名(避免以数字命名的简单做法),含义可分段,每一小段之间加下划线”_”
        //如 tx_data_val;命名长度一般限制在 20 个字符以内。
                        //INPUT
                        input rst_n, //复位信号,_n代表低电平有效,_p高电平有效
                        input clk_*, //*指代时钟频率,如clk_50M,代表50MHz时钟
                        input [i:0] a_din,
                        input [j:0] b_din,
                        //OUTPUT
                        output [m:0] a_dout,
                        output [n:0]  b_dout,
                        //INOUT
                        inout [p:0] a_dinout,
                        inout [q:0] b_dinout
                        );

// DEFINE PARAMETERS
parameter        //函数名、宏定义、参数定义用大写

// OUTPUT ATTRIBUTE
//REGS
reg [m:0] a_dout ; //*****  //端口、信号、变量名的所有字母小写
 //不能用 ”reg”,作为最后的后缀名, 因为综合工具会给寄存器自动加上_reg,
 //如果命名里就用_reg 作为后缀名则扰乱了网表的可读性。
//WIRES
wire [n:0] b_dout ; //*****

// INNER SIGNAL DECLARATION
//定义内部使用的REGs和WIREs
//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( //例化名在模块名前面加U_
        .A (A ),
        .B (B ),
        .C (C )
        );

//*****************************
// MAIN CORE
//*****************************
//Sequential logic style
//不允许有模糊不清的状态机模式,所有的状态机必须清晰明了。
//我们要求将状态机的时序部分和组合逻辑部分分开。
//always中,一定要用 begin end 区分,格式和代码风格统一如下
always @(posedge clk_* or negedge rest_n)
begin : SEQ_BLOCK_NAME
//统一的缩排取4个空格宽度
        //赋值或者条件判断时要注明比特宽度,注意表达式的位宽匹配
        //复位的条件表达式及命名要和 always 敏感列表中的描述相统一,并且一定要使用异步复
位。 所有的复位必须低有效。
        IF (rst_n==1'b0)
                counter<=4'b0;  // if else 中仅有一个语句行时,不要使用 begin end
        else
        begin
            //一般表达式在运算符的两侧要各留出一个空格
                if( (&a==1’b1) && ( !flag==1’b1) ||( b==1’b1) )  //如果一个表达式的分组情况不是很明显时,加上括号有助于理解。
                        counter <= #`DLY siginal_b;
                else;  // if else 搭配使用,对于缺省的条件要写”else;”;
        end
end // SEQ_BLOCK_NAME

//Combinational logic style
always @(signal_a or signal_b)
begin : COM_BLOCK-NAME
        //if else 结构综合的结构可能是与或非门构成的,也可能是一组多路选择器
        //而case结构综合结果一般会是多路选择器,但对于可以优化的 case 综合工具会综合出更简单的结构。
        //所有对于可以写出平行结构的条件,优先写成 case 结构,例如地址译码等,条件之间
        //有重复和嵌套的情况则是写成 if else 结构。
        case (expression)
                item1 : begin
                        signal_c=*****;
                end
                item2 : //statement;
                default ://statement;  // case 中的缺省条件要写”default”;
        endcase
end // COM_BLOCK_NAME
//*********************

endmodule
//无条件寄存的寄存信号在原信号上加 r 、rr,或者加上ff1,ff2
如原信号 data_in, 寄存一拍data_in_r或data_in_ff1, 寄存两拍 data_in_rr,data_in_ff2