数字逻辑实践2->Verilog编写规范
来源:数字逻辑与Verilog设计实验课讲解,个人做的笔记与整理。
00 规范的重要性
-
良好的编程风格有利于减少消耗的硬件资源,提高设计的工作频率 。
-
提高系统的可移植性和可维护性。
-
程序的格式化能体现程序员的基本素质和整个团队的风貌。
01 命名规则
有C语言基础的这部分可以简单略过,看看即可。无基础的可以跳过,有一定编程经验后再来总结提高。
01-00 命名字符集
用于命名的字符集为:字母A~Z和a~z, 数字0~9以及下划线组成。
例如:
1 data_bus 2 data_width 3 clk_48M 4 //使用用意义的名字,利于望文生义,便于维护 5 6 48M_clk//名称不能以数字开头 7 data__bus//不能连续使用下划线 8 data*bus//不能包含非字母符号
01-01 命名大小写规则
-
参数(parameter)、常量(constant)和块标号(block label)名必须一致采用大写;
-
而信号,变量和结构名(construct)以及实例标号(instance)必须一致采用小写。
-
有利于在仿真时,区分不变和变化的 数据。
例子:
1 module display_led( //模块标号小写 2 clk_48M, //时钟 3 ledout //LED输出 4 ); 5 input clk_48M; //48M系统时钟 6 output [7:0]ledout;//LED输出控制 7 reg [22:0]count; //计数器 8 reg [7:0]led_reg; //LED输出缓存区 9 wire led_clk; //LED显示时钟控制 10 parameter COUNTER=100; 11 assign led_clk = count[22]; //LED显示时间控制
01-02 名字必须唯一
在不区分大小写的情况下,名字必须唯一。例如,名字state和State不能同时出现在同一设计中。因为有的EDA工具不区分大小写。
01-03 不同类型的信号的命名习惯
-
如果一个名字由多个字组成,则使用下划线连接,用以增加名字的可读性。
-
为了使信号的名字有意义,可以根据信号类型选取相应的后缀。
具体示例如下:
命名 | 信号类型 | 实例 |
---|---|---|
xx_r | 寄存器类型 | Data_out_r |
xx_a | 异步信号 | Addr_strobe_a |
xx_clk | 时钟信号 | Sys_clk |
xx_nc | 不连续信号 | Stata_nc |
xx_n | 低电平有效信号 | Reset_n |
xx_pn | 有n个相位的信号 | Enable_p2 |
xx_z | 三态信号 | Data_out_z |
xx_next | 状态机信号 | Transmit_next |
xx_test | 测试模式信号 | Parallel_clk_test |
sys_xxx | 系统信号 | sys_dout,sys_din |
clk_xxx | 时钟信号(也可这样写) | clk_768MHZ |
rst_xxx reset_xxx | 复位信号 | |
st_xxx set_xxx | 置位信号 |
01-04 多后缀的优先权
这个确实有点抽象...
顺序:
1 //例子 2 ram_1_clk_z_n 3 //结构 4 操作对象序号_数据类型(_clk/_next)_三态信号(_z)_低电平有效信号(_n)
01-05 模块命名习惯
-
将模块英文名称的各个单词的首字母组合起来,形成3~5个符号的缩写。
Arithmatic logical unit —— ALU
-
若模块的英文名只有一个单词,可取该单词的前3个字母
Decider —— DEC
01-06 模块间接口命名
-
所有的变量命名分为两个部分:
-
第一部分表明数据方向,其中数据发出方在前,数据接收方在后;
-
第一部分全部大写,
-
-
第二部分为数据名称。
-
第二部分中所有具有明确意义的英文名全部拼写或者缩写的第一个字母大写,其余部分小写。
-
-
两个部分用下划线隔离开。
-
-
例:CPUMMU_WrReq (CPU发送给MMU的写请求信号)
01-07 模块内部信号
模块内部的信号由几个单词连接而成,缩写要求能基本表明本单词的含义。
02 注释
主要有三点:
-
普通描述注释“//”就可以
-
文件头注释有一点麻烦,但是显得很标准。
-
模块之间(always)的注释参照文件头注释
1 //**************************************** 2 //模块名称: 3 //功能描述: 4 //****************************************
03 代码格式
03-00 端口
1 module buzzer ( 2 clk_48M, //时钟输入 3 beep, //蜂鸣器控制输出 4 key, //按键输入 5 ledout //LED显示控制信号 6 ); 7 //个人感觉对于复杂电路比较有用,而实验代码就不必如此,直接类似函数参数一样声明即可。可配注释理解。
03-01 连线
1 input clk_48M; 2 input rst; 3 output lcd_en; 4 output [7:0]data_bus; 5 wire clk_lcd; 6 //紧跟module声明,一个Tab键 7 //标准要求是一行声明一个端口
03-02 正文
正文书写要求与C语言类似。
03-03 其他
-
用四个空格代替TAB键;因为不同的编辑系统的Tab制表符间距可能不同。
-
每行只有一个Verilog语句;对于长的语句可以使用回车和缩进方法,表示成连续的语句行。
-
避免使用硬编码;建议使用宏或则参数来定义常数,避免使用硬编码数值。例如:
1 //硬编码方式: 2 input [31:0] data_a; // 输入比较数据A 3 input [31:0] data_b; // 输入比较数据B 4 5 //参数定义方式: 6 parameter DATA_WIDTH = 32; //总线数据宽度 7 input [DATA_WIDTH-1:0] data_a; 8 // 输入比较数据A 9 input [DATA_WIDTH-1:0] data_b; 10 // 输入比较数据B
下面是更多出于美观的考虑:
-
各节之间加1行或者多行空格
-
不同变量,变量与符号,变量与括号之间都应该保留一个空格 alwaya @ ( … )
-
逻辑运算符、算术运算符、比较运算符等运算符两侧各留一个空格。(单数操作运算符例外)
-
使用”//” 注释时,在”//”后应当有一个空格