VERILOG语言编写规范.docx

上传人:b****6 文档编号:7590293 上传时间:2023-01-25 格式:DOCX 页数:22 大小:123.57KB
下载 相关 举报
VERILOG语言编写规范.docx_第1页
第1页 / 共22页
VERILOG语言编写规范.docx_第2页
第2页 / 共22页
VERILOG语言编写规范.docx_第3页
第3页 / 共22页
VERILOG语言编写规范.docx_第4页
第4页 / 共22页
VERILOG语言编写规范.docx_第5页
第5页 / 共22页
点击查看更多>>
下载资源
资源描述

VERILOG语言编写规范.docx

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

VERILOG语言编写规范.docx

VERILOG语言编写规范

VERILOG语言编写规范

1目的

本规范的目的是提高书写代码的可读性可修改性可重用性,优化代码综合和仿真结果,指导设计工程师使用VerilogHDL规范代码和优化电路,规范化公司的ASIC设计输入从而做到

1.逻辑功能正确2。

可快速仿真3。

综合结果最优如果是hardwaremodel)4.可读性较好.

2范围

本规范涉及VerilogHDL编码风格,编码中应注意的问题,Testbench的编码等。

本规范适用于Verilogmodel的任何一级(RTLbehavioral,gate_level),也适用于出于仿真,综合或二者结合的目的而设计的模块。

3定义

VerilogHDL:

Verilog硬件描述语言

FSM:

有限状态机

伪路径:

静态时序分析(STA)认为是时序失败,而设计者认为是正确的路径

4引用标准和参考资料

下列标准包含的条文通过在本标准中引用而构成本标准的条文在标准出版时所示版本

均为有效所有标准都会被修订使用本标准的各方应探讨使用下列标准最新版本的可能性

ActelHDLCodingStyleGuider

SunMicrosystems

Revision1。

0

VerilogStyleandCodingGuidelines

5规范内容

5.1Verilog编码风格

本章节中提到的Verilog编码规则和建议适应于Verilogmodel的任何一级(RTLbehavioral,gate_level)也适用于出于仿真,综合或二者结合的目的而设计的模块。

5.1.1命名规范

选择有意义的信号和变量名,对设计是十分重要的.命名包含信号或变量诸如出处,有效状态等基本含义下面给出一些命名的规则。

1。

用有意义而有效的名字

有效的命名有时并不是要求将功能描述出来如

For(I=0;I<1024;I=I+1)

Mem[I]〈=#132'b0;

For语句中的循环指针I就没必要用loop_index作为指针名。

2。

用连贯的缩写

长的名字对书写和记忆会带来不便,甚至带来错误采用缩写时应注意同一信号在模块中的一致性。

缩写的例子如下:

Addraddress

Pntrpointer

Clkclock

Rstreset

3。

用名字前加小写n表示低电平有效高电平有效的信号不得以下划线表示短暂

的引擎信号建议采用高有效

如nRst,nTrdy,nIrdynIdsel。

4。

大小写原则

名字一般首字符大写,其余小写(但parameter,integer定义的数值名可全部用大写),两个词之间要用下划线连接(或第二个单词首字母大写)

如:

Packet_addr,Data_in,Mem_wr,Mem_ce_

Or:

PacketAddr,DataIn,MemWr,MemCe

5.全局信号名字中应包含信号来源的一些信息

如:

D_addr[7:

2]这里的D指明了地址是解码模块(Decodermodule)中的地址。

6.同一信号在不同层次应保持一致性

7.自己定义的常数类型等用大写标识

如:

parameterCYCLE=100。

8.避免使用保留字

如inoutxz等不能够做为变量端口或模块名

9.添加有意义的后缀使信号名更加明确常用的后缀如下

芯片的双向信号-xbio

芯片的三态输出_xz

芯片的漏极开路输出_xod

芯片原始输出信号_xo

芯片原始输入信号_xi

下降沿有效的寄存器_f

连到三态输出的信号_z

寄存前的信号_next

时钟信号_Clk

5。

1。

2Modules

1.顶层模块应只是内部模块间的互连

Verilog设计一般都是层次型的设计,也就是在设计中会出现一个或多个模块,模块间的调用在所难免。

可把设计比喻成树,被调用的模块就是树叶,没被调用的模块

就是树根,那么在这个树根模块中,除了内部的互连和模块的调用外,尽量避免再做逻辑,如:

不能再出现对reg变量赋值等,这样做的目的是为了更有效的综合,因为在顶层模块中出现中间逻辑,Synopsys的designcompiler就不能把子模块中的逻辑综合到最优。

2。

每一个模块应在开始处注明文件名功能描述引用模块设计者设计时间及版

权信息等

如/*===========================*\

Filename﹕SPI_M.v

Author﹕whq

Description﹕Filedescription

Calledby﹕Topmodule

RevisionHistory﹕timeyy-mm-dd

Revision1.0

Email﹕wuhaoqian1@gmail。

com

Copyright(c)1999,~~~~~~~~~~~~~,Allrightreserved

/*===========================*\

3.不要对Input进行驱动,在module内不要存在没有驱动的信号,更不能在模块端口中出现没有驱动的输出信号,避免在仿真或综合时产生warning,干扰错误定位

4。

每行应限制在80个字符以内以保持代码的清晰美观和层次感

一条语句占用一行如果较长,超出80个字符则要换行。

5.电路中调用的module名用Uxx标示.向量大小表示要清晰,采用基于名字(name_based)的调用而非基于顺序的(order_based).

InstanceUInstance2(

DataOut(DOUT),

DataIn(DIN),

Cs_(Cs_)

);

6.用一个时钟的上沿或下沿采样信号,不能一会儿用上沿,一会儿用下沿。

如果既要用上沿又要用下沿,则应分成两个模块设计。

建议在顶层模块中对Clock做一非门,在层次模块中如果要用时钟下沿就可以用非门产生的PosedgeClk_,这样的好处是在整个设计中采用同一种时钟沿触发,有利于综合。

基于时钟的综合策略

7.在模块中增加注释

对信号,参量,引脚,模块,函数及进程等加以说明,便于阅读与维护。

8.Module名要用大写标示,且应与文件名保持一致。

如ModuleDFF_ASYNC_RST(

Reset,

Clk,

Data,

Qout

);

严格芯片级模块的划分

只有顶层包括IO引脚(pads),中间层是时钟产生模块,JTAG,芯片的内核(CORE),这样便于对每个模块加以约束仿真,对时钟也可以仔细仿真。

模块输出寄存器化

对所有模块的输出加以寄存(如图1)使得输出的驱动强度和输入的延迟可以预测,从而使得模块的综合过程更简单

-输出驱动的强度都等于平均的触发器驱动强度

图1

9。

将关键路径逻辑和非关键路径逻辑放在不同模块

保证DC可以对关键路径模块实现速度优化,而对非关键路径模块实施面积优化在。

同一模块DC无法实现不同的综合策略,将相关的组合逻辑放在同一模块,有助于DC对其进行优化因为DC通常不能越过模块的边界来优化逻辑。

5.1。

3NetandRegister

1。

一个reg变量只能在一个always语句中赋值

2.向量有效位顺序的定义一般是从大数到小数

尽管定义有效位的顺序很自由,但如果采用毫无规则的定义势必会给作者和读代码

的人带来困惑,如Data[-4:

0],则LSB[0][-1][—2][-3][-4]MSB,或Data[0:

4]则

LSB[4][3][2][1][0]MSB这两种情况的定义都不太好,推荐Data[4:

0]这种格式的定

义。

3。

对net和register类型的输出要做声明在PORT中.如果一个信号名没做声明Verilog将假定它为一位宽的wire变量。

4。

线网的多种类型。

寄存器的类型。

5。

1.4Expressions

1。

用括号来表示执行的优先级

尽管操作符本身有优先顺序,但用括号来表示优先级对读者更清晰,更有意义。

If((alpha〈beta)&&(gamma>=delta))..。

比下面的表达更合意

If(alpha

..(判断逻辑应是化简过后的最简形式!

2。

用一个函数(function)来代替表达式的多次重复

如果代码中发现多次使用一个特殊的表达式,那么就用一个函数来代替,这样在以后的版本升级时更便利,这种概念在做行为级的代码设计时同样使用,经常使用的一组描述可以写到一个任务(task)中。

5。

1。

5IF语句

1。

向量比较时比较的向量要相等

当比较向量时verilog将对位数小的向量做0扩展以使它们的长度相匹配它的自动

扩展为隐式的建议采用显示扩展这个规律同样适用于向量同常量的比较

RegAbc[7:

0];

RegBca[3:

0];

...

If(Abc=={4’b0,Bca})begin

.。

.。

.。

If(Abc==8'b0)begin

2.每一个If都应有一个else和它相对应

在做硬件设计时,常要求条件为真时执行一种动作而条件为假时执行另一动作即使认为条件为假不可能发生,没有else可能会使综合出的逻辑和,RTL级的逻辑不同。

如果条件为假时不进行任何操作,则用一条空语句。

always@(Cond)

begin

if(Cond)

DataOut〈=DataIn;

End

//Else

以上语句DataOut会综合成锁存器。

3.应注意If.。

elseif。

.。

elseif。

.。

else的优先级

4.如果变量在If—else或case语句中做非完全赋值则应给变量一个缺省值。

V1=2’b00;

V2=2’b00;

V3=2’b00;

If(a==b)begin

V1=2’b01;//V3isnotassigned

V2=2’b10;

End

Elseif(a==c)begin

V2=2’b10;//V1isnotassigned

V3=2’b11;

End

Else

5。

1.6case语句

1。

case语句通常综合成一级多路复用器(图的右边部分),而if-then—else则综合成优先编码的串接的多个多路复用器,如图的左边部分通常使用case语句要比if语句快,优先编码器的结构仅在信号的到达有先后时使用。

条件赋值语句也能综合成多路复用器,而case语句仿真要比条件赋值语句快。

2所有的Case应该有一个defaultcase允许空语句

Default:

;

5.1.7Writingfunctions

1。

在function的最后给function赋值

FunctionCompareVectors;//(Vector1,Vector2,Length)

Input[199:

0]Vector1,Vector2;

Input[31:

0]Length;

//localvariables

Integeri;

RegEqual;

Begin

i=0;

Equal=1;

While((i

If(Vector2[i]!

==1’bx)begin

If(Vector1[i]!

==Vector2[i])

Equal=0;

Else;

End

i=i+1;

End

CompareVectors=Equal;

End

Endfunction//compareVectors//比较器

3.函数中避免使用全局变量

否则容易引起HDL行为级仿真和门级仿真的差异.如

functionByteCompare

input[15:

0]Vector1

input[15:

0]Vector2

input[7:

0]Length

begin

if(ByteSel)

//comparetheupperbyte

else

//comparethelowerbyte

end

endfunction//ByteCompare

中使用了全局变量ByteSel可能无意在别处修改了,导致错误结果.最好直接在端口加以定义。

(注意函数与任务的调用均为静态调用.)

5。

1.8Assignment

1。

Verilog支持两种赋值过程赋值(procedural)和连续赋值(continuous。

过程赋值用于过程代码(initial,always,taskorfunction)中给reg和integer变量tim\realtime

real赋值,而连续赋值一般给wire变量赋值。

2。

Always@(敏感表)敏感表要完整,如果不完整,将会引起仿真和综合结果不一致

always@(dorClr)

if(Clr)

q=1'b0;

elseif(e)

q=d;

以上语句在行为级仿真时e的变化将不会使仿真器进入该进程,导致仿真结果错误

3.Assign/deassign仅用于仿真加速仅对寄存器有用

4.Force/release仅用于debug对寄存器和线网均有用

5.避免使用Disable

6。

对任何reg赋值用非阻塞赋值代替阻塞赋值reg的非阻塞赋值要加单位延迟但异

步复位可加可不加=与《=的区别

Always@(posedgeClkornegedgeRst_)

Begin

If(!

Rst_)//prioritizethe“ifconditions”inifstatement

Begin

Rega〈=0;//non_blockingassignment

Regb<=0;

End

Elseif(Soft_rst_all)

Begin

Rega〈=#u_dly0;//addunitdelay

Regb〈=#u_dly0;

End

Elseif(Load_init)

Begin

Rega〈=#u_dlyinit_rega;

Regb<=#u_dlyinit_regb;

End

Else

Begin

Rega<=#u_dlyRega〈<1;

Regb<=#u_dlySt_1;

End

End//endRega,Regbassignment。

5。

1。

9CombinatorialVsSequentialLogic

1.如果一个事件持续几个时钟周期,设计时就用时序逻辑代替组合逻辑。

如WireCt_24_e4;//itccarriesinfo.Lastoverseveralclockcycles

AssignCt_24_e4=(count8bit[7:

0]>=8’h24)&(count8bit[7:

0]<=8’he4);

那么这种设计将综合出两个8比特的加法器而且会产生毛刺,对于这样的电路,要采用时序设计,代码如下;

RegCt_24_e4;

Always@(poseddgeClkornegedgeRst_)

Begin

If(!

Rst_)

Ct_24_e4〈=1’b0;

Elseif(count8bit[7:

0]==8'he4)

Ct_24_e4<=#u_dly1'b0;

Elseif(count8bit[7:

0]==8’h23)

Ct_24_e4〈=#u_dly1’b1;

Esle;

2。

内部总线不要悬空在default状态要把它上拉或下拉

WireOE_default;

AssignOE_default=!

(oe1|oe2|oe3);

Assignbus[31:

0]=oe1?

Data1[31:

0]:

oe2?

Data2[31:

0]:

oe3?

Data3[31:

0]:

oe_default?

32’h0000_0000:

32’hzzzz_zzzz;

5。

1。

10Macros

1。

为了保持代码的可读性,常用“`define”做常数声明

2。

把“`define”放在一个独立的文件中参数(parameter)必须在一个模块中定义,不要传替参数到模块(仿真测试向量例外)“`define”可以在任何地方定义,要把所有的“`define”定义在一个文件中.在编译原代码时首先要把这个文件读入,如果希望宏的作用域仅在一个模块中,就用参数来代替。

5.1.11Comments

1.对更新的内容更新要做注释

2.在语法块的结尾做标记

//style1

If(~OE_&&(state!

=PENDING))begin

.。

End//ifenable==tureandready

//style2--—identicallablesonbeginandend

If(~OE_&&(state!

=PENDING))begin//drivedata

.。

.

End//drivedata

//Commentendwiththenameofthe

FunctionCalcparity//Data,ParityErr

..。

Endfunction//Calcparity

3。

每一个模块都应在模块开始处做模块级的注释,参考前面标准模块头.

4.在模块端口列表中出现的端口信号都应做简要的功能描述。

5。

1.12FSM

1。

VerilogHDL状态机的状态分配.

VerilogHDL描述状态机时必须由parameter分配好状态,这与VHDL不同VHDL状态机状态可以在综合时分配产生。

2.组合逻辑和时序逻辑分开用不同的进程

组合逻辑包括状态译码和输出,时序逻辑则是状态寄存器的切换.

3.必须包括对所有状态都处理,不能出现无法处理的状态,使状态机失控。

4.Mealy机的状态和输入有关,而Moore机的状态转换和输入无关

Mealy状态机的例子如下:

..。

regCurrentState,NextState,Out1;

ParameterS0=0,S1=1;

always@(posedgeClkornegedgeRst_)

//statevectorflip-flops(sequential)

if(!

Reset)

CurrentState=S0;

else

CurrentState〈=#u_dlyNextState;

always@(In1orIn2orCurrentState)

//outputandstatevectordecode(combinational)

case(CurrentState)

S0:

begin

NextState〈=#u_dlyS1;

Out1〈=#u_dly1'b0;

end

S1:

if(In1)begin

NextState〈=#u_dlyS0;

Out1〈=#u_dlyIn2;

end

elsebegin

NextState〈=#u_dlyS1;

Out1〈=#u_dly!

In2;

end

endcase

endmodule

5.2代码编写中容易出现的问题

1。

在for—loop中包括不变的表达式浪费运算时间

for(i=0;i<4;i=i+1)

begin

Sig1=Sig2;

DataOut[i]=DataIn[i];

end

for-loop中第一条语句始终不变,浪费运算时间。

2。

资源共享问题

条件算子中不存在资源共享如

z=(cond)?

(a+b):

(c+d);

必须使用两个加法器;

而等效的条件if-then—else语句则可以资源共享如:

if(Cond)

z=a+b;

else

z=c+d;

只要加法器的输入端复用,就可以实现加法器的共享,使用一个加法器实现

3.由于组合逻辑的位置不同而引起过多的触发器综合如下面两个例子

moduleCOUNT(AndBits,Clk,Rst);

OutputAndbits;

InputClk,

Rst;

RegAndBits;

//internalreg

Reg[2:

0]Count;

always@(posedgeClk)begin

begin

if(Rst)

Count〈=#u_dly0;

else

Count<=#u_dlyCount+1;

End//endif

AndBits<=#u_dly&Count;

End//endalways

endmodule

在进程里的变量都综合成触发器了,有4个;

moduleCOUNT(AndBits,Clk,Rst);

OutputAndBits;

InputClk,

Rst;

RegAndBits;

//internalreg

Reg[2:

0]Count;

always@(posedgeClk)begin//synchronous

if(Rst)

Count〈=#u_dly0;

else

Count<=#u_dlyCount+1;

End//endalways

always@(Count)begin//asynchronous

AndBits=&Count;

End//endalways

Endmodule//endCOUNT

组合逻辑单开,只有3个触发器。

4。

谨慎使用异步逻辑

moduleCOUNT(Z,Enable,Clk,Rst);

Output[2:

0]Z;

InputRst,

Enable,

Clk;

reg[2:

0]Z;

always@(posedgeClk)begin

if(Rst)begin

Z〈=#u_dly1’b0;

end

elseif(Enable==1’b1)begin

If(Z==3'd7)begin

Z<=#u_dly1'b0;

End

elsebegin

Z〈=#u_dlyZ+1'b1;

end

End

Else;

End//endalways

Endmodule//endCOUNT

是同步逻辑,而下例则使用了组合逻辑作时钟,以及异步复位。

实际的运用中要加以避免.

moduleCOUNT(Z,Enable,Clk,Rs

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

当前位置:首页 > 高等教育 > 工学

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

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