ImageVerifierCode 换一换
格式:DOCX , 页数:31 ,大小:47.85KB ,
资源ID:10215447      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/10215447.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Verilog编码规范.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Verilog编码规范.docx

1、Verilog编码规范Verilog编码规范(仅供内部使用)拟制:xxx日期:xxx审核:审核者日期:yyyy-mm-dd批准:批准者日期:yyyy-mm-dd版权所有 XX修订记录修订日期修订版本描述修订者基本原则:简单,一致,可重用。 简单指尽量使用简单的语句,尽量使用简单的设计,尽量使用简单的时钟,尽量使用简单的复位。 一致指尽量保持代码风格一致,尽量保持命名一致。 可重用指有成熟的IP尽量使用IP,设计的代码要尽量可重用。1 命名规范给信号命名就像给孩子取名字一样,有区别,有根源,有深度,还有一点,要简单,别冗长。有区别指取名字不要一样,假如大家只有一个手机号码,那这个号码还能有什么用

2、处?有根源指取名字要能象姓氏一样,让人一看就直到是张家的后代而不是李家的。有深度就是取名字要有涵义,张一,张二,张三虽然也是名字,但是请考虑一下被取名字人的感受。简单点,几十个字母长的名字,打字的和看字的都累。 大小写规则:只有parameter,define和module名称才能享受大写。 Module 名应与文件名保持一致(文件名是小写),假如不想在设计后面遇到麻烦的话。 不要尝试使用任何保留字,因为他们已经被保留了。 不要重复使用同样的名字去命名不同的数据。 (建议)对module名加”_LVx”的后缀,增强module名称的结构层次含义如:设计顶层为TOP LEVEL,即LEVEL1,

3、命名为QTRxxxx_LV1;时钟模块,IO_PAD,CORE,为LEVEL2,命名为CLK_PROC_LV2等等;CORE内子模块为LEVEL3,然后以此类推。 对于来自同一驱动源的所有时钟信号使用相同的名字。 对于低电平有效的信号,应该以_n结尾。 模块间相连端口名称要一致。 (建议)使用下表所列的命名缩写方式。全称名称clockClkresetrstclearclraddressaddrdata_indindata_outdoutinterrupt requestintread enablerdenwrite enablewrencountcntrequestreqcontrolctrl

4、arbiterarbpointerptrsegmentsegmemorymemregisterreg (建议)使用下列后缀命名方式全称添加后缀active low_nenable_enselect_selflag_flgdelay_dly 信号命名的两个词之间用下划线间隔,如ram_addr,cnt_ctrl等等 信号命名尽量不要使用孤立的、小写的英文字母L2 代码编写规范2.1 版面 语句独立成行,增加可读性和可维护性。 行的长度保持每行小于或等于72个字符。因为有的终端或打印机每行不能超过80个字符。规定72个字符是为了留出边空,提高可读性。还有一个原因是为象vi这样的编辑器留有显示行号的

5、地方。用回车来分割超过72个字符的行,并且在下一行用缩进来表示该行是前一行的继续。 缩进。用缩进来提高续行和嵌套循环的可读性。缩进采用4个空格。避免使用TAB键。不同的编辑器或用户环境使得TAB的位置差别很大,造成缩进的混乱。有一些工具可以将TAB替换成空格。 (建议)使用注释使用注释来解释端口、信号、信号组、always块、函数等。注释应该放在它所描述的代码的附近。注释应该简明扼要,并足够说明问题。避免注释杂乱。显而易见的功能不用加注释。注释关键是说明设计意图。2.2 编写代码规范 在源文件中要有文件头在源文件、script文件的开始应包含一个文件头。文件头至少应包含下列信息:文件名、作者、

6、模块的功能描述和关键特征的列表、文件产生的日期、更改记录(日期、更改者、更改的内容)。(参见代码模板sample.v) 模块名称用大写,例如:module MEM_CTRL。 端口声明时每行声明一个端口,并有注释(最好在同一行),也可对同一类型的一组端口加注释。对于时钟,复位以及其他控制信号,需要注释有效工作沿或者有效工作值 建议用下述顺序声明端口。/INPUTsclocks , / posedge activeresets , / active highenables , / active highother control signals ,Data and address lines ,

7、/OUTPUTsclocks ,resets ,enables ,other control signals ,data 在输入和输出两类端口之间留一个空行来提高可读性。如上例所示。 端口列表之后,使用parameter定义内部信号宽度以及其他参数化设置。 IO信号申明和内部信号申明要单独成行,参考sample.v文件 使用简单的语句,一般使用if else和case就能满足大部分需求,不要使用复杂的语句 常量(1)一位的控制信号采用二进制表达方式,如1b0;(2)常数位宽不可缺省;如:Bad: if (rst_n = 0) & (cnt_addr = 15)Good:if (rst_n =

8、1b0) & (cnt_addr = 5d15) 变量(1)Net and Register(a)一位位宽的wire信号的声明不可缺省(b)一个reg变量只可以在一个always语句中赋值(c)(建议)任一register的赋值加上单位延迟,对异步复位同样加上单位延迟;(d)向量有效位顺序的定义采用倒序格式,如:Data4:0(2)Memory代码中不建议使用Memory(存储器阵列),Memory只用于Testbench中,访问存储器阵列中某一向量的某一位或几位,需要通过中间变量进行。例:reg15:0 mem0:255;temp = mem33; /temp gets data at ad

9、dr 333_bit_reg = temp8:6; /get three bits of addr 33 运算符及表达式(1)表达式(a)用括号来表示执行的优先级,尽管操作符本身有优先顺序,但用括号表示优先级对读者更清晰,更有意义如:Bad: A + B ? C : D;Good: (A + B) ? C : D;(b)适当使用括号适当使用括号可以控制生成的电路结构,如Z = A + B + C + D,综合结果可能为三级加法器,而变换为Z = (A + B) + (C + D),综合结果则可能为两级加法器;(c)注意资源共享需要资源共享的部分一定要放在同一个模块的同一个always语句中,不

10、同模块不同always语句之间的代码不能实现资源共享。如:always (.)if (.) d0 = A + B;else d0 = C + D;中,DC可能只会生成一个加法器。条件算子中不存在资源共享如:z = (cond1b1)? (a+b) : (c+d);必须使用两个加法器;而等效的条件if-else语句可以资源共享,如:if (cond=1b1)z = (a+b);elsez = (c+d);只要加法器的输入端复用,就可以实现加法器的共享,使用一个加法器实现。(d)尽量采用公共子表达式如 :x=a+b+cy=d+a+b改为:z=a+bx=z+cy=d+z(2)算符(a)条件运算符r1

11、 = gate? r2 : r3;避免使用条件嵌套:r1 = (aa = 0)? (bb = 0)? r2 : r3) : r4; orr1 = aa,bb = 0? r2: aa,bb = 0? r3: aa,bb = 0? R4:r4;(b)逻辑操作符在if(),while(),()?A:B 之类的表达式中,括号中的表达式应该是一个逻辑表达式,相应的操作符应该用逻辑操作符。如:wire x,A,B; (x) ? A:B 与 (x = 1b1) ? A:B If(A&B) 与 if(A&B)=1b1) While(A=B) 与 while(A=B) 操作结果相同,但显然前者不规范。(c)乘法

12、运算符“*”对于一个变量data与常数constant相乘data * constant,如果常数不是2的整数次幂,建议先将其分解,如constant= 53 = 32 + 16 + 4 + 1 = 25 + 24 + 22 + 20,这样乘积就可以表示为变量data移位结果的相加。对于乘法运算符“*”,综合后通常得到的是乘法器,时延较大。 赋值语句(1)不要在信号列表中进行运算操作如:Bad: addr(a,b,d&e); Good: addr(a,b,c); c=d&e;(2)BLOCK赋值和NON-BLOCK赋值的使用(a)组合逻辑采用BLOCK赋值(=)如: always (dat)

13、i_dat = dat;(b)非组合逻辑(主要是寄存器)采用NON-BLOCK赋值并加delay以保证前仿真和后仿真的一致如: always (posedeg clk) q = #DEL d;(3)在同一块语句中不允许同时出现阻塞赋值和非阻塞赋值 条件语句(1)IF语句(a)向量比较时,比较的向量长度要相等,同样向量和常量比较时长度也要求匹配,长度不同时要求进行显式位扩展(verilog对位数小的向量做0扩展以使它们的长度相匹配,该扩展是隐式的)如: reg 7:0 abc; reg 3:0 def; . if (abc = 4b0,def) begin . if (abc = 8h0) be

14、gin(b)不要采用if表达式的简写形式例如: if (variable) 等同于 if (variable != 0) if (!variable) 等同于 if (variable = 0) 但后者才合乎规范(c)每个if都应该有一个else与之相对应,如果条件为假时不进行任何操作,则用一条空语句else;避免产生latch(d)if.else if.else if.else的代码书写格式如下,要注意优先级if (.) begin .endelse begin if (.) . else (.) if (.) else (.)end(d)如果变量在if-else语句中非完全赋值,则应给变量

15、一个缺省值如: if (a = b) begin v1 = 2b01; v2 = 2b10; /v3 is not assigned end else if (a = c) begin v2 = 2b10; v3 = 2b11; /v1 is not assigned endelse /default赋值 begin v1 = 2b00; v2 = 2b00; v3 = 2b00; end(2)CASE语句(a)所有的case语句都应该有一个default语句,避免产生Latch(b)(建议)不要使用casex、casez语句,综合工具不支持 循环语句(1)forever语句(2)repeat

16、语句(3)while语句(4)for语句在可以用其它语句描述电路时,建议不要采用循环语句来描述。 initial语句不要在RTL代码中出现initial 块综合会将initial块忽略,使前仿真和后仿真不一致initial begin.end always语句(1)在使用always生成组合逻辑时,敏感表要列全,敏感表中也不能包含没有用到的变量。Rule:Combinational sensitivity lists should include1)Any signal on right hand side of assignment2)Any signal in if or case exp

17、ressionFor example:.module sense_list_ex( b, c, d );/PARAMETER/INPUTSinput b;input c;input d;/OUTPUTS/INOUTS/SIGNAL DECLARATIONSwire b;wire c;wire d;reg a;/ASSIGN STATEMENTS/MAIN CODE always (b or c or d) if (b1b1) a = c & d; else if (c=1b1) a = d;endmodule /SENSE_LIST_EX (2)对带异步清零端的寄存器的定义模板always (

18、posedge clk_main or negedge rst_n) if (rst_n = 1b0) /此处统一采用rst_n = 1b0形式而不采用(! rst_n) begin /形式,对相关寄存器清0(采用 # u_dly= 赋值) . end else begin /对相关寄存器赋值(采用 # u_dly= 赋值) . end采用时钟上升沿触发。 有限状态机(FSM)(1)组合逻辑和时序逻辑分开描述; / PART 1: COMBINATERIAL LOGIC FOR NEXT STATEalways (cur_state or full_new_fr or full or have

19、_space)begin: OVC_FSM_NXT_ST case (cur_state) STDBY: begin if (full_new_fr = 1b1) nxt_state = W_BLOCK; else if (full = 1b1) nxt_state = W_DSCD; else nxt_state = cur_state; end W_BLOCK: begin if (have_space = 1b1) nxt_state = STDBY; else nxt_state = cur_state; end W_DSCD: begin if (have_space = 1b1)

20、nxt_state = STDBY; else nxt_state = W_BLOCK; end default: nxt_state = STDBY; endcaseend / OVC_FSM_NXT_ST/ PART 2: SEQUENTIAL LOGIC FOR CURRENT STATEalways (posedge clk or RST_EDGE reset)begin: OVC_FSM_ST_TRANS if(reset = RST_VALUE) cur_state = DLY W_BLOCK; else cur_state = DLY nxt_state;end / OVC_FS

21、M_ST_TRANS3 电路设计规则3.1 时钟 (建议)简单的时钟结构易于理解、分析和维护,而且容易产生好的综合结果。最好是能够有单一的全局时钟,所有寄存器都在上升沿触发。 所有子模块内部使用单一时钟单一时钟沿,如条件不满足时,必须注明原因,并提出对综合以及布线的要求。 设计中包含内部产生的时钟时,必须将所有需要的时钟在一个单独的模块中生成。 如果不得不用混合的时钟沿,在综合和时序分析时确保能满足时钟精度最差情况下的占空比。同时确保把假定的占空比写入用户手册。在多数设计中,占空比是时钟树的函数,而时钟树的插入通常又依赖于具体的工艺。使用Core的芯片设计者必须检查实际的占空比能够满足Core

22、的要求,也应该了解怎样改变综合和时序分析的策略以使得Core能够满足实际的条件。 (建议)多数基于扫描链的测试方法要求对上升沿和下降沿触发的寄存器分开处理。如果必须使用大量的上升沿和下降沿触发的寄存器,将上升沿和下降沿触发的寄存器分到不同的模块中是很有用的。这样容易确定下降沿触发的寄存器,并可将它们放到不同的扫描链中。 (建议)避免在RTL级手工实例化时钟Buffer。时钟Buffer通常是在综合以后在物理设计时插入的。在可综合的RTL代码中,时钟网络通常被认为是理想的网络,没有延时。在布局布线时,时钟树插入工具插入适当的结构,尽可能的接近理想的、平衡的时钟配布网络。一个例外情况是在顶层模块中

23、可以插入厂家提供的伪时钟Buffer,用于指明时钟树的源头和时钟树的参数。 (建议)避免在RTL级使用门控时钟或内部产生的时钟信号。门控时钟电路依赖于具体的工艺和时序。门控时钟不正确的时序可能导致假的时钟信号和误操作。不同局部时钟SKEW还会导致保持时间冲突(violation)。门控时钟还会降低电路的可测性,也使得综合的约束变得困难。多数低功耗的电路需要门控时钟,但它们不应该出现在RTL级的编码中,象Power Compiler这类工具可以自动去做。如果设计中必须使用门控时钟、内部产生的时钟或复位信号,应该让产生这些信号的电路位于设计顶层的一个独立的模块中。它将违反编码规范的地方限制在一个小

24、的范围内,有利于对这些产生电路开发特殊的测试策略。对于其他模块将可采用标准的时序分析和扫描链插入技术。3.2 复位 (建议)确保所有寄存器只被简单的复位信号所控制。最好的情况是,复位信号是1bit寄存器的输出。因为组合逻辑的输出会带有毛刺,对于异步复位电路,则会引起触发器的异常。 (建议)尽可能避免内部产生的条件复位信号。通常模块内所有寄存器应在同一时间内被复位。这种方式使得分析和设计更加简单和容易。 (建议)如果需要条件复位,设置一个单独的复位信号,并且将产生逻辑隔离于一个单独的模块。这种方式可使代码更易读,并易于综合出好的结果。 如果需要内部产生异步复位信号,必须保证所产生的异步复位信号没

25、有毛刺,最好的办法是保证异步复位信号最后为1bit触发器的输出,例如当计数器达到一个预设值时,产生异步复位信号:bad: wire reset; assign reset = (count=value);better: reg reset; always (posedge clk) reset = (count=value);3.3 避免LATCH描述组合逻辑的always块中,如果if语句缺乏else子句、case语句中各个条件所处理的变量不同都会在综合时推断出LATCH。使用下述方法可避免LATCH: 对所有的输入条件都给出输出。 保证always块敏感列表完备。敏感列表应包括:if(),

26、case()中的条件信号;所有always块中位于赋值语句右边的信号;当信号为多bit向量时,应包括向量的所有bit而不是部分。 在最终优先级的分支上使用else子句,而不用elsif。 所有的Case 应该有一个default case。 避免使用LATCH,除非能清楚地分析相关电路的时序以及毛刺带来的影响3.4 避免组合反馈 在设计中避免组合反馈电路。这种电路违背了同步设计原则,难以控制其行为,对仿真、调试和DFT都极其不利。3.5 赋值语句 在写可综合的代码时,在时序逻辑的always语句块中总是使用非阻塞赋值。否则RTL级的仿真会和门级仿真的结果不一致。 在组合逻辑的always语句块

27、中使用阻塞赋值。 同一个触发器不能在多个always块中被赋值。3.6 case语句和if-else语句 (建议)如果不需要有优先级的编码结构,建议使用case语句而不要使用if-else语句。对于基于cycle的仿真器,case语句的仿真速度要比if 语句的仿真速度快。对于大的多选器,case语句也比条件赋值语句的仿真速度快。对于综合工具,case语句也往往能产生出时序和面积更优化的电路。 (建议)对于条件分支为独热编码的case语句,建议采用下列语句,对于综合工具能产生较优化的电路case(1b1) condition1 : statement ; condition2 : stateme

28、nt ; default : statement;endcase3.7 状态机 将状态机的描述分成两个always块,一个用来描述组合逻辑,一个用来描述时序逻辑。 (建议)用参数语句来定义状态向量。 (建议)将状态机的逻辑和非状态机的逻辑分成不同的模块,以便于综合工具对状态机进行单独优化。 必须使用default条件为状态机指定一个默认的状态,防止状态机进入死锁状态。 FSM提供防死锁机制,以防止限死在某个状态,特别是在异常情况下。 在FSM逻辑比较复杂的时候,建议使用独热编码方式,以提高时序。/ PART 1: COMBINATERIAL LOGIC FOR NEXT STATEalways (cur_state or full_new_fr or full or have_space)begin: OVC_FSM_NXT_ST case (cur_state) STDBY: begin if (full_new_fr = 1b1) nxt_state = W_BLOCK; else if (full = 1b1) nxt_state = W_DSCD; else nxt_state = cur_state; end W_BLOCK: begin if (have_space = 1b1) nxt_state = STDBY; else nxt_state = cur_

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

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