Verilog HDL 编程规范

文章目录


前言

        本专栏的博文都是关于Verilog HDL 语法。目前(2021/9/7),本人接触FPGA和Verilog HDL 语法也差不多有近半年的时间了。对于一些常规的模块编写、IP核配置、仿真等没有太大问题。但是如果涉及到特别复杂的逻辑设计时,也会出现较多的语法空白需要填补。所以我准备以博客的形式重新整理相关的Verilog HDL 语法,做到知识的沉淀。

        有很多从事FPGA数字设计的人都说过,掌握Verilog HDL 的基础语法就能够编写将近90%的逻辑,尽管事实确实如此。但是全面一些我觉得会更好。因为设计的正确性和最优性是两个不同的概念。掌握基本的语法足够让你做到正确性,但是要想做到最优设计,必须要对语法有比较全面、透彻的认识。

        Verilog HDL 编程风格和编程规范程度都很重要。规范的编程不仅是有助于自己排错查错,也利于别人理解。尽量在初学阶段就逐渐形成自己规范的编程风格。

        本文主要介绍一种规范的编程方式,供借鉴


一、文件声明

每个文件的开始,最好有说明该文件的文字段。主要包括:

1、公司、版权

2、文件名

3、作者

4、日期

5、版本号

6、概述(此部分包括模块的功能描述、注意事项、关键点等)

如果后期对该模块进行版本修改、升级、维护等,在原本的声明文字后再添加对应版本修改信息。方便后期整理维护。

文件声明具体格式参考:

//----------------文件的相关说明-------------------//

// 公司版权:

// 文件名称:
// 功能说明:

// 作    者:
// 设计日期:
// 版    本:

// 相关参考:

//----------------- 版 本 修 改--------------------//

// 改后版本:
// 修改日期:
// 修改作者:

// 修改原因:

二、命名

1、模块(module)命名

        一个 Verilog 文件只能包含一个 module ,module 的名称统一小写或者大写。尽量不要大小写混着用。因为大小写切换麻烦。这只是命名,不是设置密码,模块(module)的名称要能够有一定的功能、参数代表性。要做到见名识义。

2、parameter 命名

        参数 parameter 的命名统一大写。本地参数 localparam 也统一用大写命名。建议用 parameter 、localparam 参数类型命名一些诸如数据位宽、版本号、状态值等有意义的常数,方便程序改版升级。

3、信号命名

        输入信号、输出信号、内部信号等的命名同一大写或者小写,不要混合使用(除了复位信号)。信号名称最好能见名识义。最好在信号名称最前面添加信号性质或者类型标识,方便使用。信号名称不应过长(尽量小于20个字符)。信号名称缩写要有一定的通用性,不能过于生僻。

        命名举例:

input									I_SYS_CLK, 	  //系统时钟
input									I_ARst_n,  	  //异步复位信号 低电平有效
input									I_Rst_n,   	  //同步复位信号 低电平有效
input									I_ARst,    	  //异步复位信号 高电平有效
input				[15:0]				I_FFT_DATA_RE,//FFT计算输入数据实部
input				[15:0]				I_FFT_DATA_IM,//FFT计算输入数据虚部

output				[15:0]				O_FFT_RES_RE,//FFT计算结果实部
output				[15:0]				O_FFT_RES_IM,//FFT计算结果虚部
output									O_VALID,     //输出有效信号

wire									W_READ_FLAG;//读标志信号
wire				[11:0]				W_FIR_RES;	//FIR滤波器输出结果

reg				 						R_1_VALID;	//valid 信号打一拍
reg				 						R_2_VALID;	//valid 信号打二拍
reg				 	[15:0]				R_COUNTER;	//计数器

三、注释

        用 // 注释单独的一行,用 /* */ 注释多行。注释的内容不要冗长。

四、模块

        模块的例化名要做到统一,且有规律可循。IP 核的例化也是一样。

        一条语句占一行。

        模块的接口信号按照输入(input)、双端口(inout)、输出(output)的顺序定义。

        多bit信号定义按照【width-1:0】的方式定义。

        不能用向量方式定义一组时钟信号。如 input   [2:0]   CLK

        module内不能存在无驱动源的多余信号,也不能存在无驱动的输出信号。

        顶层模块中,除了例化模块和它们之间彼此的连线,避免出现其他的逻辑。

        子模块的输出建议用寄存器输出。

        子模块内避免双向端口(inout),最好在顶层模块处理双向总线。

        子模块内禁止用三态逻辑(除非子模块的三态逻辑输出直接供顶层模块使用),顶层模块可以用三态逻辑。

        模块内避免存在未连接的端口。

        为逻辑升级等准备的端口、信号,现阶段先注释掉。

五、wire、reg

        禁止锁存器和触发器在不同的always块中被赋值,形成多重驱动。

        always 语句实现时序逻辑用 非阻塞赋值语句,实现组合逻辑用 阻塞赋值语句。同一种信号的赋值不能既是阻塞赋值 又是 非阻塞赋值。

        所定义的wire 、 reg 类型的信号不能未使用。

        建议不要使用 integer 类型的寄存器。

        寄存器类型(reg)的信号要初始化。

        除了移位寄存器,一个always语句块中只对一个信号赋值、运算。 

六、表达式

        表达式内多用小括号()表示运算优先级。

        设计中用到的逻辑电平值用基数表示。如:1’b0、8‘b0101_1111、16’hA89B

        进行端口声明、信号赋值、变量比较时,一定注意位宽匹配。

七、条件语句

        if 、 else if 语句要有 else 语句与之相对应。

        case 语句要有default。

        if 语句的条件表达式不能是常数。

        不建议5级以上的 if-else 嵌套。

        条件表达式必须为 1 bit 。如:

// 异步复位信号 低电平有效
if (I_ARst_n == 1'b0) 

// 不建议的写法:
if (I_ARst_n == 0) 
if (!I_ARst_n) 

八、可综合性

        避免使用 include 语句;

        应采用复位方式初始化,仿真时可用 initial 语句初始化;

        不要使用 specify 模块;

        不要使用 === 、!== 等不可综合的操作符;

        除仿真外不要使用 fork-join 语句、while 语句、repeat 语句、forever 语句、force 语句、release语句、named events 语句、系统任务($);

        不能在连续赋值语句中引入 驱动强度 和 延时;

        禁止用 trireg 型线网;

        禁止用tri1、tri0、triand、trior、型连接;

        禁止位驱动型(supply0、supply1)线网赋值;

        禁止在RTL代码中实例化门级单元,如:CMOS/RCMOS/NMOS/PMOS/RNMOS/RPMOS

/trans/rtrans/tranif0/tranif1

九、可重用性

        进口信号尽量少,接口时序尽量简单;

        将状态机电路与其他电路分开,异步电路与同步电路分开,便于后续的综合、约束;

        顶层模块中将 I/O 端口、边界测试电路、逻辑设计相区分;

十、同步设计

        同一个模块内,时序电路应在时钟的同一个边沿动作。如果有的部分需要用到上升沿而有的部分需要用到下降沿,那么就要用两个模块来设计。

        顶层模块中,时钟信号必须可见,不要再模块内部生成时钟信号。要用PLL/MMCM等生成。

        避免使用门控时钟、门控复位。

        对于同步复位电路,建议在同一时钟域使用单一的全局同步复位电路;对于异步复位电路,建议使用单一全局异步复位电路。

        不要在时钟、复位路径上添加任何 buffer。

        避免使用latch(锁存器)。

        寄存器的异步复位和置位不能同时有效。

        避免使用组合反馈逻辑。

        复杂电路将组合逻辑和时序逻辑分成独立的 always 块描述。

十一、循环语句

        不建议使用循环语句,必要时可用 for 语句。

十二、约束

        对全部的时钟频率、占空比进行约束。

        对全局时钟的 skew 进行约束。

        根据输入输出信号特性进行上下拉约束。

        综合设置,建议将 fanout 设置为30。

        布局布线报告中 IOB、LUTs、RAM等资源利用率低于80%。

十三、PLL、DCM

        使用FPGA内部PLL/DCM资源时,应保证输入时钟抖动小于300ps,以防止失锁。

        输入时钟出现瞬断,必须复位PLL/DCM。

十四、关于对齐

        代码对齐用空格,尽量不用 Tab 。


参考声明

【1】Verilog 红宝书编程规范。

【2】Verilog 编程规范。 

欢迎提出宝贵意见~



文末推荐

掌握了基本的Verilog语法,不去实战练习的话很难有大的突破。牛客网可以为大家提供一个免费的刷题练习的平台。非常推荐大家使用。

 链接如下:牛客网-Verilog专项https://www.nowcoder.com/link/pc_csdncpt_zls_verilog这个里面有很多代码题目练习,对于新手来说可以快速掌握Verilog编程的基本语法,对于老手来说也可以巩固自己的编程能力。不用付费免费试用哦。基本是每个即将找工作的人必备的刷题网站。快行动起来吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在路上-正出发

哈哈,多少是个心意

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值