VERILOG语言编写要求规范Word文件下载.docx
- 文档编号:22066390
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:21
- 大小:122.01KB
VERILOG语言编写要求规范Word文件下载.docx
《VERILOG语言编写要求规范Word文件下载.docx》由会员分享,可在线阅读,更多相关《VERILOG语言编写要求规范Word文件下载.docx(21页珍藏版)》请在冰豆网上搜索。
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
Email﹕wuhaoqian1gmail.
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<
beta&
gamma>
=delta)...(判断逻辑应是化简过后的最简形式!
)
2.用一个函数(function)来代替表达式的多次重复
如果代码中发现多次使用一个特殊的表达式,那么就用一个函数来代替,这样在以后的版本升级时更便利,这种概念在做行为级的代码设计时同样使用,经常使用的一组描述可以写到一个任务(task)中。
5.1.5IF语句
1.向量比较时比较的向量要相等
当比较向量时verilog将对位数小的向量做0扩展以使它们的长度相匹配它的自动
扩展为隐式的建议采用显示扩展这个规律同样适用于向量同常量的比较
RegAbc[7:
0];
RegBca[3:
......
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;
Elseif(a==c)begin
//V1isnotassigned
V3=2’b11;
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<
Length)&
Equal)begin
If(Vector2[i]!
==1’bx)begin
If(Vector1[i]!
==Vector2[i])
Equal=0;
Else;
i=i+1;
CompareVectors=Equal;
Endfunction//compareVectors//比较器
3.函数中避免使用全局变量
否则容易引起HDL行为级仿真和门级仿真的差异。
如
functionByteCompare
input[15:
0]Vector1
0]Vector2
input[7:
0]Length
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_)
If(!
Rst_)//prioritizethe“ifconditions”inifstatement
Rega<
=0;
//non_blockingassignment
Regb<
Elseif(Soft_rst_all)
=#u_dly0;
//addunitdelay
Elseif(Load_init)
=#u_dlyinit_rega;
=#u_dlyinit_regb;
Else
=#u_dlyRega<
<
1;
=#u_dlySt_1;
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_)
Rst_)
Ct_24_e4<
=1’b0;
Elseif(count8bit[7:
0]==8’he4)
=#u_dly1’b0;
0]==8’h23)
=#u_dly1’b1;
Esle;
2.部总线不要悬空在default状态要把它上拉或下拉
WireOE_default;
AssignOE_default=!
(oe1|oe2|oe3);
Assignbus[31:
0]=oe1?
Data1[31:
0]:
oe2?
Data2[31:
oe3?
Data3[31:
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
=PENDING))begin//drivedata
End//drivedata
//Commentend<
unit>
withthenameofthe<
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;
CurrentState<
=#u_dlyNextState;
always(In1orIn2orCurrentState)
//outputandstatevectordecode(combinational)
case(CurrentState)
S0:
begin
NextState<
=#u_dlyS1;
Out1<
=#u_dly1'
S1:
if(In1)begin
=#u_dlyS0;
=#u_dlyIn2;
elsebegin
=#u_dly!
In2;
endcase
endmodule
5.2代码编写中容易出现的问题
1.在for-loop中包括不变的表达式浪费运算时间
for(i=0;
i<
4;
i=i+1)
Sig1=Sig2;
DataOut[i]=DataIn[i];
for-loop中第一条语句始终不变,浪费运算时间.
2.资源共享问题
条件算子中不存在资源共享如
z=(cond)?
(a+b):
(c+d);
必须使用两个加法器;
而等效的条件if-then-else语句则可以资源共享如:
z=a+b;
z=c+d;
只要加法器的输入端复用,就可以实现加法器的共享,使用一个加法器实现
3.由于组合逻辑的位置不同而引起过多的触发器综合如下面两个例子
moduleCOUNT(AndBits,Clk,Rst);
OutputAndbits;
InputClk,
Rst;
RegAndBits;
//internalreg
Reg[2:
0]Count;
always(posedgeClk)begin
if(Rst)
Count<
=#u_dlyCount+1;
End//endif
AndBits<
=#u_dly&
Count;
End//endalways
在进程里的变量都综合成触发器了,有4个;
OutputAndBits;
always(posedgeClk)begin//synchronous
=#u_dlyCount+1;
always(Count)begin//asynchronous
AndBits=&
Endmodule//endCOUNT
组合逻辑单开,只有3个触发器.
4.谨慎使用异步逻辑
moduleCOUNT(Z,Enable,Clk,Rst);
Output[2:
0]Z;
InputRst,
Enable,
Clk;
reg[2:
if(Rst)begin
Z<
elseif(Enable==1'
b1)begin
If(Z==3'
d7)begin
=#u_dlyZ+1'
b1;
是同步逻辑,而下例则使用了组合逻辑作时钟,以及异步复位.实际的运用中要加以避免.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VERILOG 语言 编写 要求 规范