Verilog代码编写风格

合集下载

systemverilog 可综合 语法

systemverilog 可综合 语法

systemverilog 可综合语法-概述说明以及解释1.引言1.1 概述SystemVerilog是一种硬件描述语言,其可综合语法用于描述硬件设计的行为和结构。

可综合语法是指在编写SystemVerilog代码时,能够被综合工具翻译成底层硬件电路,并最终映射到FPGA或ASIC等可编程器件上的语法规则和风格。

因此,可综合语法在硬件设计中起着至关重要的作用。

在硬件设计中,可综合语法使设计工程师能够通过代码描述硬件的功能和结构,包括处理器、逻辑电路、存储器等。

通过使用可综合语法,设计工程师可以更加灵活地实现各种功能和性能要求,同时也能提高设计的可维护性和可重用性。

SystemVerilog的可综合语法特点是其结构化的设计风格,丰富的数据类型和内置的高级语言功能。

与传统的硬件描述语言相比,SystemVerilog提供了更多的抽象层次和编程特性,可以更高效地完成复杂的硬件设计任务。

例如,SystemVerilog支持面向对象的设计方法,可以使用类和对象对设计进行建模和封装。

此外,SystemVerilog还提供了多种数据类型和运算符,使设计工程师可以更方便地处理各种数据和信号。

综上所述,可综合语法在SystemVerilog中具有重要的地位和作用。

通过使用可综合语法,设计工程师能够更加方便地描述和实现各种硬件功能,提高设计的效率和可靠性。

在今后的硬件设计中,可综合语法的应用将更加广泛,并且不断发展和完善,以满足不断变化的设计需求。

1.2 文章结构文章结构部分的内容可以包括以下内容:文章结构的目的是为了给读者提供清晰的导航和理解文章的逻辑框架。

通过合理的结构,读者可以更好地理解文章的目的和内容,并能够有序地阅读和理解整个文档。

本文的结构如下:第一部分是引言部分,用于介绍文章的背景和相关信息。

在引言部分,我们将概述SystemVerilog可综合语法的定义和作用,并介绍本文的结构和目的。

第二部分是正文部分,主要内容是关于SystemVerilog可综合语法的定义和特点。

verilog语言例化书写格式

verilog语言例化书写格式

verilog语言例化书写格式Verilog语言是一种硬件描述语言(HDL),在数字电路设计、逻辑仿真和综合等领域得到广泛应用。

在Verilog中,实例化是将模块实例化为实体的过程,通过实例化可以在设计中重复使用模块并连接各个模块之间的信号。

Verilog语言的例化书写格式如下:1. 定义模块首先,在设计中需要定义要实例化的模块。

模块定义包括模块名称、输入输出端口和内部信号。

例如,我们定义了一个名为"example_module"的模块,包含三个输入端口(A、B、C)和一个输出端口(D):```verilogmodule example_module(A, B, C, D);input A, B, C;output D;// internal logicendmodule```2. 实例化模块在设计中需要使用该模块时,可以进行实例化。

实例化的格式为:模块名称实例名称 ( .端口名称(信号名称), ... );例如,我们使用上述定义的"example_module"模块进行实例化,假设实例名称为"example_inst",连接的信号为A、B、C、D,实例化代码如下:```verilogexample_module example_inst(.A(signal_A),.B(signal_B),.C(signal_C),.D(signal_D));```在上述实例化代码中,通过"."符号将信号与端口进行连接。

例如,信号signal_A将与输入端口A连接起来。

3. 内部信号的连接在实例化模块时,还可以直接将内部信号连接到其他信号上。

例如,我们在实例化时,将一个内部信号internal_signal直接连接到另一个信号output_signal上:```verilogexample_module example_inst(.A(signal_A),.B(signal_B),.C(signal_C),.D(output_signal));assign internal_signal = output_signal;```通过上述的例化书写格式,我们可以在Verilog设计中有效地实例化模块,并连接各个模块之间的信号。

2024版Verilog编程规范(华为)

2024版Verilog编程规范(华为)
自动化测试实现
实现自动化测试流程,提高测试 效率和准确性。
06
代码审查与质量保证
代码审查流程介绍
提交代码
开发人员将代码提交到代码审查 系统中。
分配审查任务
系统或审查组长将审查任务分配 给审查人员。
代码审查
审查人员对代码进行逐行审查, 检查是否符合编程规范和质量要
求。
审查通过
经过多轮反馈和整改后,代码符 合要求,审查通过。
通过定期的培训、分享和宣传活动,提高开 发人员对Verilog编程规范的认识和重视程度。
引入自动化检查工具
建立持续改进机制
研究和引入自动化检查工具,对Verilog代码 进行静态分析和规范检查,进一步提高代码 质量和开发效率。
建立规范的持续改进机制,收集开发人员的 反馈和建议,及时调整和优化规范内容。
可重用性原则
模块应具有高内聚、低耦 合的特点,便于在不同项 目中重用。
可维护性原则
模块应易于理解、测试和 修改,以降低维护成本。
顶层结构设计方法
自顶向下设计
从系统整体需求出发,逐 步细化到各个模块的设计 和实现。
模块化设计
将系统划分为多个独立的 模块,每个模块承担一定 的功能,便于并行开发和 维护。
减少错误和提高代码质量
02
规范的编程习惯有助于减少编码过程中的错误,提高代码的稳
定性和可靠性。
促进知识共享和传承
03
统一的编程规范有利于知识的积累和传承,降低新人学习成本,
提高团队整体技术水平。
适用范围及对象
适用范围
本规范适用于使用Verilog语言进 行硬件描述和设计的所有场景,包 括但不限于数字电路设计、验证、 仿真等。
端口名应避免与模块内部变量名冲突。

verilog %用法

verilog %用法

verilog %用法摘要:一、Verilog简介1.Verilog是一种硬件描述语言2.用于描述数字电路和模拟混合信号电路3.被广泛应用于电子设计自动化领域二、Verilog的基本语法与结构1.模块定义2.信号声明3.行为描述4.结构描述三、Verilog的主要关键字1.模块关键字(module)2.信号关键字(wire、reg、integer、real)3.行为关键字(initial、always、assign、deassign)4.结构关键字(begin、end、architecture)四、Verilog的运算符1.算术运算符2.关系运算符3.逻辑运算符4.位运算符五、Verilog的常用函数1.基本数学函数2.逻辑函数3.位运算函数4.字符串处理函数六、Verilog的编码风格与实践1.合理使用注释2.保持代码简洁3.命名规范4.层次化设计正文:Verilog是一种硬件描述语言,被广泛应用于电子设计自动化领域,用于描述数字电路和模拟混合信号电路。

它具有简洁、清晰的语法特点,易于学习和使用。

在Verilog中,模块定义是基本单位,可以包含信号声明、行为描述和结构描述。

模块关键字为`module`,用于定义一个模块实例。

信号关键字包括`wire`(线网)、`reg`(寄存器)、`integer`(整数)和`real`(实数),用于声明信号。

行为关键字有`initial`(初始化)、`always`(always 块)和`assign`(赋值),用于描述模块的行为。

结构关键字`begin`和`end`用于组织代码结构,`architecture`用于描述模块的层次结构。

Verilog中的运算符包括算术运算符、关系运算符、逻辑运算符和位运算符。

运算符的使用可以简化代码,提高描述电路的效率。

此外,Verilog还提供了丰富的函数,包括基本数学函数、逻辑函数、位运算函数和字符串处理函数,方便用户进行各种计算和操作。

verilog的代码规范和coding风格

verilog的代码规范和coding风格

verilog的代码规范和coding风格想要成为一名优秀的数字IC设计工程师需要哪些基本的专业知识呢?如下:1.半导体物理学、半导体器件物理学、基本的固体物理、半导体工艺与制造等物理学知识;2.电路分析、模拟电子线路、COMS模拟集成电路、专用集成电路基础等模拟IC知识;3.信号系统、数字信号处理、信道编码、通信原理等通信知识;4.C语言、汇编、C++、脚本(shell、tcl、perl)、Linux(我觉得如果懂kernel那就更好了)、体系结构、组成原理等计算机知识;5.各种EDA和编程调试工具的使用Modelsim、Debussy、quartus ii、Cadence、DC、vim等等(就数字方向而言用的最多的5种左右,模拟另当别论);另外虚拟机什么的总得玩得转吧!6.当然最重要的还是我们亲爱的--verilog,不会verilog(当然VHDL也是一样的)那你会别的也算不上优秀的Digital IC Engineer!verilog语法并不复杂,只是初学者容易犯一些“类C”错误,总会不经意间将verilog写成了C语言,或者是没有使用并行思想,或者就是多处赋值等等问题。

如果我们克服了之前的一些小毛病,在这些之外,我们想更近一步提升自己的写代码水平、研发水平,而不是只做一个码农的话那么我们要做的就是:第一步:提高代码规范性,每个企业、研究所可能都有自己的一套代码书写规范,但是总的来说都有一些共性,而且往往这些共性的地方还特别多,一个没有代码规范的程序员不可能写出非常漂亮和优秀的程序,当然有了规范的代码后也不一定就能写出漂亮和优秀的程序,这是两码事。

代码规范之后的一个境界我觉得是优良的编程风格,编程风格不同于代码规范,编程风格在verilog中特别指代那些逻辑上的风格,同样的功能,使用不同的编程风格,代码综合面积可能是几倍的关系,这一点我深有体会,另外,人们不经意间的编码习惯可能会导致许多冗余代码,在verilog综合之后,这些冗余就会成为实实在在多出来的不必要的电路,他们或者是寄存器或者是没用的组合逻辑,虽然往往DC一类的综合工具会对代码综合进行优化,并且会根据综合脚本进行最大化的优化计算,但是工具毕竟是工具,他不可代替人类,很多冗余电路综合工具并没有办法进行优化,因为工具并不知道你的本意,也不可完全进行语意预测,而不必要的电路意味着更多的流片成本,更低的work效率和更多的功耗消耗,这些都不是我们想看到的,所以一个好的coding风格本身对于企业来说就是非常大的价值!!!当然我认为要培养良好的coding风格并不是一件容易的事,本身 verilog design == 电路设计,透过代码看电路这个能力并不是一蹴而就的,这需要我们的长期的学习和思考总结,就像模拟设计一样,往往这是一种经验!。

verilog书写规范

verilog书写规范

海思高校合作——QA培训资料一、RTL CODE 规范1.标准的文件头在每一个版块的开头一定要使用统一的文件头,其中包括作者名,模块名,创建日期,概要,更改记录,版权等必要信息。

统一使用以下的文件头:// **************************************************************// COPYRIGHT(c)2005, Hislicon Technologies Co, Ltd// All rights reserved.//// IP LIB INDEX : IP lib index just sa UTOPIA_B// IP Name : the top module_name of this ip, usually, is same// as the small ip classified name just as UTOPIA// File name : file_name of the file just as “tx_fifo.v”// Module name : module_name of this file just as “TX_FIFO”// Full name : complete Emglish nme of this abbreviated//// Author : Athor/ID// Email : Author‟s email// Data :// Version : V 1.0////Abstract :// Called by : Father Module//// Modification history// ------------------------------------------------------------------------------------------------------// //// $Log$//// *********************************************************************2. 标准的module 格式(module 整体结构)对于模块的书写采用统一的格式便于项目内部成员的理解和维护,我们用批处理建立了一个MODULE模块,其内容解释如下:●端口定义按照输入,输出,双向的顺序:●模块名、模块例化名统一,例化名前加大写U_以区分(多次例化另加标识),三者关系:文件名:xxx .v (小写)模块名:XXX (大写)例化名:U_XXX (大写)IP 内部所有的模块名都要加IP名或者IP名简称作前缀,如USB_CTRL、USB_TX_FIFO。

verilog编码规则检查 -回复

verilog编码规则检查 -回复

verilog编码规则检查-回复在Verilog编程中,遵循一定的编码规则是非常重要的。

这些规则有助于增加代码的可读性、可维护性和可重用性,从而提高整体的代码品质。

本文将详细讨论一些常见的Verilog编码规则检查,帮助您了解如何正确地编写高质量的Verilog代码。

第一部分:文件和模块在编写Verilog代码时,首先需要创建一个文件和定义一个模块。

以下是一些与文件和模块相关的编码规则:1. 文件命名:保持文件命名简洁明了,使用有意义的名称,并以".v"作为文件扩展名。

例如,"priority_encoder.v"。

2. 模块命名:每个模块也应具有有意义和描述性的名称。

命名应使用驼峰式大小写,以便在查看代码时更容易理解。

3. 模块接口:明确定义模块的输入和输出接口。

每个接口信号都应有明确的名称和数据类型。

推荐使用`input`和`output`关键字来定义接口。

4. always块:在模块的always块中,避免使用无限循环。

始终为always 块提供明确的条件,以便它只在满足特定条件时执行。

第二部分:信号声明和赋值在Verilog中,信号的声明和赋值是代码的核心部分。

以下是一些与信号声明和赋值相关的编码规则:1. 信号声明:对于每个信号,应当在使用前为其声明数据类型和宽度。

这有助于避免潜在的数据冲突和类型错误。

2. 信号赋值:在对信号进行赋值操作时,只能使用一个连续的赋值语句。

如果需要对一个信号进行多个赋值,则应使用多个连续的赋值语句。

3. 复位信号:始终为每个模块提供一个复位信号。

在复位时,应确保所有需要复位的信号都被清零或者赋予一个已知的值。

4. 整数宽度:在Verilog中,数值宽度是非常重要的。

在声明和使用整数类型的信号时,务必指定宽度,并确保正确的数值范围。

第三部分:操作符和表达式操作符和表达式是编写Verilog代码中的主要构建块。

以下是一些与操作符和表达式相关的编码规则:1. 操作符优先级:在编写使用多个操作符的表达式时,务必使用括号来明确运算的优先级和结合性,以避免歧义和错误的计算结果。

verilog教程

verilog教程

verilog教程当您开始学习Verilog时,以下是一些重要的基础知识和概念。

1. Verilog是一种硬件描述语言(HDL),用于描述和设计数字电路。

它可以用于模拟、合成和验证电路。

2. Verilog使用模块化的设计风格。

每个设计都由一个或多个模块组成,每个模块有自己的输入和输出。

3. 使用`module`关键字定义一个模块,并在其后给出模块的名称。

```verilogmodule my_module;// 模块主体endmodule```4. 模块内部包含用`input`和`output`声明的端口,用于与其他模块进行通信。

```verilogmodule my_module(input wire a,input wire b,output wire c);// 模块主体endmodule```5. `wire`关键字用于声明连接不同模块的导线。

可以将导线看作是用于传输数字信号的线。

6. 在模块主体中,可以使用`assign`关键字创建逻辑连接。

逻辑连接使用`=`运算符连接输入和输出。

```verilogmodule my_module(input wire a,input wire b,output wire c);assign c = a & b;endmodule```7. 除了逻辑连接外,可以在模块内部使用`always`块创建组合和时序逻辑。

```verilogmodule my_module(input wire a,input wire b,output wire c);reg d;always @(a or b)d = a | b;assign c = d;endmodule```8. Verilog还支持使用`if-else`语句,`case`语句和循环结构等常见的编程结构。

9. 为了模拟和验证设计,可以使用Verilog仿真工具,如ModelSim、VCS等。

Verilog编码规范

Verilog编码规范

Verilog编码规范(仅供内部使用)拟制 :xxx日期:xxx审查 :审查者日期:yyyy-mm-dd 同意 :同意者日期:yyyy-mm-dd版权全部侵权必究订正记录订正日期订正版本描绘订正者目录基来源则:简单,一致,可重用。

简单指尽量使用简单的语句,尽量使用简单的设计,尽量使用简单的时钟,尽量使用简单的复位。

一致指尽量保持代码风格一致,尽量保持命名一致。

可重用指有成熟的IP 尽量使用IP ,设计的代码要尽量可重用。

1命名规范给信号命名就像给孩子取名字相同,有差异,有本源,有深度,还有一点,要简单,别冗长。

有差异指取名字不要相同,若是大家只有一个手机号码,那这个号码还可以有什么用途有本源指取名字要能象姓氏相同,让人一看就直到是张家的后辈而不是李家的。

有深度就是取名字要有涵义,张一 , 张二 , 张三固然也是名字,可是请考虑一下被取名字人的感觉。

简单点,几十个字母长的名字,打字的和看字的都累。

大小写规则:只有parameter , `define和module名称才能享受大写。

Module 名应与文件名保持一致(文件名是小写),若是不想在设计后边碰到麻烦的话。

不要试试使用任何保存字,由于他们已经被保存了。

不要重复使用相同的名字去命名不一样的数据。

(建议)对module 名加” _LVx”的后缀,加强module 名称的构造层次含义如:设计顶层为TOP LEVEL,即 LEVEL1,命名为QTRxxxx_LV1;时钟模块, IO_PAD, CORE,为 LEVEL2,命名为CLK_PROC_LV2等等;CORE内子模块为LEVEL3,而后以此类推。

关于来自同一驱动源的全部时钟信号使用相同的名字。

关于低电平有效的信号,应当以_n 结尾。

模块间相连端口名称要一致。

(建议)使用下表所列的命名缩写方式。

全称名称clock Clkreset rstclear clraddress addrdata_in dindata_out doutinterrupt request intread enable rdenwrite enable wrencount cntrequest req全称名称control ctrlarbiter arbpointer ptrsegment segmemory memregister reg(建议)使用以下后缀命名方式全称增添后缀active low_nenable_enselect_selflag_flgdelay_dly信号命名的两个词之间用下划线间隔,如ram_addr ,cnt_ctrl等等信号命名尽量不要使用孤立的、小写的英文字母L2代码编写规范2.1 版面语句独立成行,增添可读性和可保护性。

Verilog 代码风格总结-供参考

Verilog 代码风格总结-供参考

[转]Verilog 代码风格-供参考Description本文主要是收集一些重要的Verilog coding style。

一个好的coding style可以减少错误的发生,增加电路的效能,以及较好的可读性。

TextThe order of module signals一个module signal顺序如下(由左至右):Inputclock signals(clk_*)set/reset signals(set_*, rst_*)enable/disble signals(en_*, dis_*)read/write enable signals(we_*, re_*, rw_*)control signals(i_*)address signals(i_*)data signals(i_*)Outputclock signals(o_clk_*)set/reset signals(o_set_*, o_rst_*)enable/disable signals(o_en_*, o_dis_*)control signals(o_*)address signals(o_*)data signals(o_*)In/Outcontrol signals(io_*)address signals(io_*)data signals(io_*)Naming Rule以下的namign rule为个人使用的规则。

命名方式分类底线分隔型:xxx_yyy_zzz大写底线分隔型:XXX_YYY_ZZZ首字大写型:AbcDefGhi首字小写型:avcDefGhi各种元素所使用的命名文件名称:底线分隔型, Ex: xxx_yyy_zzz.vmodule名称:底线分隔型, Ex: xxx_yyy_zzzmodule instance名称:底线分隔型, Ex: xxx_yyy_zzzlocal wire名称:底线分隔型:Ex: xxx_yyy_zzzlocal reg名称:底线分隔型, Ex: xxx_yyy_zzzinput signal名称:前置i_的底线分隔型, Ex: i_xxx_yyy_zzzoutput signal名称:前置o_的底线分隔型, Ex: o_xxx_yyy_zzzinput/output signal名称:前置io_的底线分隔型, Ex: io_xxx_yyy_zzz常数名称:大写底线分隔型, `XXX_YYY_ZZZparameter参数名称:大写底线分隔型, Ex: XXX_YYY_ZZZblock名称:大写底线分隔型, Ex: XXX_YYY_ZZZ特殊讯号名称单一的clock signal: clk多个clock signal: clk_xxx负缘触发的clock signal: clk_n, clk_xxx_n单一的reset signal: rst多个reset signal: rst_xxx负缘触发的reset signal: rst_n , rst_xxx_n单一的set signal: set多个set signals: set_xxx负缘触发的set signals: set_n, set_xxx_n致能讯号: en_xxx除能讯号: dis_xxxProcedural Assignments使用指引在撰写sequential logic时,使用nonblocking assignment。

iverilog编译代码

iverilog编译代码

iverilog编译代码
摘要:
1.Iverilog 简介
2.Iverilog 编译代码的过程
3.Iverilog 编译代码的注意事项
正文:
Iverilog 是一种硬件描述语言,主要用于设计和验证数字集成电路。

相较于传统的硬件描述语言,如VHDL 和Verilog,Iverilog 具有更高的表达能力和更强的抽象能力,可以更好地描述复杂的数字电路。

Iverilog 编译代码的过程主要包括以下几个步骤:
1.预处理:在编译之前,Iverilog 编译器会首先读取输入的源代码,并对其进行预处理。

预处理的主要目的是将Iverilog 代码转换为可以被编译器识别的形式。

2.编译:预处理完成后,Iverilog 编译器会将预处理后的代码编译成目标代码。

目标代码可以是二进制代码,也可以是其他形式的代码,这取决于编译器的设置和目标平台。

3.验证:编译完成后,Iverilog 编译器会生成一个验证工具,用于验证生成的目标代码是否符合预期。

验证过程通常包括功能验证和时序分析。

在编写Iverilog 代码时,需要注意以下几点:
1.语法规范:Iverilog 的语法比较严格,需要遵循一定的规则。

否则,编译器可能会报错。

2.模块化:Iverilog 代码应该采用模块化的方式组织,这样可以提高代码的可读性和可维护性。

3.注释:Iverilog 代码中应该添加适当的注释,以便于他人理解和维护。

4.代码风格:Iverilog 代码应该保持一致的风格,包括缩进、空格和命名规范等。

个人总结Verilog代码编写的25条经验

个人总结Verilog代码编写的25条经验

个人总结Verilog代码编写的25条经验1、对所有的信号名、变量名和端口名都用小写,这样做是为了和业界的习惯保持一致;对常量名和用户定义的类型用大写;2、使用有意义的信号名、端口名、函数名和参数名;3、信号名长度不要太长;4、对于时钟信号使用clk 作为信号名,如果设计中存在多个时钟,使用clk 作为时钟信号的前缀;5、对来自同一驱动源的信号在不同的子模块中采用相同的名字,这要求在芯片总体设计时就定义好顶层子模块间连线的名字,端口和连接端口的信号尽可能采用相同的名字;6、对于低电平有效的信号,应该以一个下划线跟一个小写字母b 或n 表示。

注意在同一个设计中要使用同一个小写字母表示低电平有效;7、对于复位信号使用rst 作为信号名,如果复位信号是低电平有效,建议使用rst_n;8、当描述多比特总线时,使用一致的定义顺序,对于verilog 建议采用bus_signal[x:0]的表示;9、尽量遵循业界已经习惯的一些约定。

如*_r 表示寄存器输出,*_a 表示异步信号,*_pn 表示多周期路径第n 个周期使用的信号,*_nxt 表示锁存前的信号,*_z 表示三态信号等;10、在源文件、批处理文件的开始应该包含一个文件头、文件头一般包含的内容如下例所示:文件名,作者,模块的实现功能概述和关键特性描述,文件创建和修改的记录,包括修改时间,修改的内容等;11、使用适当的注释来解释所有的always 进程、函数、端口定义、信号含义、变量含义或信号组、变量组的意义等。

注释应该放在它所注释的代码附近,要求简明扼要,只要足够说明设计意图即可,避免过于复杂;12、每一行语句独立成行。

尽管VHDL 和Verilog 都允许一行可以写多个语句,当时每个语句独立成行可以增加可读性和可维护性。

同时保持每行小于或等于72 个字符,这样做都是为了提高代码得可读性;13、建议采用缩进提高续行和嵌套语句得可读性。

缩进一般采用两个空格,如西安交通大学SOC 设计中心2 如果空格太多则在深层嵌套时限制行长。

Verilog语言编程规范

Verilog语言编程规范

Verilog语⾔编程规范前⾔.................................................................... IV 1范围 (1)2术语 (1)3代码标准 (1)3.1命名规范 (1)3.1.1⽂件命名 (1)3.1.2HDL代码命名总则 (2)3.2注释 (4)3.2.1⽂件头 (4)3.2.2其它注释 (5)3.3编程风格 (7)3.3.1编写代码格式要整齐 (7)3.3.2使⽤⼆到四个空格符缩排 (7)3.3.3⼀⾏⼀条Verilog语句 (7)3.3.4⼀⾏⼀个端⼝声明 (7)3.3.5在定义端⼝时,按照端⼝类型或端⼝功能定义端⼝顺序。

(8) 3.3.6保持端⼝顺序⼀致。

(8)3.3.7声明内部net (8)3.3.8在⼀个段内声明所有内部net (8)3.3.9每⾏长度不超过80字符....................... 错误!未定义书签。

3.3.10代码流中不同结构之间⽤⼀空⾏隔开 (8)3.4模块划分和重⽤ (10)3.4.1不能访问模块外部的net和variable (10)3.4.2不使⽤`include编译指令 (10)3.4.3建议模块的端⼝信号尽可能少。

(10)3.4.4时钟产⽣电路单独构成⼀个模块 (10)3.4.5划分时钟域 (10)3.4.6物理和逻辑边界的匹配 (10)3.4.7特定应⽤代码要单独划分出来 (10)3.4.8关键时序逻辑划分 (10)3.4.9数据流逻辑划分 (11)3.4.10异步逻辑划分 (11)3.4.11状态机划分 (11)3.4.12控制逻辑和存储器划分 (11)3.5逻辑设计经验 (11)3.5.1时钟域要尽可能少,所⽤时钟尽可能加全局BUFF (11) 3.5.2异步接⼝信号同步化 (11)3.5.3避免寄存器的数据与时钟异步 (11)3.5.4使⽤⽆⽑刺的门控时钟使能信号 (11)3.5.5直接作⽤信号⽆⽑刺 (11)3.5.6初始化控制存储元件 (12)3.5.7使⽤同步设计 (12)3.5.8避免组合反馈环 (12)3.6常⽤编程技巧 (12)3.6.1条件表达式的值必须是⼀个单bit值 (12)3.6.2总线位顺序按⾼到低保持⼀致 (12)3.6.3不要给信号赋x值 (12)3.6.4寄存器变量只能在⼀个always语句中赋值 (12)3.6.5对常量使⽤参数⽽不使⽤⽂本宏 (12)3.6.6不能重复定义参数 (12)3.6.7不能重复定义⽂本宏 (12)3.6.8保持常量之间的联系 (12)3.6.9状态编码的参数使⽤ (13)3.6.10`define、`undef配合使⽤ (13)3.6.11⽤基地址+地址偏移量⽣成地址 (13)3.6.12使⽤⽂本宏表⽰寄存器字段位置和值 (13)3.6.13`ifdef的嵌套限制在三层以内 (13)3.6.14操作数的位宽必须匹配 (13)3.6.15模块调⽤时端⼝要显式引⽤ (14)3.6.16⽮量端⼝和net/variable声明的位宽要匹配 (14)3.6.17避免inout类型的端⼝ (14)3.6.18在复杂的表达式中使⽤括号 (14)3.7常⽤综合标准 (14)3.7.1always 的敏感列表要完整 (14)3.7.2⼀个 always 的敏感列表中只能有⼀个时钟 (14)3.7.3只使⽤可综合的结构 (15)3.7.4组合逻辑的条件需完备 (15)3.7.5循环结构中禁⽤disable语句 (15)3.7.6避免⽆界循环 (15)3.7.7端⼝连接禁⽤表达式 (15)3.7.8禁⽤Verilog primitive (15)3.7.9边沿敏感结构中使⽤⾮阻塞赋值(<=) (15)3.7.10Latch使⽤⾮阻塞赋值 (15)3.7.11模块闲置的输⼊端不要悬空 (15)3.7.12连接模块闲置的输出端 (16)3.7.13函数中不要使⽤锁存器 (16)3.7.14禁⽤casex (16)3.7.15多周期路径的信号使⽤单周期使能信号 (16)3.7.16三态元件建模 (16)3.7.17避免顶层胶合逻辑 (16)3.7.18在case语句中使⽤default赋值语句 (16)3.7.19full_case综合命令的使⽤ (16)附录1 HDL编译器不⽀持的Verilog结构 (18)附录2 Verilog和VHDL关键词列表 (19)前⾔编写本标准的⽬的是为了统⼀部门内部FPGA\EPLD设计⽤verilog语⾔编程风格,提⾼Verilog设计源代码的可读性、可靠性和可重⽤性,减少维护成本,最终提⾼产品⽣产⼒;并且以此作为代码⾛查的标准。

VERILOG语言编写规范

VERILOG语言编写规范

VERILOG语言编写规范1 目的本规范的目的是提高书写代码的可读性可修改性可重用性,优化代码综合和仿真结果,指导设计工程师使用VerilogHDL规范代码和优化电路 ,规范化公司的ASIC设计输入从而做到1. 逻辑功能正确2.可快速仿真3. 综合结果最优如果是hardware model4. 可读性较好;2 范围本规范涉及Verilog HDL编码风格, 编码中应注意的问题, Testbench的编码等;本规范适用于Verilog model的任何一级 RTL behavioral, gate_level, 也适用于出于仿真,综合或二者结合的目的而设计的模块;3 定义Verilog HDL : Verilog 硬件描述语言FSM :有限状态机伪路径:静态时序分析 STA 认为是时序失败, 而设计者认为是正确的路径4 引用标准和参考资料下列标准包含的条文通过在本标准中引用而构成本标准的条文在标准出版时所示版本均为有效所有标准都会被修订使用本标准的各方应探讨使用下列标准最新版本的可能性Actel HDLCoding Style GuiderSun MicrosystemsRevisionVerilogStyle and Coding Guidelines5 规范内容Verilog 编码风格本章节中提到的Verilog编码规则和建议适应于 Verilog model的任何一级 RTL behavioral,gate_level 也适用于出于仿真, 综合或二者结合的目的而设计的模块;命名规范选择有意义的信号和变量名, 对设计是十分重要的; 命名包含信号或变量诸如出处, 有效状态等基本含义下面给出一些命名的规则;1. 用有意义而有效的名字有效的命名有时并不是要求将功能描述出来如For I = 0; I < 1024; I = I + 1MemI<= 1 32’b0;For 语句中的循环指针I 就没必要用loop_index作为指针名;2. 用连贯的缩写长的名字对书写和记忆会带来不便, 甚至带来错误采用缩写时应注意同一信号在模块中的一致性; 缩写的例子如下:Addr addressPntr pointerClk clockRst reset3. 用名字前加小写n表示低电平有效高电平有效的信号不得以下划线表示短暂的引擎信号建议采用高有效如 nRst, nTrdy, nIrdy nIdsel.4. 大小写原则名字一般首字符大写 ,其余小写但parameter, integer 定义的数值名可全部用大写,两个词之间要用下划线连接或第二个单词首字母大写如 :Packet_addr, Data_in, Mem_wr , Mem_ce_Or: PacketAddr, DataIn, MemWr , MemCe5.全局信号名字中应包含信号来源的一些信息如: D_addr7:2 这里的 D 指明了地址是解码模块Decoder module中的地址.6. 同一信号在不同层次应保持一致性7. 自己定义的常数类型等用大写标识如: parameter CYCLE=100.8.避免使用保留字如 in out x z等不能够做为变量端口或模块名9. 添加有意义的后缀使信号名更加明确常用的后缀如下芯片的双向信号 -xbio芯片的三态输出 _xz芯片的漏极开路输出 _xod芯片原始输出信号 _xo芯片原始输入信号 _xi下降沿有效的寄存器 _f连到三态输出的信号 _z寄存前的信号 _next时钟信号 _ClkModules1.顶层模块应只是内部模块间的互连Verilog设计一般都是层次型的设计, 也就是在设计中会出现一个或多个模块, 模块间的调用在所难免; 可把设计比喻成树, 被调用的模块就是树叶, 没被调用的模块就是树根, 那么在这个树根模块中, 除了内部的互连和模块的调用外, 尽量避免再做逻辑, 如:不能再出现对reg变量赋值等, 这样做的目的是为了更有效的综合, 因为在顶层模块中出现中间逻辑 ,Synopsys 的design compiler 就不能把子模块中的逻辑综合到最优;2. 每一个模块应在开始处注明文件名功能描述引用模块设计者设计时间及版权信息等如 / =========================== \Filename ﹕Author ﹕whqDescription ﹕File descriptionCalled by ﹕Top moduleRevision History ﹕time yy-mm-ddRevisionEmailCopyrightc1999,~~~~~~~~~~~~~ ,All right reserved/ =========================== \3. 不要对Inpu t进行驱动, 在module 内不要存在没有驱动的信号, 更不能在模块端口中出现没有驱动的输出信号, 避免在仿真或综合时产生warning, 干扰错误定位4. 每行应限制在80个字符以内以保持代码的清晰美观和层次感一条语句占用一行如果较长,超出80个字符则要换行;5. 电路中调用的 module 名用 Uxx 标示; 向量大小表示要清晰, 采用基于名字name_based 的调用而非基于顺序的 order_based;Instance U Instance2.DataOut DOUT ,.DataIn DIN ,.Cs_ Cs_;6. 用一个时钟的上沿或下沿采样信号, 不能一会儿用上沿, 一会儿用下沿; 如果既要用上沿又要用下沿, 则应分成两个模块设计; 建议在顶层模块中对Clock做一非门,在层次模块中如果要用时钟下沿就可以用非门产生的PosedgeClk_ , 这样的好处是在整个设计中采用同一种时钟沿触发, 有利于综合; 基于时钟的综合策略7. 在模块中增加注释对信号, 参量, 引脚, 模块, 函数及进程等加以说明, 便于阅读与维护;8. Module名要用大写标示, 且应与文件名保持一致;如 Module DFF_ASYNC_RSTReset,Clk,Data,Qout;严格芯片级模块的划分只有顶层包括IO引脚pads, 中间层是时钟产生模块, JTAG, 芯片的内核CORE,这样便于对每个模块加以约束仿真, 对时钟也可以仔细仿真;模块输出寄存器化对所有模块的输出加以寄存如图1 使得输出的驱动强度和输入的延迟可以预测, 从而使得模块的综合过程更简单- 输出驱动的强度都等于平均的触发器驱动强度图19.将关键路径逻辑和非关键路径逻辑放在不同模块保证DC可以对关键路径模块实现速度优化, 而对非关键路径模块实施面积优化在;同一模块DC无法实现不同的综合策略,将相关的组合逻辑放在同一模块,有助于DC对其进行优化因为DC通常不能越过模块的边界来优化逻辑;Net and Register1. 一个reg变量只能在一个always语句中赋值2. 向量有效位顺序的定义一般是从大数到小数尽管定义有效位的顺序很自由, 但如果采用毫无规则的定义势必会给作者和读代码的人带来困惑 ,如 Data-4: 0, 则 LSB0-1-2-3-4MSB, 或 Data0: 4 则LSB43210MSB 这两种情况的定义都不太好, 推荐Data4: 0这种格式的定义;3.对net和register类型的输出要做声明在PORT中;如果一个信号名没做声明 Verilog 将假定它为一位宽的wire变量;4. 线网的多种类型; 寄存器的类型;Expressions1. 用括号来表示执行的优先级尽管操作符本身有优先顺序, 但用括号来表示优先级对读者更清晰, 更有意义;If alpha < beta && gamma >= delta.... 比下面的表达更合意2. 用一个函数function来代替表达式的多次重复如果代码中发现多次使用一个特殊的表达式 ,那么就用一个函数来代替, 这样在以后的版本升级时更便利, 这种概念在做行为级的代码设计时同样使用, 经常使用的一组描述可以写到一个任务task中;IF 语句1. 向量比较时比较的向量要相等当比较向量时 verilog将对位数小的向量做0 扩展以使它们的长度相匹配它的自动扩展为隐式的建议采用显示扩展这个规律同样适用于向量同常量的比较Reg Abc7:0;Reg Bca3:0;......If Abc= = {4’b0, Bca}begin.......If Abc= = 8’b0 begin2. 每一个If 都应有一个else 和它相对应在做硬件设计时, 常要求条件为真时执行一种动作而条件为假时执行另一动作即使认为条件为假不可能发生, 没有else可能会使综合出的逻辑和,RTL级的逻辑不同;如果条件为假时不进行任何操作, 则用一条空语句;always Condbeginif CondDataOut<= DataIn;End3. 应注意If ..else if ...else if ...else 的优先级4. 如果变量在If-else 或case 语句中做非完全赋值则应给变量一个缺省值;即V1 = 2’b00;V2 =2’b00;V3 = 2’b00;If a = = b beginV1 = 2’b01; case语句通常综合成一级多路复用器图的右边部分, 而if-then-else则综合成优先编码的串接的多个多路复用器, 如图的左边部分通常使用case 语句要比if 语句快, 优先编码器的结构仅在信号的到达有先后时使用; 条件赋值语句也能综合成多路复用器, 而case 语句仿真要比条件赋值语句快;2 所有的Case 应该有一个default case允许空语句Default : ;Writing functions1. 在function的最后给function赋值Function CompareVectors; 函数中避免使用全局变量否则容易引起HDL行为级仿真和门级仿真的差异;如function ByteCompareinput 15:0 Vector1input 15:0 Vector2input 7:0 Lengthbeginif ByteSelVerilog 支持两种赋值过程赋值procedural 和连续赋值continuous;; 过程赋值用于过程代码 initial, always, task or function 中给reg 和 integer 变量tim\realtimereal赋值, 而连续赋值一般给wire 变量赋值;2. Always 敏感表敏感表要完整, 如果不完整, 将会引起仿真和综合结果不一致always d or Clrif Clrq = 1'b0;else if eq = d;以上语句在行为级仿真时e的变化将不会使仿真器进入该进程,导致仿真结果错误3. Assign/deassign 仅用于仿真加速仅对寄存器有用4. Force/release 仅用于debug 对寄存器和线网均有用5. 避免使用Disable6.对任何reg赋值用非阻塞赋值代替阻塞赋值 reg 的非阻塞赋值要加单位延迟但异步复位可加可不加 =与 =的区别Always posedge Clkor negedge Rst_BeginIf Rst_ Combinatorial Vs Sequential Logic1. 如果一个事件持续几个时钟周期 ,设计时就用时序逻辑代替组合逻辑;如 Wire Ct_24_e4; Last over several clock cyclesAssign Ct_24_e4= count8bit7:0>= 8’h24 & count8bit7:0<= 8’he4;那么这种设计将综合出两个8 比特的加法器而且会产生毛刺, 对于这样的电路, 要采用时序设计, 代码如下;Reg Ct_24_e4;Always poseddge Clk or negedge Rst_BeginIf Rst_Ct_24_e4<= 1’b0;Else if count8bit7:0= = 8’he4Ct_24_e4<= u_dly1’b0;Else if count8bit7:0= = 8’h23Ct_24_e4<= u_dly1’b1;Esle;2. 内部总线不要悬空在default状态要把它上拉或下拉Wire OE_default;Assign OE_default= oe1| oe2| oe3;Assign bus31:0= oe1 Data131:0:oe2 Data231:0:oe3 Data331:0:oe_default 32’h0000_0000 :32’hzzzz_zzzz;为了保持代码的可读性, 常用“`define”做常数声明2. 把“`define”放在一个独立的文件中参数 parameter 必须在一个模块中定义, 不要传替参数到模块仿真测试向量例外“`define”可以在任何地方定义, 要把所有的“`define”定义在一个文件中. 在编译原代码时首先要把这个文件读入, 如果希望宏的作用域仅在一个模块中, 就用参数来代替;对更新的内容更新要做注释2. 在语法块的结尾做标记..End ..End ..Endfunction每一个模块都应在模块开始处做模块级的注释, 参考前面标准模块头;4. 在模块端口列表中出现的端口信号都应做简要的功能描述;VerilogHDL状态机的状态分配;VerilogHDL描述状态机时必须由parameter分配好状态,这与VHDL不同 VHDL状态机状态可以在综合时分配产生;2. 组合逻辑和时序逻辑分开用不同的进程组合逻辑包括状态译码和输出, 时序逻辑则是状态寄存器的切换;3. 必须包括对所有状态都处理, 不能出现无法处理的状态, 使状态机失控;4. Mealy机的状态和输入有关,而Moore机的状态转换和输入无关Mealy 状态机的例子如下:...reg CurrentState, NextState, Out1;Parameter S0=0,S1=1;always posedge Clkor negedge Rst_在for-loop中包括不变的表达式浪费运算时间for i=0;i<4;i=i+1beginSig1= Sig2;DataOuti= DataIni;endfor-loop中第一条语句始终不变,浪费运算时间.2. 资源共享问题条件算子中不存在资源共享如z = cond a + b : c + d;必须使用两个加法器;而等效的条件if-then-else语句则可以资源共享如:if Condz = a + b;elsez = c + d;只要加法器的输入端复用,就可以实现加法器的共享,使用一个加法器实现3. 由于组合逻辑的位置不同而引起过多的触发器综合如下面两个例子moduleCOUNT AndBits, Clk, Rst;Output Andbits;Input Clk,Rst;Reg AndBits;4. 谨慎使用异步逻辑module COUNT Z, Enable, Clk, Rst;Output 2:0 Z;Input Rst,Enable,Clk;reg2:0 Z;always posedge Clkbeginif RstbeginZ <= u_dly1'b0;endelse if Enable == 1'b1 beginIf Z == 3'd7 beginZ <= u_dly1'b0;Endelse beginZ <= u_dlyZ + 1'b1;endEndElse ;End际的运用中要加以避免.module COUNT Z, Enable, Clk, Rst;Output 2:0 Z;Input Rst,Enable,Clk;Reg 2:0 Z;对组合逻辑的描述有多种方式 ,其综合结果是等效的c = a &b;等效于c3:0 = a3:0 & b3:0;等效于c3 = a3 & b3;c2 = a2 & b2;c1 = a1 & b1;c0 = a0 & b0;等效于for i=0; i<=3; i= i+ 1ci= ai& bi;可以选择简洁的写法.6. 考虑综合的执行时间通常会推荐将模块划分得越小越好, 事实上要从实际的设计目标面积和时序要求出发好的时序规划和合适的约束条件要比电路的大小对综合时间的影响要大, 要依照设计的目标来划分模块, 对该模块综合约束的scripts也可以集中在该特性上, 要选择合适的约束条件, 过分的约束将导致漫长的综合时间最好在设计阶段就做好时序规划通过综合的约束scripts来满足时序规划 ;这样就能获得既满足性能的结果, 又使得综合时间最省, 从代码设计讲 500~5000行的长度是合适的;7. 避免点到点的例外所谓点到点例外 Point-to-point exception 就是从一个寄存器的输出到另一个寄存器的输入的路径不能在一个周期内完成多周期路径就是其典型情况, 多周期路径比较麻烦在静态时序分析中要标注为例外, 这样可能会因为人为因素将其他路径错误地标注为例外, 从而对该路径没有分析造成隐患避免使用多周期路径 ;如果确实要用, 应将它放在单独一个模块, 并且在代码中加以注释;8. 避免伪路径False path伪路径是那些静态时序分析 STA 认为是时序失败, 而设计者认为是正确的路径; 通常会人为忽略这些warning, 但如果数量较多时, 就可能将其他真正的问题错过了;9. 避免使用Latch使用Latch 必须有所记录, 可以用All_registers -level_sensitive 来报告设计中用到的Latch; 不希望使用Latch时, 应该对所有输入情况都对输出赋值, 或者将条件赋值语句写全, 如在if语句最后加一个else, case语句加defaults;当你必须使用Latch时, 为了提高可测性, 需要加入测试逻辑;不完整的if和case语句导致不必要的latch的产生, 下面的语句中, DataOut会被综合成锁存器; 如果不希望在电路中使用锁存器, 它就是错误;always Condbeginif CondDataOut<= DataInend10. 避免使用门控时钟使用门控时钟Gated clock不利于移植, 可能引起毛刺, 带来时序问题, 同时对扫描链的形成带来问题; 门控钟在低功耗设计中要用到, 但通常不要在模块级代码中使用; 可以借助于Power compiler来生成, 或者在顶层产生;11. 避免使用内部产生的时钟在设计中最好使用同步设; 如果要使用内部时钟, 可以考虑使用多个时钟; 因为使用内部时钟的电路要加到扫描链中比较麻烦 ,降低了可测性, 也不利于使用约束条件来综合;12. 避免使用内部复位信号模块中所有的寄存器最好同时复; 如果要使用内部复位, 最好将其相关逻辑放在单独的模块中, 这样可以提高可阅读性;13. 如果确实要使用内部时钟, 门控时钟, 或内部的复位信号将它们放在顶层将这些信号的产生放在顶层的一个独立模块这样所有的子模块分别使用单一的时钟和复位信号一般情况下内部门控时钟可以用同步置数替代例如:module COUNT Reset Enable Clk Qout module COUNT Reset EnableClk Qoutinput Reset Enable Clk input Reset Enable Clkoutput 2:0 Qout output 2:0 Qoutreg2:0 Qout reg2:0 Qoutwire GATED_Clk= Clk& Enable always posedge Clkbeginif Reset beginalways posedge GATED_Clkor posedgeReset Qout= 1'b0begin endif Reset begin else if Enable == 1'b1 beginQout= 1'b0 if Qout== 3'd7 beginend Qout= 1'b0else begin endif Qout== 3'd7 begin else beginQout=1'b0 Qout= Qout+ 1'b1end endelse begin endQout= Qout+ 1'b1 endend endmoduleendendendmodule6 附录Module 编写示例/ \Filename ﹕Author ﹕Description ﹕Called by ﹕Revision History ﹕mm/dd/yyRevisionEmail ﹕Company ﹕ HuaweiTechnology .IncCopyrightc1999, HuaweiTechnology Inc,All right reserved \ /Module module_nameOutput_ports,.;Module_name2 Uinstance_name2...;lkClk, .CLRZClr, .DData, .out;.EndlockClock,.ResetReset,.QoutQout;initialbeginClock = 1'b0;Reset =1'b1;5CYCReset = 1'b0;5CYCReset = 1'b1;5000CYC$fclosefout;$finish;endinitialbegin$shm_open"";$shm_probe"AS";fout=$fopen"";endalways CYCClock = ~ Clock;//输出数据到文件always posedgeClockbegin$fwritefout,"%d %b\n",Qout,Qout;endendmodulea ;在testbench 中避免使用绝对的时间, 如20,15 或CYC+15 等, 应该在文件前面使用parameter定义一些常量,使得时间的定义象CYC+OFF0的形式,便于修改;b ;观测结果可以输出到波形文件或数据文件生成波形文件可以用simwave观测结果比较直观而生成数据文件则既可以快速定位也可以通过编写的小程序工具对它进行进一步的处理;c ;对大的设计的顶层仿真一般不要对所有信号跟踪波形文件会很大仿真时间延长可以有选择的观测一些信号;。

veriloga语法规则

veriloga语法规则

Verilog是一种硬件描述语言,用于描述数字电路和系统。

以下是Verilog语法规则的一些要点:
标识符:Verilog中的标识符由字母、数字和下划线组成,且第一个字符必须是字母或下划线。

标识符区分大小写。

数据类型:Verilog中有多种数据类型,包括wire、reg、int、parameter等。

wire类型用于表示线网,reg类型用于表示寄存器。

赋值语句:Verilog中的赋值语句使用“=”操作符,例如“a = b”。

运算符:Verilog中有多种运算符,包括算术运算符、逻辑运算符、关系运算符等。

控制结构:Verilog中有条件语句、循环语句等控制结构。

模块:Verilog中的模块是自顶向下的设计方法的核心,用于描述数字电路和系统。

模块的语法包括模块声明、端口声明、内部信号声明、过程块和实例化等部分。

时序控制:Verilog中的时序控制使用非阻塞赋值和延迟表达式。

参数:Verilog中的参数用于在模块之间传递值。

任务和函数:Verilog中的任务和函数用于执行特定的操作。

注释:Verilog中的注释使用“//”或“/* */”进行注释。

这些是Verilog语法规则的一些要点,如果您想了解更多细节,建议参考Verilog的相关书籍或文档。

高通的绝密Verilog编码规范(中文版)verilogco

高通的绝密Verilog编码规范(中文版)verilogco

Verilog编码规范2.编写可综合的RTL级Verilog 模块代码时必须遵守的要点:2.1 不允许在代码中出现的语句要点:⚫不允许在可综合的设计代码中使用`Define 来定义参数, 应该使用参数Parameter来定义。

`Define只用于编写不可综合的仿真测试模块。

⚫不允许使用UDP ( 用户定义的原语元件)⚫不允许在可综合代码中出现逻辑反馈环路,否则会生成不可预知的逻辑电路。

⚫只允许用Verilog2001 中的always (*) 来生成组合逻辑,其他Verilog 2001语法在可综合模块中目前都不建议采用。

2.2 建议尽量采用的要点⚫用高电平有效的硬件异步复位reset。

⚫用高电平有效的同步软件复位reset。

⚫尽可能使用高电平有效信号,不使用低电平有效信号(除某些总线、器件有特殊要求外)。

只有复位信号reset 在特定情况下可以设置为低电平有效信号。

⚫尽可能使用assign语句设计组合逻辑。

⚫模块之间数据交换总线应该尽量用多路器实现。

尽量不使用三态总线。

三态总线只用于对外接口或者顶层内部总线。

⚫模块中的每个输出信号原则上必须通过寄存器输出。

任何不通过寄存器输出的信号必须加以注释,注意防止出现反馈回路。

⚫尽量合并源代码,使其简洁明了,不要试图依靠综合器的功能。

⚫case语句和if else语句必须保证其完整性,即所有分支项应该完全列出,case语句应该加缺省项(default),if语句应该有对应的else项。

⚫使用参数(parameter)作为可变化的常数,例如总线的位宽。

⚫端口声明的顺序--在保证先输入再输出的基础上按如下顺序clocks,resets,control signals,address bus,data bus⚫端口和连接端口的信号尽量同名。

⚫注释应尽量靠近被注释的语句。

大段的注释必须用由注释符号组成的边框/////////////// 围绕。

⚫代码中的所有常数都应该使用参数(parameter),将这些参数的定义放在一个独立的文件中,然后在设计模块中用`include 宏命令将其包含。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Verilog代码编写风格
一. 强调Verilog代码编写风格的必要性。

强调Verilog代码编写规范,经常是一个不太受欢迎的话题,但却是非常有必要的。

每个代码编写者都有自己的编写习惯,而且都喜欢按照自己的习惯去编写代码。

与自己编写风格相近的代码,阅读起来容易接受和理解。

相反和自己编写风格差别较大的代码,阅读和接受起来就困难一些。

曾有编程大师总结说,一个优秀的程序员,能维护的代码长度大约在1万行数量级。

代码的整洁程度,很大程度上影响着代码的维护难度。

遵循代码编写规范书写的代码,很容易阅读、理解、维护、修改、跟踪调试、整理文档。

相反代码编写风格随意的代码,通常晦涩、凌乱,会给开发者本人的调试、修改工作带来困难,也会给合作者带来很大麻烦。

(实际上英文Coding Style有另一层涵义,更偏重的是,某一个电路,用那一种形式的语言描述,才能将电路描述得更准确,综合以后产生的电路更合理。

本文更偏重的是,编写Verilog 代码时的书写习惯。


二. 强调编写规范的宗旨。

缩小篇幅
提高整洁度
便于跟踪、分析、调试
增强可读性,帮助阅读者理解
便于整理文档
便于交流合作
三. 变量及信号命名规范。

1. 系统级信号的命名。

系统级信号指复位信号,置位信号,时钟信号等需要输送到各个模块的全局信号;系统信号以字符串Sys开头。

2. 低电平有效的信号后一律加下划线和字母n。

如:SysRst_n;FifoFull_n;
3. 经过锁存器锁存后的信号,后加下划线和字母r,与锁存前的信号区别。

如CpuRamRd 信号,经锁存后应命名为CpuRamRd_r。

低电平有效的信号经过锁存器锁存后,其命名应在_n后加r。

如CpuRamRd_n信号,经锁存后应命名为CpuRamRd_nr
多级锁存的信号,可多加r以标明。

如CpuRamRd信号,经两级触发器锁存后,应命名为CpuRamRd_rr。

4. 模块的命名。

在系统设计阶段应该为每个模块进行命名。

命名的方法是,将模块英文名称的各个单词首字母组合起来,形成3到5个字符的缩写。

若模块的英文名只有一个单词,可取该单词的前3个字母。

各模块的命名以3个字母为宜。

例如:
Arithmatic Logical Unit模块,命名为ALU。

Data Memory Interface模块,命名为DMI。

Decoder模块,命名为DEC。

5. 模块之间的接口信号的命名。

所有变量命名分为两个部分,第一部分表明数据方向,其中数据发出方在前,数据接收方在后,第二部分为数据名称。

两部分之间用下划线隔离开。

第一部分全部大写,第二部分所有具有明确意义的英文名全部拼写或缩写的第一个字母大写,其余部分小写。

举例:CPUMMU_WrReq,下划线左边是第一部分,代表数据方向是从CPU模块发向存储器管理单元模块(MMU)。

下划线右边Wr为Write的缩写,Req是Request的缩写。

两个缩写的第一个字母都大写,便于理解。

整个变量连起来的意思就是CPU发送给MMU的写请求信号。

模块上下层次间信号的命名也遵循本规定。

若某个信号从一个模块传递到多个模块,其命名应视信号的主要路径而定。

6. 模块内部信号:
模块内部的信号由几个单词连接而成,缩写要求能基本表明本单词的含义;
单词除常用的缩写方法外(如:Clock->Clk, Write->Wr, Read->Rd等),一律取该单词的前几个字母(如:Frequency->Freq, Variable->Var 等);
每个缩写单词的第一个字母大写;
若遇两个大写字母相邻,中间添加一个下划线(如DivN_Cntr);
举例:SdramWrEn_n;FlashAddrLatchEn;
四. 编码格式规范。

1. 分节书写,各节之间加1到多行空格。

如每个always,initial语句都是一节。

每节基本上完成一个特定的功能,即用于描述某几个信号的产生。

在每节之前有几行注释对该节代码加以描述,至少列出本节中描述的信号的含义。

2. 行首不要使用空格来对齐,而是用Tab键,Tab键的宽度设为4个字符宽度。

行尾不要有多余的空格。

3. 注释。

使用//进行的注释行以分号结束;
使用/* */进行的注释,/*和*/各占用一行,并且顶头;
例:
// Edge detector used to synchronize the input signal;
4. 空格的使用:
不同变量,以及变量与符号、变量与括号之间都应当保留一个空格。

Verilog关键字与其它任何字符串之间都应当保留一个空格。

如:
Always @ (……)
使用大括号和小括号时,前括号的后边和后括号的前边应当留有一个空格。

逻辑运算符、算术运算符、比较运算符等运算符的两侧各留一个空格,与变量分隔开来;单操作数运算符例外,直接位于操作数前,不使用空格。

使用//进行的注释,在//后应当有一个空格;注释行的末尾不要有多余的空格。

例:
assign SramAddrBus = { AddrBus[31:24], AddrBus[7:0] };
assign DivCntr[3:0] = DivCntr[3:0] + 4’b0001;
assign Result = ~Operand;
5. 同一个层次的所有语句左端对齐;Initial、always等语句块的begin关键词跟在本行的末尾,相应的end关键词与Initial、always对齐;这样做的好处是避免因begin独占一行而造成行数太多;
例:
always @ ( posedge SysClk or negedge SysRst begin
if( !SysRst DataOut <= 4'b0000;
else if( LdEn begin
DataOut <= DataIn;
End
else DataOut <= DataOut + 4'b0001;
end
6. 不同层次之间的语句使用Tab键进行缩进,每加深一层缩进一个Tab;
8. 在endmodule,endtask,endcase等标记一个代码块结束的关键词后面要加上一行注释说明这个代码块的名称;
9. 在task名称前加tsk以示标记。

在function的名称前加func以示标记。

例如:
task tskResetSystem;
……
endtask //of tskResetSystem
五.小结:
以上列出的代码编写规范无法覆盖代码编写的方方面面,还有很多细节问题,需要在实际编写过程中加以考虑。

并且有些规定也不是绝对的,需要灵活处理。

并不是律条,但是在一个项目组内部、一个项目的进程中,应该有一套类似的代码编写规范来作为约束。

总的方向是,努力写整洁、可读性好的代码。

相关文档
最新文档