VerilogHDL程序编写规范2.docx

上传人:b****8 文档编号:10154052 上传时间:2023-02-08 格式:DOCX 页数:37 大小:167.34KB
下载 相关 举报
VerilogHDL程序编写规范2.docx_第1页
第1页 / 共37页
VerilogHDL程序编写规范2.docx_第2页
第2页 / 共37页
VerilogHDL程序编写规范2.docx_第3页
第3页 / 共37页
VerilogHDL程序编写规范2.docx_第4页
第4页 / 共37页
VerilogHDL程序编写规范2.docx_第5页
第5页 / 共37页
点击查看更多>>
下载资源
资源描述

VerilogHDL程序编写规范2.docx

《VerilogHDL程序编写规范2.docx》由会员分享,可在线阅读,更多相关《VerilogHDL程序编写规范2.docx(37页珍藏版)》请在冰豆网上搜索。

VerilogHDL程序编写规范2.docx

VerilogHDL程序编写规范2

 

VerilogHDL程序编写规范

 

版本号:

1.0

编写者:

刘兆庆

状态:

试用

发布日期:

2008年月日

 

摘要

本文定义了VerilogHDLRTL编码规则和指南,按照本文介绍的方法进行编码,有助于使VerilogHDLRTL代码具有良好的可读性、可修改性和可重用性,同样也有助于综合和仿真。

文档控制表

表1文档控制表

文档

标题:

版本号:

发行号:

VerilogHDL程序编写规范

V1.0

实行日期:

关键词

2008年6月1日

编辑工具

名称

Microsoft®OfficeWord2003

模板:

作者情况

原作者:

刘兆庆

协作者:

罗杰俊

校对:

审核:

文档状态表

表2文档状态表

标题

VerilogHDL程序编写规范

ID号

版本号

发行号

日期

更改原因

1.0

0

2008.03.20

试发布

1.0

1

2008.06.01

补充内容

目录

1概述1

1.1目的1

1.2所面向的对象1

1.3文档的组织结构2

2基本编码规范2

2.1命名规范:

2

2.2源文件中信息头书写规范4

2.3注释书写规范5

2.4代码书写规范5

2.5端口声明规范6

2.6端口映射和常量映射8

2.7立即数的使用8

2.8编辑器9

2.9语法规则9

2.9.1模块9

2.9.2变量10

2.9.3参数11

2.9.4function和task12

2.9.5其他规则12

3时钟和复位信号设计规范13

3.1避免使用混合时钟沿13

3.2避免使用时钟缓冲器14

3.3避免使用门控时钟14

3.4避免在模块内部产生时钟15

3.5门控时钟和低功耗设计15

3.6避免在模块内部产生复位信号16

3.7复位逻辑功能17

3.8一位同步器17

3.9多位同步器17

4可综合性编码规范18

4.1寄存器描述18

4.2避免产生锁存器18

4.3避免产生组合电路反馈。

19

4.4完整的敏感量列表20

4.5阻塞和非阻塞赋值21

4.6case语句和if-else语句23

4.7时序逻辑电路的描述24

4.8对关键信号的描述25

4.9避免使用延时语句25

5可综合划分规范25

5.1所有输出采用寄存器输出25

5.2将相关的组合逻辑放在同一模块26

5.3将具有不同设计目标的部分分配到不同模块中27

5.4异步逻辑27

5.5避免时序设计中的例外情况27

5.6消除顶层模块中的胶连逻辑电路28

1概述

本文的编码指南基于几个基本原则。

最基本的目标是,要求开发出来的RTL代码简单,而且规范。

简单且规范的结构比复杂的结构更容易设计、编码、验证和综合。

在满足功能和性能的前提下,这个可重用设计的目标是尽可能简单。

编码指南详细描述了以下几个值得推荐的建议。

●使用简单结构、基本类型和简单的时钟规划;

●使用一致的编码方式,一致的命名习惯,一致的过程和状态机;

●使用规则的划分方法,所有模块采用寄存器输出,模块大小尽量一致;

●为了让RTL代码容易理解,编码中使用注释,使用有意义的命名方式,使用常用或参数代替立即数。

在这些原则指导下,开发者能够更容易编码,达到理想的性能、功能、时序、功耗和面积。

1.1目的

本文档的目的是定义一个VerilogHDL编码标准,编写VerilogHDL代码时必须遵循该标准的规定。

这一标准的提出,可以为VerilogHDL编程者提供以下便利:

●避免犯低级错误

●便于不同程序员的维护

●便于程序的移植和复用

●便于阅读和理解

●具有一致的书写风格

另外请注意,本文档都不能替代VerilogHDL的编程书籍。

1.2所面向的对象

本文档面向哈尔滨工业大学自动化测试与控制研究所所有从事VerilogHDLRTL程序编写的人员。

1.3文档的组织结构

文档组织如下:

1.概述;

2.基本编码规范,同时给出解释和例子;

3.时钟和复位信号设计规范,同时给出解释和例子;

4.可综合性编码规范,同时给出解释和例子;

5.可综合划分规范,同时给出解释和例子;

2基本编码规范

2.1命名规范:

在整个设计中一直遵守命名习惯有助于提高代码的可读性,同样也有助于代码的调试、检查、维护和修改。

具体规范如下:

规则——为设计开发命名习惯。

以文档的形式规定下来,并在整个设计中一直遵守命名习惯。

指南——变量名、模块名、参数和端口名使用小写字母。

指南——常数(`define)使用大写字母。

指南——信号、端口、函数和参数命名时采用有意义的名称。

例如,不要用ra命名RAM地址,而应该用ram_addr。

指南——对时钟信号使用一致的命名方式,例如clk。

如果有一个以上的时钟信号,使用clk作为所有时钟信号的前缀(例如:

clk1、clk2或clk_interface等)。

指南——对于低有效信号,信号名称尾部用下划线加小写字母n,如_n。

指南——对复位信号使用一致的命名方式,如rst。

如果复位信号是低有效的,则可以使用诸如rst_n的名称。

规则——在描述多个总线时,使用由大到小的位排列顺序。

即[x:

0]或[0:

x]。

使用一致的位排列顺序有助于提高代码可读性,减少总线连接时偶尔发生的位排列顺序不一致的情况,如例1.1所示。

例1.1使用[x:

0]端口声明

moduleDW_addinc#(

parameterwidth=8

)(

input[width-1:

0]a,

input[width-1:

0]b,

inputci,

input[width-1:

0]sum,

output[width-1:

0]co

);

endmodule

指南——连接的端口与信号使用相同或类似的名称(例如,a=>a;或a=>a_int)。

指南——模块的端口命名必须根据不同类型选择不同的后缀,命名格式为“*_后缀”,后缀如表1所示。

表1信号命名习惯

后缀

用法

*_a

异步信号(例如,addr_strobe_a)

*_pn

第n段中使用的信号(例如,enable_p2)

*_nxt

数据在被寄存到相同名称的寄存器之前

*_i

输入信号

*_o

输出信号

*_n

低电平或下降沿有效的信号

如果端口信号具有多个属性,则后缀为多个后缀的任意顺序组合。

例如:

输入输出信号的后缀应选为“io”或“oi”,模块端口命名的其他规则,和变量命名相同。

2.2源文件中信息头书写规范

规则——在每一个源文件的开始,都必须包含一段注释,信息头部分。

脚本文件也是如此。

信息头部分必须包含:

a.法律声明,包括机密性、版权、复制时的限制

b.文件名

c.作者

d.模块功能和主要特征描述

e.文件创建日期

f.修改历史记录,包括日期、修改者姓名及对变化的描述

例1.2展示了一个源文件头。

例1.2一个VerilogHDL源文件头

//Thisconfidentialandproprietarysoftwaremaybeusedonlyas

//authorizedbyalicensingagreementfromSynopsysInc.

//Intheeventofpublication,thefollowingnoticeisapplicable.

//

//©COPYRIGHT1996SYNOPSYSINC.

//ALLRIGHTSRESERVED

//

//Theentirenoticeabovemustbereproducedonallauthorizedcopies.

//

//Filename:

DWpci_core.v

//Author:

张三

//Date:

09/17/96

//Version:

0.1

//Abstract:

Thisfilehastheentity,architectureandconfiguration

//ofthePCI2.1MacroCellcoremodule.

//Thecoremodulehastheinterface,config,initiator,

//andtargettop-levelmodules.

//

//ModificationHistory:

//DateByVersionChangeDescription

//=============================================

//09/17/96JDH0.1Original

//11/13/96JDHLastpre-Atriachanges

//03/04/97SKCchangesforism_ad_en_ffd_n

//andtsm_data_ffd_n

//

//=============================================

2.3注释书写规范

规则——使用注释大概地解释一下过程、函数和声明类型。

如例1.3所示。

例l.3对子类型声明注释

//CreatesubtypeINTEGER_256forbuilt-inerror

//checkingoflegalvalues.

subtypeINTEGER_256istypeintegerrange0to255;

指南——用注释解释端口、信号、变量或一组信号或变量。

注释应该放在靠近被解释的代码附近。

指南——注释采用简单容易理解的英文,不能使用中文(不同的编译器支持的中文字符不同,会产生不能识别的现象)

指南——全部使用单行注释,只有在开发调试过程中需要注释大段代码时才使用多行注释

指南——/*…/*…*/…..*/这种注释在第一个*/处结束,第二个被忽略,而且会产生语法错误,禁止出现此类注释。

指南——注释应遵循简洁、精炼的原则,禁止使用“注释段”。

指南——一些很明显的功能不需要注释,在代码后面,对关键内容注释。

指南——对过程的注释,放在整个过程的前面,而不是插入过程中,这样可以不中断代码的连贯性。

2.4代码书写规范

规则——代码按照规定格式书写,可提高代码的可读性和可维护性。

指南——每行只能写一条代码(声明或语句)。

指南——每行代码长度最好不要超过72个字符,对于超过72个字符的代码,使用回车符进行分割,在下一行中继续书写上一行的代码。

指南——使用缩进格式书写条件和循环部分代码,如例1.4所示。

例1.4一个嵌套if语句的缩进格式

if(bit_width(m+1)==2)begin

for(i==0;i

spin_j=0;

for(j==i;j

if(j>spin_j)begin

if(matrix(m)(i-1)(j)!

=wht)begin

if(j==m&&matrix(m)(i)(j)==wht)begin

matrix(m)(i)(j)=j;

elsebegin

for(k==j+1;k

if(matrix(m)(i-1)(k)!

=wht)begin

matrix(m)(i)(k)=j;

spin_j=k;

end

end//k

end

end

end

end//j

end//i

end

指南——推荐使用两个空格的缩进格式,如果缩进比较大(例如8格),那么在书写多层嵌套时,可能会遇到每行字长的限制。

指南——避免使用Tab键,在不同的编辑器中对Tab的设置不一致,可能会引起代码的某种混乱。

指南——begin必须与if,while,always,initial,for等词同行,end必须另起一行,begin…end之间的代码必须具有缩进关系

指南——在RTL源文件中,不要使用HDL保留字命名任何信号或变量。

2.5端口声明规范

规则——在声明端口时应遵循逻辑顺序,并且在整个设计中保持一致的声明顺序

指南——每行声明一个端口,紧跟着注释的内容(注释最好在同一行内)。

指南——对于每个接口,端口声明的顺序如下:

输入(input):

时钟(Clocks)

复位(Resets)

使能(Enables)

其它控制信号(Othercontrolsignals)

数据和地址线(Dataandaddresslines)

输出(output):

时钟(Clocks)

复位(Resets)

使能(Enables)

其它控制信号(Othercontrolsignals)

数据(Data)

例1.5端口排列顺序

moduleDW_usbd(

//ExternalClockGenerator:

Inputs

refclk,//MainReferenceClock

//ScanTestInterface:

Inputs

scan_mode,//Forscantesting

//UTMIPHY(type2/3)Interface:

Inputs

//Enables

phy23_rxvalid,//SpecifiesthevaliddataLSB

phy23_rxvalidh,//SpecifiesthevaliddataonMSB

phy23_txready,//Validdatawillbepolled

//Othercontrolsignals

phy23_linestate,//Currentstateofdp,dmlines

phy23_rxerror,//Errorinreceiveddata

phy23_rxactive,//PHYneedstotransmitdata

//Dataandaddresslines

phy23_rx_data,//16_bitunidirreceivedatabus

//UTMIPHY(type2/3)Interface:

Outputs

//Reset

phy23_reset,//ResetsignaltothePHY

//Enables

phy23_suspend_n,//SuspendsignaltothePHY

phy23_xcvr_select,//SelectHSorFStransceriver

//ApplicationInterface:

Inputs

//Resets

app_rst_n,//Asynchronousreset

app_test_mode,//BypassingUSBreset

//APPRegisterR/WInterface:

Inputs

//Enables

app_16bit,//APP16_bitr/waccess

app_reg_sel,//APPRegisterInterfaceselect

//Othercontrolsignals

app_rd_n,//APPregister-readcommand

app_wr_n,//APPregister-writecommand

//Dataandaddresslines

app_addr,//APPRegisteraddressbus

app2usb_data,//APPWrite-databus

//APPRegisterR/WInterface:

Outputs

//Othercontrolsignals

usb2app_drdy,//Datareadyindicationfrom

//DW_usbdtoAPP

//Dataandaddresslines

usb2app_data,//APPRead-Databus

//

//

//

);//DW_usbd

2.6端口映射和常量映射

规则——使用显式的方式映射端口和常量,保持端口名称之间一一对应,不能使用顺序映射方法。

如例1.5所示。

例1.6使用名称对应的映射方法

DW_ram_r_w_s_dff

#(.ram_width(`ram_data_width+`ram_be_data_width),

.fifo_depth(`fifo_depth),

.tco

(1))

U_int_txf_ram(

.clk(refclk),

.rst_n(txfifo_ram_reset_n),

.cs_n(1`b0),

.wr_n(txfifo_wr_en_n),

.rd_addr(txfifo_rd_addr),

.wr_addr(txfifo_wr_addr),

.data_in(txfifo_wr_data),

.data_out(txf_ram_data_out)

);

2.7立即数的使用

指南——在设计中,除0和1以外,不能使用立即数值,而使用参数或常量赋值,如例2.1中所示。

参数或常量赋值有以下优点,

●对于一个设计具有更多的灵活性;

●参数或常量值只需要在一个地方修改;

●参数可以在实例化时重载,提高模块的可重用性;

●编译器可能只支持常量类型,不支持立即数。

例1.7使用参数赋值,不要使用立即数赋值

parameterbus_size=8;

wire[bus_size–1:

0]my_in_bus;

reg[bus_size–1:

0]my_out_bus;

2.8编辑器

指南——建议使用SourceInsight软件。

2.9语法规则

2.9.1模块

指南——模块声明使用如下样式:

例1.8模块声明样式

modulewaveform_generator#(

parameterperiod=100,//注意缩进两个字符

parametertype="sine"

)(//注意括号

inputhold_i,//注意端口命名

outputreg[63:

0]value_o

);

指南——模块命名与普通变量命名类似

指南——模块实例的命名建议以模块名的一部分为前缀

指南——模块实例化时,不能采用按顺序匹配输入输出的方式,而必须使用“.端口名(端口信号)”的方式,参数也必须使用“.参数名(参数值)”方式重新设置参数值,因此模块实例化的格式和其声明的格式相似,例如:

例1.9

waveform_generator#(

.period(100),

.type("sine")

)wg_chnnal_1(

.hold_i(hold),

.value_o(value)

);

指南——每一个可以被调用的模块的最后(endmodule之前)必须给出实例化本模块的典型代码,以方便调用者复制,注释形式为/*...*/,如:

例1.10

/*

waveform_generator#(

.period(100),

.type("sine")

)wg_chnnal_1(

.hold_i(hold),

.value_o(value)

);

*/

指南——每一个模块(可综合或行为模块,包括FPGA顶层设计)必须由与之对应的testbench文件,testbench文件命名必须和模块文件名相同,扩展名使用.vt,testbench的顶层模块建议命名为“被测模块名_tb”。

指南——可综合的模块必须放在一个单独的文件里,且这个文件的文件名必须和这个模块的名字完全相同。

只有仿真文件里可以放多个模块,此时文件名应按文件作用取名,命名方法参见变量命名。

指南——所有模块的仿真时间单位和精度都规定为1ns/1ps,即所有文件的第一条语句必须为“`timescale1ns/1ps”。

2.9.2变量

指南——每一行至多只能定义一个变量

指南——变量必须以小写字母打头,只能包含小写字母和数字和用于分隔单词“_”

指南——变量命名中使用完整单词,除约定缩写以外,约定缩写如下表

完整形式

缩写

Oscillator

osc

Reset

rst

Synchronous

sync

Condition

conf

Manufacture

manf

Parameter

param

Clock

clk

Control

ctrl

Condition

cond

Counter

cntr

Configure

config/cfg

Instance

inst

chip_select

cs

有待添加

指南——如果变量的使用范围较大,建议使用对不同类型的变量使用不同的前缀,即以“前缀_”打头,如下表:

类型

前缀

integer

i

real

r

realtime

rt

time

t

event

ev

genvar

gv

reg

reg

指南——命名必须使用有意义的英文,不得使用拼音

指南——状态机变量命名建议以“state_”打头,如果模块内

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 职业教育 > 中职中专

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1