Verilog 代码风格总结供参考.docx

上传人:b****4 文档编号:3733275 上传时间:2022-11-25 格式:DOCX 页数:13 大小:24.35KB
下载 相关 举报
Verilog 代码风格总结供参考.docx_第1页
第1页 / 共13页
Verilog 代码风格总结供参考.docx_第2页
第2页 / 共13页
Verilog 代码风格总结供参考.docx_第3页
第3页 / 共13页
Verilog 代码风格总结供参考.docx_第4页
第4页 / 共13页
Verilog 代码风格总结供参考.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

Verilog 代码风格总结供参考.docx

《Verilog 代码风格总结供参考.docx》由会员分享,可在线阅读,更多相关《Verilog 代码风格总结供参考.docx(13页珍藏版)》请在冰豆网上搜索。

Verilog 代码风格总结供参考.docx

Verilog代码风格总结供参考

窗体顶端

[转]Verilog代码风格-供参考

Description 

本文主要是收集一些重要的Verilogcodingstyle。

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

Text 

Theorderofmodulesignals 

一个modulesignal顺序如下(由左至右):

Input 

clocksignals(clk_*) 

set/resetsignals(set_*,rst_*) 

enable/disblesignals(en_*,dis_*) 

read/writeenablesignals(we_*,re_*,rw_*) 

controlsignals(i_*) 

addresssignals(i_*) 

datasignals(i_*) 

Output 

clocksignals(o_clk_*) 

set/resetsignals(o_set_*,o_rst_*) 

enable/disablesignals(o_en_*,o_dis_*) 

controlsignals(o_*) 

addresssignals(o_*) 

datasignals(o_*) 

In/Out 

controlsignals(io_*) 

addresssignals(io_*) 

datasignals(io_*) 

NamingRule 

以下的namignrule为个人使用的规则。

命名方式分类 

底线分隔型:

xxx_yyy_zzz 

大写底线分隔型:

XXX_YYY_ZZZ 

首字大写型:

AbcDefGhi 

首字小写型:

avcDefGhi 

各种元素所使用的命名 

文件名称:

底线分隔型,Ex:

xxx_yyy_zzz.v 

module名称:

底线分隔型,Ex:

xxx_yyy_zzz 

moduleinstance名称:

底线分隔型,Ex:

xxx_yyy_zzz 

localwire名称:

底线分隔型:

Ex:

xxx_yyy_zzz 

localreg名称:

底线分隔型,Ex:

xxx_yyy_zzz 

inputsignal名称:

前置i_的底线分隔型,Ex:

i_xxx_yyy_zzz 

outputsignal名称:

前置o_的底线分隔型,Ex:

o_xxx_yyy_zzz 

input/outputsignal名称:

前置io_的底线分隔型,Ex:

io_xxx_yyy_zzz 

常数名称:

大写底线分隔型,`XXX_YYY_ZZZ 

parameter参数名称:

大写底线分隔型,Ex:

XXX_YYY_ZZZ 

block名称:

大写底线分隔型,Ex:

XXX_YYY_ZZZ 

特殊讯号名称 

单一的clocksignal:

clk 

多个clocksignal:

clk_xxx 

负缘触发的clocksignal:

clk_n,clk_xxx_n 

单一的resetsignal:

rst 

多个resetsignal:

rst_xxx 

负缘触发的resetsignal:

rst_n,rst_xxx_n 

单一的setsignal:

set 

多个setsignals:

set_xxx 

负缘触发的setsignals:

set_n,set_xxx_n 

致能讯号:

en_xxx 

除能讯号:

dis_xxx

ProceduralAssignments 

使用指引

在撰写sequentiallogic时,使用nonblockingassignment。

 

在撰写latches电路时,使用nonblockingassignment。

 

在alwaysblock中撰写conbinationallogic时,使用blockingassignment。

 

在同一个alwaysblock中同时撰写sequential及combinationallogic时,一律使用nonblockingassignment。

 

别在同一个alwaysblock中混合使用nonblocking及blockingassignment。

 

别在两个以上的alwaysblock中对同一个变量设定数值。

 

使用$strobe来显示由nonblockingassignment所给定的变量。

 

不要对assignment使用#0延迟设定。

 

在proceduralassignment中,LHS(等式的左边LeftHandSide?

)一定要是reg型态。

非proceduralassignment一定是net的型态。

 

常用的style 

Combinationlogic 

在alwaysblock中,如果使用combinationlogic,应当使用blockingassignment.

//Allinputsusedwithinalwaysblockshouldbelistedinsensitivelist.

always@(in1orin2orin3)

begin

 xxx=in1^in2&in3;

end

Sequentiallogic 

在alwaysblock中,如果使用sequentiallogic,应当使用nonblockingassignment.

//Synchronousreset.Therst_nisNOTinsensitivelist.

always@(posedgeclk)

 begin

   if(~rst_n)

       begin

     xxx<=`INIT_VAL;

       end

   else

       begin

     xxx<=yyy;

       end

 end

//Asynchronousreset.Therst_nISinsensitivelist.

always@(posedgeclkornegedgerst_n)

 begin

   if(~rst_n)

     begin 

       xxx<=`INIT_VAL;

     end

   else

     begin

       xxx<=yyy;

     end

 end

Delay的建模 

Combinationlogic 

建模没有delay时,使用blockingassignment(ex:

a=b;) 

建模有惯性(inertial)delay时(即glitch不会传到后面的电路中)。

使用delayedevaluationblockingassignments(#10a=b;). 

建模传输(transport)delay时(即glitch也会一并传到后面的电路中)。

使用delayedassignmentnonblockingassignments(ex:

a<=#10b;). 

Sequentiallogic 

建模没有delay时,使用non-blockingassignments(ex:

q<=d;). 

建模有delay时,使用delayedassignmentnonblockingassignments(ex:

q<=#10d;).

FiniteStateMachine 

MooreFSM:

输出与输入没有直接关系。

 

由两个alwaysblock构成,一个是sequentialblock用来处理状态的变化。

另一个为combinationalblock用来处理状态与输入之间的关系。

注意,在sequentialblock中应全部使用nonblockingassignment。

在combinationalblock中应使用blockingassignment。

在某些简单的case中,combinationalblock也可直接由continuousassignment来取代。

下面的范例是一般简单的FSM。

 

//Sequentialalwaysblock.

always@(posedgeclkorposedgerst)

 begin

   if(rst)

     state<=STATE_IDLE;

   else

     state<=next;

 end

//Combinationalalwaysblock.

always@(stateorinput1orinput2...orinputN)

 begin

   next=STATE_IDLE;

   outputs=OUTPUT_IDLE:

   case(state)

     STATE_IDLE:

 

       begin

         ...//thelogictodeterminethenextstate.

         next=STATE_?

?

?

?

?

;

       end

     STATE_?

?

?

?

?

:

       begin

         ...//thelogictodeterminethenextstate.

         next=STATE_?

?

?

?

?

;        

         outputs=?

?

?

?

?

;//Theoutputofthisstate.

       end

   endcase

 end

针对simplifiedone-hotencoding的FSM范例:

//Sequentialalwaysblock.

always@(posedgeclkorposedgerst)

 begin

   if(rst)

     state<=n'b0;

     state[STATE_DEFAULT]<=1'b0;

   else

     state<=next;

 end

//Combinationalalwaysblock.

always@(stateorinput1orinput2...orinputN)

 begin

   next=n'b0;

   outputs=OUTPUT_DEFAULT:

   case(1'b1) //synopsysfull_caseparallel_case

     state[STATE_DEFAULT]:

       begin

         ...//thelogictodeterminethenextstate.

         next[STATE_?

?

?

?

?

]=1'b1;

       end

     state[STATE_?

?

?

?

?

]:

       begin

         ...//thelogictodeterminethenextstate.

         next[STATE_?

?

?

?

?

]=1'b1;

         outputs=?

?

?

?

?

;//Theoutputofthisstate.

       end

     //synopsystranslate_off

     default:

 

       $display("Badstate!

!

");

     //synopsystranslate_on

   endcase

 end

针对simplifiedone-hotwithzero-idleencoding的FSM:

//Sequentialalwaysblock.

always@(posedgeclkorposedgerst)

 begin

   if(rst)

     state<=n'b0;

   else

     state<=next;

 end

//Combinationalalwaysblock.

always@(stateorinput1orinput2...orinputN)

 begin

   next=n'b0;

   outputs=OUTPUT_DEFAULT:

   case(1'b1) //synopsysfull_caseparallel_case

     ~|state:

 //IDLE

       begin

         ...//thelogictodeterminethenextstate.

         next[STATE_?

?

?

?

?

]=1'b1;

       end

     state[STATE_?

?

?

?

?

]:

       begin

         ...//thelogictodeterminethenextstate.

         next[STATE_?

?

?

?

?

]=1'b1;

         outputs=?

?

?

?

?

;//Theoutputofthisstate.

       end

     //synopsystranslate_off

     default:

       $display("Badstate!

!

");

     //synopsystranslate_on

   endcase

 end

MealyFSM:

输出与输入有直接关系。

 

MealyFSM的作法与上面的范例相类似。

唯一的不同在于outputs的指定,需加上与input相关的逻辑判断。

例如:

case(state) //synopsysparallel_casefull_case

 ...

 STATE_?

?

?

?

?

:

   begin

   ...

   if(input1&input2)

     outputs=?

?

?

?

?

;

   else

     outputs=?

?

?

?

?

;

   end

 //synopsystranslate_off

 default:

   $display("BadFSM.");

 //synopsystranslate_on

 default    

endcase

Datapath 

参考:

CodingGuidelinesforDatapathSynthesis.

有号数的计算:

若有需要关于有号数的计算,应当利用Verilog2001所提供的signed及$signed()机制。

input  signed[7:

0] a,b;

output  signed[15:

0] o;

assign o=a*b;

or

input    [7:

0] a,b;

output    [15:

0] o;

wire signed[15:

0] o_sgn;

assugb o_sgn=$signed(a)*$signed(b);

assign o=$unsigned(o_sgn);

正负号的扩展:

应多加利用Verilog的implicitysignedextension,避免手动进行转换。

input signed[7:

0] a,b;

input signed[8:

0] o;

assign o=a+b; //Verilog会自动进行符号的扩展。

有号数与无号数的混合计算:

不要在同一个verilog叙述中进行有号数与无号数的计算。

应该要分成个别独立的叙述。

在一个verilog叙述中只要有一个无号数的操作数,整个算式将被当成无号数进行计算。

 

input    [7:

0] a;

input  signed [7:

0] b;

output signed [15:

0] o;

//Don'tdothis:

assigno=a*b;

//The$signed({1'b0,a})canconverttheunsignednumbertosignednumber.

assigno=$signed({1'b0,a})*b;

input signed [7:

0] a;

output signed [15:

0] o;

//Don'tdothis:

assigno=a*8'b10111111;

//Use$signed()systemtask

assigno=a*$signed(8'b10111111);

//orsbkeyword.

assigno=a*8'sb10111111;

part-select运算过后的操作数是无号数。

就算是选择的范围包含整个register或wire。

 

input signed [7:

0] a;

input signed [7:

0] b;

output signed [15:

0] o1,o2;

//Don'tdothis:

assigno1=a[7:

0];

assign o1=a;

//Don'tdothis:

assigno2=a[6:

0]*b;

assign o2=$signed(a[6:

0])+b;

Verilog的位宽度规则:

技巧就是要善用LHS来限制位宽度。

利用中介的讯号线来作为限制宽度用的LHS操作数。

 

在没有特别设定的状况下,Verilog会依据LHS的操作数宽度来决定RHS操作数的宽度。

 

input [7:

0] a;

input [7:

0] b;

output [8:

0] o;

assigno=a+b; //9bits.

对一个表示式而言,最大宽度的操作数决定了整体的宽度。

 

input signed [3:

0] a;

input signed [7:

0] b;

output   [11:

0] o;

wire signed [11:

0] o_sgn;

//Don'tdothis:

assigno=$unsigned(a*b); 这将会是一个8bit的运算。

因为在刮号内的bits数是依据最大操作数b的宽度决定的。

assign  o_sgn=a*b; //12bits。

因为bit数是依据LHS宽度决定的。

assgigno=$unsigned(o_sgn);

input [7:

0] a;

input [7:

0] b;

input [7:

0] c;

input [7:

0] d;

output o;

wire [15:

0] tmp1;

wire [15:

0] tmp2;

//Don'tdothis:

assigno=(a+b)>(c*d);因为(a+b)及(c*d)都会是8bit的结果。

assign tmp1=a+b; //16bits.

assign tmp2=c*d; //16bits.

assign o=tmp1>tmp2; //1bit.

 一.文件命名

规则1:

每个文件中只包含一个设计单元

理由:

便于修正.

规则2:

文件命名协定

<设计单元名称>.<扩展名>

理由:

便于理解设计单元constructs及文件内容.

如:

spooler.v   //spooler模块的同步Verilog代码描述

规则3.模拟和数字Verilog文件

每个单一文件必须包含:

(1)模拟(analog)Verilog(用.va文件后缀);或

(2)数字Verilog(用.v文件后缀);或(3)清晰的模\数混合Verilog(用.va文件后缀).

理由:

模拟的编译器也许不能操纵数字的架构;反之亦然.

二.HDL编码项目命名

规则4:

允许的字符集

命名中必须包含字母,数字或下划线[A-Z,a-z,_](见规则5)

例外:

不允许使用连续的下划线.

理由:

双下划线在硬件竞争中是不工作的.

规则5:

命名的首字符

命名必须以字母开头,而不是数字或下划线(见规则4)

理由:

以数字或下划线开头的命名,可能会引起工具冲突.

规则6:

所有命名必须是唯一的无关项

理由:

 在Verilog(语法敏感)和VHDL(语法不敏感)中的设计转换中,很可能受语法不敏感的设计风格影响.

规则7:

信号的一致性

理由:

和VHDL相比,Verilog和许多支持VHDL的工具都一样是语法敏感.及时辨别信号的类型(如:

低电平有效的信号或时钟)有助于调试.

规则8:

常量,参数和标签区块要大写

理由:

提供了一种可以辨别那些在仿真中不需要经过数据转换的实体的机制.

规则9:

信号,constructs和实例化标签要小写

理由:

从在仿真中数据不变化的实体中区别信号和constructs,以及在设计中保持一致的视觉和感觉.

规则10:

有意义的信号和变量名称

小写的名称必须包含信号和变量的意图.

理由:

描述是什么,而不是怎样去做,有助于理解设计.

如:

data_bus,set_priority

规则11:

有意义的常量名称

常量名称一定要描述常量的意图.根据意图可以很明显地看出常量的类型,及不是端口的名称.常量需大写.

理由:

有意义的名称对于常量来说,非常重要.

如:

好的名称:

SBUS_DATA_BITS,MEMORY_WIDTH,CLK_PERIOD

如:

差的名称:

ADDRESS_SIZE并不明晰,当它指的是数的位宽或地址空间的长度

规则12:

有意义的construct名称

construct的名称如functions,modules,tasks等,必须根据它们要做什么而不是怎么样去做来命名.construct名称必须小写.

理由:

描述是什么,而不是怎样去做,有助于理解设计.

规则13:

有意义的实例化标签

实例化标签要根据construct指定的要实现什么,而不是怎样去做来命名.

理由:

描述是什么,而不是怎样去做,有助于理解设计.

如:

addr_decode,bit_stuff,sbus_if

规则14:

用下划线分隔包含许多单词的名称

理由:

增加可读性

如:

ram_addr

规则15:

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

当前位置:首页 > 求职职场 > 简历

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

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