当前位置:首页 > 硬件描述语言篇Verilog HDL代码规范
WWW.EEPW.COM.CN
手把手教你学习FPGA系列教程
硬件描述语言篇之Verilog HDL代码规范
1. 代码规范目的
本规范的目的是提高书写代码的可读性、可修改性、可重用性,优化代码综合和仿真的结果,指导设计工程师使用VerilogHDL规范代码和优化电路,规范可编程技术的VerilogHDL设计输入,从而做到:1.逻辑功能正确,2.提高整洁度,3.便于跟踪、分析、调试,4.增强可读性,帮助阅读者理解,5.便于程序维护,6. 便于整理文档,7. 便于交流合作。
2. 代码规范范围
本规范涉及Verilog HDL编码风格,编码中应注意的问题,Testbench的编码等。本规范适用于Verilog model的任何一级(RTL,behavioral, gate_level),也适用于出于仿真、综合或二者结合的目的而设计的模块。
3. 代码规范内容 3.1标准的文件头
在每一个版块的开头一定要使用统一的文件头,其中包括作者名,模块名,
创建日期,所属项目,概要,更改记录,版权等必要信息。
3.2标准的module 格式
(1) module例化名用xx_u标示(多次例化用次序号0,1,2…)。 (2) 建议每个模块加timescale。
(3) 不要书写空的模块,即一个模块至少要有一个输入一个输出。
(4) 为了保持代码的清晰、美观和层次感,一条语句占用一行,每行限制
在80个字符以内,如果较长则要换行。
(5) 采用基于名字(name_based)的调用而非基于顺序的(order_based)的
调用。
(6) 模块的接口信号按输入、双向、输出顺序定义。 (7) 使用降序定义向量有效位顺序,最低位是0。
(8) 管脚和信号说明部分,一个管脚和一组总线占用一行,说明清晰。 (9) 在顶层模块中,除了内部的互联和module的例化外,避免再做其他
WWW.EEPW.COM.CN
逻辑。
(10) 为逻辑升级保留的无用端口以及信号要注释。 (11) 建议采用层次化设计,模块之间相对独立。
3.3命名规则
(1) 每个文件只包含一个module,module名要小写,并且与文件名保持
一致。
(2) 模块接口信号定义输入后缀“_i”,输出后缀“_o”。
(3) 模块接口信号定义在module()里直接声明信号类型 如module(input
clk, input rst, input a, output reg b)。
(4) 三态输出的寄存器信号应后缀\。
(5) 除parameter外,信号名全部小写,名字中的两个词之间用用下划线
连接。
(6) 由parameter定义的常量要求全部字母大写,自己定义的参数、类型
用大写标识。
(7) 推荐用parameter来定义有实际意义的常数,包括单位延时、版本号、
板类型、单板在位信息、LED亮灯状态、电源状态、电扇状态等。
(8) 信号名长度不超过20字符。
(9) 代码中不能使用VHDL保留字,更不能使用verilog保留字。
(10) 建议给信号添加有意义的前缀或者后缀,命名符合常用命名规范
(_clk或clk_表示时钟,n表示低电平有效,z表示三态信号,en表示使能控制,rst表示复位,保持缩写意义在模块中的一致性。
3.4线网和寄存器
(1) 不允许锁存器和触发器在不同的always块中赋值,造成多重驱动。 (2) always语句实现时序逻辑采用非阻塞赋值,always语句实现的组合逻
辑和assign语句块中使用阻塞赋值。
(3) 不允许出现定义的parameter/wire/reg没有使用。 (4) 数据位宽要匹配。
(5) 建议不使用integer类型寄存器。
(6) 三态逻辑可以在顶层模块使用,子模块中避免使用三态。 (7) 建议使用coregen生成的乘法电路。 (8) 不使用real,time,realtime类型。
3.5可综合语句的使用
(1) 不要使用disable、initial等综合工具不支持的电路,而应采用复位方
式进行初始化。但在testbench电路中可以使用。
(2) 不要使用===、!==等不可综合的操作符。
WWW.EEPW.COM.CN
(3) 除仿真外不要使用fork-join、while、repeat、forever、deassign、force、
release等语句。
3.6条件语句的使用
(1) if语句都要有else和它对应。
(2) 变量在if-else或case语句中所有变量在所有分支中都赋值,如果用到
case语句,写上default项。
(3) 组合逻辑语句块敏感表中的敏感变量必须和该块中使用的相一致,不
能多也不能少(直接用*表示敏感变量)。
(4) 多个表达式的组合,建议使用括号()区分优先级,避免编译器优先级
错误。
(5) 不允许使用常数作为if语句的条件表达式。
(6) 异步复位,高电平有效用“If(
“if(
(7) 不推荐嵌套使用5级以上if…else if…结构。
3.7重用化设计
(1) 层次设计的原理以简单为主――尽量避免不必要的层次;层次结构设
计得好,在综合中就不需要太多的优化过程。
(2) 模块的划分根据层次设计来决定,模块化对于布线有很大帮助,模块
化的设计中 要尽量减少全局信号的使用。
(3) 通用的部分尽量提取出来作为一个共用模块,同时为了适应需求的更
改也应提供用户定制模块入库的方式。
(4) 合理划分设计的功能模块,保证模块功能的独立性 (5) 将异步电路和同步电路区分开,便于综合和后端约束
(6) 需要传递参数的模块,在多次例化的时候统一都传递参数,不要例化
同一个模块,有的传参数,有的不传。
3.8参数化设计
为了源代码的可读性和可移植性起见,不要在程序中直接写特定数值,尽可能采用`define语句或paramater语句定义常数或参数。
3.9同步设计
(1) 在一个module中,在时钟信号的同一个沿动作,如果必须使用时钟
WWW.EEPW.COM.CN
上升沿和时钟下降沿,要分两个module设计。
(2) 在顶层模块中,时钟信号必须可见,不要在模块内部生成时钟信号,
而是使用DCM/PLL产生的时钟信号。
(3) 避免使用门控时钟和门控复位。
(4) 同步复位电路,建议在同一时钟域使用单一的全局同步复位电路;异
步复位电路,建议使用单一的全局异步复位电路。
(5) 不要在时钟路径上添加任何buffer。 (6) 不要在复位路径上添加任何buffer。 (7) 避免使用latch。
(8) 寄存器的异步复位和异步置位信号不能同时有效。
(9) always有且仅有一个的敏感事件列表,敏感事件列表要完整,否则可
能会造成前后仿真的结果不一致;异步复位情况下需要异步复位信号和时钟沿做敏感量,同步复位情况下只需要时钟沿做敏感量。
(10)在时序always块的敏感事件列表中必须都是沿触发事件,不允许出
现电平触发事件。
(11)复杂电路将组合逻辑和时序逻辑电路分成独立的always描述。
3.10代码注释
(1) 用“//”做小于1行的注释,用“/* */”做多于1行的注释。 (2) 代码中应采用英文作详细的注释,注释量应达到代码总量的30%以上。 (3) 更新的内容要做注释,记录修改原因,修改日期和修改人。 (4) 注释应在代码行的上面或末尾, 若在上面, 注释行前应加空行。
(5) 对信号、参量、引脚、模块、函数及进程等加以说明,便于阅读与维
护,如信号的作用、频率、占空比、高低电平宽度等。
(6) 注释不应重复代码已经表明的内容,而是简介的点明程序的突出特征。
3.11空行和空格
(1) 适当地在代码的不同部分中插入空行,避免因程序拥挤不利阅读。 (2) always块前后必须加空行。
(3) 相对独立的功能块间必须加空行。
(4) 每次空行不宜超过2行, 否则, 只会增加翻页的工作。 (5) 在表达式中插入空格,避免代码拥挤,包括:赋值符号两边要有空格;
双目运算符两边要有空格;单目运算符和操作数之间可没有空格。
3.12排版
(1) 每层缩进1个Tab(4个空格),不宜缩进太多,超出屏幕。
(2) 输入输出信号的宽度定义与关键字之间,信号名与宽度之间要用空格
WWW.EEPW.COM.CN
分开;所有宽度定义对所有信号名对齐。
(3) 一致的 begin end 书写方式,always 中,一定要用begin end 区分, (4) if else 中仅有一个语句行时,不要使用begin end; 如果有多个语句行
时,begin end和if ()或else ()空四个格。
4. 小结
以上列出的代码编写规范无法覆盖代码编写的方方面面,还有很多细节问题,需要在实际编写过程中加以考虑。并且有些规定也不是绝对的,需要灵活处理。代码规范并不是律条,但是在一个项目组内部、一个项目的进程中,应该有一套类似的代码编写规范来作为约束。总的方向是,努力写整洁、可读性好的代码。
共分享92篇相关文档