版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、Verilog代码编写规范· 2007-5-2 23:01:27 · 发表时间: · 541 · 浏览次数: · 网络 · 文章来源: · 佚名 · 作者: Verilog代码编写规范-打印文章 打印本文 关闭窗口 Verilog代码编写规范 作者:A0023 文章来源:本站原创 点击数108 更新时间:2007
2、-2-27 21:17:10 文章录入:admin 责任编辑:admin 一. 强调Verilog代码编写风格的必要性。 强调Verilog代码编写规范,经常是一个不太受欢迎的话题,但却是非常有必要的。
3、0; 每个代码编写者都有自己的编写习惯,而且都喜欢按照自己的习惯去编写代码。与自己编写风格相近的代码,阅读起来容易接受和理解。相反和自己编写风格差别较大的代码,阅读和接受起来就困难一些。 曾有编程大师总结说,一个优秀的程序员,能维护的代码长度大约在1万行数量级。代码的整洁程度,很大程度上影响着代码的维护难度。 遵循代码编
4、写规范书写的代码,很容易阅读、理解、维护、修改、跟踪调试、整理文档。相反代码编写风格随意的代码,通常晦涩、凌乱,会给开发者本人的调试、修改工作带来困难,也会给合作者带来很大麻烦。 (实际上英文Coding Style有另一层涵义,更偏重的是,某一个电路,用那一种形式的语言描述,才能将电路描述得更准确,综合以后产生的电路更合理。本文更偏重的是,编写Verilog代码时的书写习惯。)
5、 二. 强调编写规范的宗旨。 缩小篇幅 提高整洁度 便于跟踪、分析、调试 增强可读性,帮助阅读者理解 便于整理文档
6、60; 便于交流合作 三. 变量及信号命名规范。 1. 系统级信号的命名。 系统级信号指复位信号,置位信号,时钟信号等需要输送到各个模块的全局信号;系统信号以字符串Sys开头。 2. 低电平有效的信号后一律加下划线和字母n。如:SysRst
7、_n;FifoFull_n; 3. 经过锁存器锁存后的信号,后加下划线和字母r,与锁存前的信号区别。如CpuRamRd信号,经锁存后应命名为CpuRamRd_r。 低电平有效的信号经过锁存器锁存后,其命名应在_n后加r。如CpuRamRd_n信号,经锁存后应命名为CpuRamRd_nr 多级锁存的信号,可多加r以标明。如CpuRamRd信号,经两级触发器锁存后,应命名为
8、CpuRamRd_rr。 4. 模块的命名。 在系统设计阶段应该为每个模块进行命名。命名的方法是,将模块英文名称的各个单词首字母组合起来,形成3到5个字符的缩写。若模块的英文名只有一个单词,可取该单词的前3个字母。各模块的命名以3个字母为宜。例如: &
9、#160; Arithmatic Logical Unit模块,命名为ALU。 Data Memory Interface模块,命名为DMI。 Decoder模块,命名为DEC。 5. 模块之间的接口信号的命名。
10、所有变量命名分为两个部分,第一部分表明数据方向,其中数据发出方在前,数据接收方在后,第二部分为数据名称。 两部分之间用下划线隔离开。 第一部分全部大写,第二部分所有具有明确意义的英文名全部拼写或缩写的第一个字母大写,其余部分小写。 举例:CPUMMU_WrReq,下划线左边是第一部分,代表数据方向是从CPU模块发向存储器管理单元模块(MMU)。下划线右边Wr为Write的缩写,Req是Request的缩写。两个缩写的
11、第一个字母都大写,便于理解。整个变量连起来的意思就是CPU发送给MMU的写请求信号。 模块上下层次间信号的命名也遵循本规定。 若某个信号从一个模块传递到多个模块,其命名应视信号的主要路径而定。 6. 模块内部信号:
12、模块内部的信号由几个单词连接而成,缩写要求能基本表明本单词的含义; 单词除常用的缩写方法外(如:Clock->Clk, Write->Wr, Read->Rd等),一律取该单词的前几个字母( 如:Frequency->Freq, Variable->Var 等); 每个缩写单词的第一个字母大写; 若遇两个大写字母相邻,中间添加
13、一个下划线(如DivN_Cntr); 举例:SdramWrEn_n;FlashAddrLatchEn; 四. 编码格式规范。 1. 分节书写,各节之间加1到多行空格。如每个always,initial语句都是一节。每节基本上完成一个特定的功能,即用于描述某几个信号的产生。在每节之前有几行注释对该节代码加以描述,至少列出本节中描述的信号的含义。 &
14、#160; 2. 行首不要使用空格来对齐,而是用Tab键,Tab键的宽度设为4个字符宽度。行尾不要有多余的空格。 3. 注释。 使用/进行的注释行以分号结束; 使用/* */进行的注释,/*和*/各占用一行,并且顶头; 例: / Edge detector use
15、d to synchronize the input signal; 4. 空格的使用: 不同变量,以及变量与符号、变量与括号之间都应当保留一个空格。 Verilog关键字与其它任何字符串之间都应当保留一个空格。如: Always () 使用大括号和小括号时,前括号的后边和后括号的前边应当留有一个空
16、格。 逻辑运算符、算术运算符、比较运算符等运算符的两侧各留一个空格,与变量分隔开来;单操作数运算符例外,直接位于操作数前,不使用空格。 使用/进行的注释,在/后应当有一个空格;注释行的末尾不要有多余的空格。 例: assign SramAddrBus = AddrBus31:24, AddrBus7:0 ;
17、160; assign DivCntr3:0 = DivCntr3:0 + 4b0001; assign Result = Operand; 5. 同一个层次的所有语句左端对齐;Initial、always等语句块的begin关键词跟在本行的末尾,相应的end关键词与Initial、always对齐;这样做的好处是避免因begin独占一行而造成行数太多;
18、例: always ( posedge SysClk or negedge SysRst ) begin if( !SysRst ) DataOut <= 4'b0000; else if( LdEn ) begin DataOut <= DataIn; End
19、60; else DataOut <= DataOut + 4'b0001; end 6. 不同层次之间的语句使用Tab键进行缩进,每加深一层缩进一个Tab; 8. 在endmodule,endtask,endcase等标记一个代码块结束的关键词后面要加上一行注释说明这个代码块的名称;
20、 9. 在task名称前加tsk以示标记。在function的名称前加func以示标记。例如: task tskResetSystem; endtask /of tskResetSystem 五小结: &
21、#160; 以上列出的代码编写规范无法覆盖代码编写的方方面面,还有很多细节问题,需要在实际编写过程中加以考虑。并且有些规定也不是绝对的,需要灵活处理。并不是律条,但是在一个项目组内部、一个项目的进程中,应该有一套类似的代码编写规范来作为约束。 总的方向是,努力写整洁、可读性好的代码。 打印本文 关闭窗口 Verilog 代
22、码风格-供参考作者:Free 文章来源:Free 点击数: 1809 更新时间:2008-1-4 Description 本文主要是收集一些重要的Verilog coding style。一个好的coding style可以减少错误的发生,增加电路的效能,以及较好的可读性。 Text The order of module signals 一个module signal顺序如下 (由左至右): Input clo
23、ck signals(clk_*) set/reset signals(set_*, rst_*) enable/disble signals(en_*, dis_*) read/write enable signals(we_*, re_*, rw_*) control signals(i_*) address signals(i_*) data signals(i_*) Output clock signals(o_clk_*) set/reset signals(o_set_*, o_rst_*) enable/disable signals(o_en_*, o_dis_*) contr
24、ol signals(o_*) address signals(o_*) data signals(o_*) In/Out control signals(io_*) address signals(io_*) data signals(io_*) Naming Rule 以下的namign rule为个人使用的规则。 命名方式分类 底线分隔型:xxx_yyy_zzz 大写底线分隔型:XXX_YYY_ZZZ 首字大写型:AbcDefGhi 首字小写型:avcDefGhi 各种元素所使用的命名 文件名称:底线分隔型, Ex: xxx_yyy_zzz.v module名称:底线分隔型, Ex: x
25、xx_yyy_zzz module instance名称:底线分隔型, Ex: xxx_yyy_zzz local wire名称:底线分隔型:Ex: xxx_yyy_zzz local reg名称:底线分隔型, Ex: xxx_yyy_zzz input signal名称:前置i_的底线分隔型, Ex: i_xxx_yyy_zzz output signal名称:前置o_的底线分隔型, Ex: o_xxx_yyy_zzz input/output signal名称:前置io_的底线分隔型, Ex: io_xxx_yyy_zzz 常数名称:大写底线分隔型, XXX_YYY_ZZZ paramet
26、er参数名称:大写底线分隔型, Ex: XXX_YYY_ZZZ block名称:大写底线分隔型, Ex: XXX_YYY_ZZZ 特殊讯号名称 单一的clock signal: clk 多个clock signal: clk_xxx 负缘触发的clock signal: clk_n, clk_xxx_n 单一的reset signal: rst 多个reset signal: rst_xxx 负缘触发的reset signal: rst_n , rst_xxx_n 单一的set signal: set 多个set signals: set_xxx 负缘触发的set signals: set_n
27、, set_xxx_n 致能讯号: en_xxx 除能讯号: dis_xxx Procedural Assignments 使用指引 在撰写sequential logic时,使用nonblocking assignment。 在撰写latches电路时,使用nonblocking assignment。 在always block中撰写conbinational logic时,使用blocking assignment。 在同一个always block中同时撰写sequential及combinational logic时,一律使用nonblocking assignment。
28、 别在同一个always block中混合使用nonblocking及blocking assignment。 别在两个以上的always block中对同一个变量设定数值。 使用$strobe来显示由nonblocking assignment所给定的变量。 不要对assignment使用#0延迟设定。 在procedural assignment中,LHS一定要是reg型态。非procedural assignment一定是net的型态。 常用的style Combination logic 在always block中,如果使用combination logic,应当使用blocking
29、 assignment. / All inputs used within always block should be listed in sensitive list.always (in1 or in2 or in3)begin xxx = in1 in2 & in3;endSequential logic 在always block中,如果使用sequential logic,应当使用nonblocking assignment. / Synchronous reset. The rst_n is NOT in sensitive list.always (pose
30、dge clk) begin if (rst_n) begin xxx <= INIT_VAL; end else begin xxx &
31、lt;= yyy; end end/ Asynchronous reset. The rst_n IS in sensitive list.always (posedge clk or negedge rst_n) begin if (rst_n) begin xxx <= INIT_VAL;
32、; end else begin xxx <= yyy; end endDelay的建模 Combination logic 建模没有delay时,使用blocking assignment(ex: a = b;) 建模有惯性(inertial) delay时(即glitch不会传到后面的电路
33、中)。使用delayed evaluation blocking assignments(#10 a = b;). 建模传输(transport)delay时(即glitch也会一并传到后面的电路中)。使用delayed assignment nonblocking assignments(ex: a <= #10 b;). Sequential logic 建模没有delay时,使用non-blocking assignments (ex: q <= d; ). 建模有delay时,使用delayed assignment nonblocking assignments(ex:
34、q <= #10 d;). Finite State Machine Moore FSM: 输出与输入没有直接关系。 由两个always block构成,一个是sequential block用来处理状态的变化。另一个为combinational block用来处理状态与输入之间的关系。注意,在sequential block中应全部使用nonblocking assignment。在combinational block中应使用blocking assignment。在某些简单的case中,combinational block也可直接由continuous assignment来取代
35、。下面的范例是一般简单的FSM。 / Sequential always block.always (posedge clk or posedge rst) begin if (rst) state <= STATE_IDLE; else state <= next; end/ Combinational always block.always (state
36、 or input1 or input2 . or inputN) begin next = STATE_IDLE; outputs = OUTPUT_IDLE: case (state) STATE_IDLE: begin
37、. / the logic to determine the next state. next = STATE_?; end STATE_?: begin
38、. / the logic to determine the next state. next = STATE_?; outputs = ?; / The output of this state. end
39、0; endcase end针对simplified one-hot encoding的FSM范例: / Sequential always block.always (posedge clk or posedge rst) begin if (rst) state <= n'b0; stateSTATE_DEFAULT <= 1'b0;
40、160; else state <= next; end/ Combinational always block.always (state or input1 or input2 . or inputN) begin next = n'b0; outputs = OUTPUT_DEFAULT: case (1'b1) / synopsys full_case paral
41、lel_case stateSTATE_DEFAULT: begin . / the logic to determine the next state. nextSTATE_? = 1'b1; &
42、#160; end stateSTATE_?: begin . / the logic to determine the next state. nextSTATE_? = 1'b1;
43、 outputs = ?; / The output of this state. end / synopsys translate_off default: $display("Bad state!&q
44、uot;); / synopsys translate_on endcase end针对simplified one-hot with zero-idle encoding的FSM: / Sequential always block.always (posedge clk or posedge rst) begin if (rst) state <= n'b0;
45、160; else state <= next; end/ Combinational always block.always (state or input1 or input2 . or inputN) begin next = n'b0; outputs = OUTPUT_DEFAULT: case (1'b1) / synopsys ful
46、l_case parallel_case |state: / IDLE begin . / the logic to determine the next state. nextSTATE_? = 1'b1;
47、 end stateSTATE_?: begin . / the logic to determine the next state. nextSTATE_? = 1&
48、#39;b1; outputs = ?; / The output of this state. end / synopsys translate_off default: $display("
49、Bad state!"); / synopsys translate_on endcase endMealy FSM: 输出与输入有直接关系。 Mealy FSM的作法与上面的范例相类似。唯一的不同在于outputs的指定,需加上与input相关的逻辑判断。例如: case(state) / synopsys parallel_case full_case . STATE_?: begin
50、60; . if (input1 & input2) outputs = ?; else outputs = ?; end / synopsys translate_off default: $display("Bad FSM."); / synopsys t
51、ranslate_on default endcaseDatapath 参考:Coding Guidelines for Datapath Synthesis. 有号数的计算:若有需要关于有号数的计算,应当利用Verilog 2001所提供的signed及$signed()机制。 input signed 7:0 a, b;output signed 15:0 o;assign o = a * b;or input
52、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的implicity signed extension,避免手动进行转换。input signed 7:0 a, b;input signed 8:0 o;assign
53、 o = a + b; / Verilog会自动进行符号的扩展。有号数与无号数的混合计算:不要在同一个verilog叙述中进行有号数与无号数的计算。应该要分成个别独立的叙述。在一个verilog叙述中只要有一个无号数的操作数,整个算式将被当成无号数进行计算。 input 7:0 a;input signed 7:0 b;output signed 15:0 o;/ Don't do this: assign o = a
54、* b;/ The $signed(1'b0, a) can convert the unsigned number to signed number.assign o = $signed(1'b0, a) * b;input signed 7:0 a;output signed 15:0 o;/ Don't do this: assign o = a * 8'b10111111;/ Use $signed() system taskassign o = a * $signed(8'
55、b10111111);/ or sb keyword.assign o = a * 8'sb10111111;part-select运算过后的操作数是无号数。就算是选择的范围包含整个register或wire。 input signed 7:0 a;input signed 7:0 b;output signed 15:0 o1, o2;/ Don't do this: assign o1 = a7:0;assign o1 = a;/ Don't do
56、 this: assign o2 = a6:0 * b;assign o2 = $signed(a6:0) + b;Verilog的位宽度规则:技巧就是要善用LHS来限制位宽度。利用中介的讯号线来作为限制宽度用的LHS操作数。 在没有特别设定的状况下,Verilog会依据LHS的操作数宽度来决定RHS操作数的宽度。 input 7:0 a;input 7:0 b;output 8:0 o;assign o = a + b; / 9 bits.对一个表示式而言,最大宽度的操作数决定了整体的宽度。 in
57、put signed 3:0 a;input signed 7:0 b;output 11:0 o;wire signed 11:0 o_sgn;/ Don't do this: assign o = $unsigned(a * b); 这将会是一个8 bit的运算。因为在刮号内的bits数是依据最大操作数b的宽度决定的。assign o_sgn = a * b; / 12 bits。
58、因为bit数是依据LHS宽度决定的。assgign o = $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't do this: assign o = (a + b) > (c * d); 因为(a + b)及(c * d)都会是8 bit的结果。assig
59、n tmp1 = a + b; / 16 bits.assign tmp2 = c * d; / 16 bits.assign o = tmp1 > tmp2; / 1 bit.写verilog代码要有硬件的概念2009-11-27 19:45因为Verilog是一种硬件描述语言,所以在写Verilog语言时,首先要有所要写的module在硬件上如何实现的概念,而不是去想编译器如何去解释这个module. 比如在决定是否使用reg定义时,要问问自己物理上是不是真正存在这个register, 如果是,它的clock是什
60、么? D端是什么?Q端是什么?有没有清零和置位?同步还是异步?再比如上面讨论的三态输出问题,首先想到的应该是在register的输出后面加一个三态门,而不是如何才能让编译器知道要“赋值”给一个信号为三态。同样,Verilog中没有“编译”的概念,而只有综合的概念。 写硬件描述语言的目的是为了综合,所以说要想写的好就要对综合器有很深的了解,这样写出来的代码才有效率。 有些东西完全是没有意义的,像有些书上的很多程序,完全是不可综合的比如产生一个10ms方波什么的程序,用什么#1
61、0 clk,这样的语句硬件不可能做的那里面很多程序是用来verification的,不是综合的。张老师那本书用来当初级教材还是不错的,但是想通过它来掌握verilog是不够的。曾经接触过motorola苏州设计中心的一位资深工程师,他忠告了一句:就是用verilog描述电路的时候,一定要清楚它实现的电路,很多人只顾学习verilog语言,而不熟悉它实现的电路,这是设计不出好的电路来的 一般写verilog code时,对整个硬件的结构应该是很清楚了,最好有详细的电路图画出,时序问题等都应该考虑清楚了。可以看着图直接写code。
62、0; 要知道,最初Verilog是为了实现仿真而发明的.不可综合的Verilog语句也是很重要的.因为在实际设计电路时,除了要实现一个可综合的module外,你还要知道它的外围电路是怎样的,以及我的这个电路与这些外围电路能否协调工作.这些外围电路就可以用不可综合的语句来实现而不必管它是如何实现的.因为它们可能已经实际存在了,我仅是用它来模拟的.所以,在写verilog的时候应该要先明确我是用它来仿真的还是综合的.要是用来综合的话,就必须要严格地使用可综合的语句,而且不同的写法可能产生的电路会有很大差别,这时就要懂一些verilog综合方法的知识.
63、就像前面说的,脑子里要有一个硬件的概念.特别是当综合报错时,就要想一想我这种写法能不能用硬件来实现,verilog毕竟还不是C,很多写法是不可实现的.要是这个module仅是用来仿真的,就要灵活得多了,这时你大可不必太在意硬件实现.只要满足它的语法,实现你要的功能就行了. 有网友说关于#10 clk=clk的问题,虽然这种语句是不可综合的,但是在做simulation和verification是常常用它在estbench中来产生一个clock信号。再比如常常用到的大容量memory, 一般是不会在片上实现的,这个时候也需要一个unsynthesi
64、zable module. mengxy所言切中肯罄。 我们设计的module的目的是为了可以综合出功能正确,符合标准的电路来。我想这是个反复的过程,就像我们在写design flow中总要注明前仿真,综合后的仿真,以及后仿真等。仿真是用来验证我们的设计的非常重要的手段。而verilog里那些看是无聊的语句这个时候就会发挥很大的作用。我想,用过verilog_xl的兄弟应该深有体会。verilog_xl里的操作,可以用verilog里的系统命令来完成。通过最近的应聘我也深有体会,很多公司看中你在写code时,是否考虑到timing,a
65、rchitecture,DFT等,这也说明verilog中的任何语句都是非常重要的。 要写代码前必须对具体的硬件有一个比较清晰的概念但是想一次完成可综合代码就太夸张了,verilog的自顶向下设计方法就是从行为建模开始的,功能验证了以后再转向可综合模型.太在意与可综合令初期设计变得太累 很同意这种看法,在做逻辑结构设计时,综合的因素是要考虑的,但是有很多东西不能考虑的过于细致,就是在设计的时候不能过于紧卡时延,面积等因素,因为这样以来综合后优化的余量就会很小,反而不利与设计的优化,如果在
66、时延和面积要求不是很紧张的情况下,其实代码写的行为级,利用综合工具进行优化也是一种方法。偶就听说有一家很有名的公司,非常相信综合工具的优化能力,从来不作综合后仿真的,hehe.当然,如果面积和时延的要求很高,最好还是把代码写的底层一点,调用库单元时,也要充分考虑其面积和时延的因素。Verilog代码编写规范2009-10-16 19:46一.强调Verilog代码编写风格的必要性强调Verilog代码编写规范,经常是一个不太受欢迎的话题,但却是非常有必要的。 每个代码编写者都有自己的编写习惯,而且都喜欢按照自己的习惯去编写代码。与自己编写风格相近的代码,阅读
67、起来容易接受和理解。相反和自己编写风格差别较大的代码,阅读和接受起来就困难一些。 曾有编程大师总结说,一个优秀的程序员,能维护的代码长度大约在1万行数量级。代码的整洁程度,很大程度上影响着代码的维护难度。遵循代码编写规范书写的代码,很容易阅读、理解、维护、修改、跟踪调试、整理文档。相反代码编写风格随意的代码,通常晦涩、凌乱,会给开发者本人的调试、修改工作带来困难,也会给合作者带来很大麻烦。 (实际上英文Coding Style有另一层涵义,更偏重的是,某一个电路,用那一种形式的语言描述,才能将电路描述得更准确,综合以后产生的电路更合理
68、。本文更偏重的是,编写Verilog代码时的书写习惯。)二.强调编写规范的宗旨 缩小篇幅 提高整洁度 便于跟踪、分析、调试 增强可读性,帮助阅读者理解 便于整理文档 便于交流合作三. 变量及信号命名规范。 1. 系统级信号的命名。 系统级信号指复位信号,置位信号,时钟信号等需要输送到各个模块的全局信号;系统信号以字符串Sys开头。2. 低电平有效的信号后一律加下划线和字母n。如:SysRst_n;FifoFull_n;3. 经过锁存器锁存后的信号,后加下划线和字母r,与锁存前的信号区别。如CpuRamRd信号,经锁存后应命名为C
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 传染病防控领导小组及职责分工
- 税务代理服务协议(3篇)
- 2026年家长进课堂幼儿园活动方案设计
- 2026干旱面试题目及答案大全
- 税收筹划:莫在刀锋上跳舞
- 2026 基于5G和AI的智慧城市解决方案
- 中考生物复习生物的多样性专项真菌的基本形态和结构特点题选汇编含答案
- 数据统计的重要性
- 2026后勤干事面试题及答案大全
- 2026会议材料面试题及答案
- 油田采出水处理设计规范
- 智能节水系统安装与运维综合实训平台需求
- 招标采购专家管理办法
- 买卖矿山居间合同协议
- 重症超声及血流动力学培训班试题
- 广东研学实践活动方案
- T/CCMA 0112-2021全断面隧道掘进机用盾尾密封刷
- DB32/T 4494-2023房屋白蚁灭治技术规程
- 《婴幼儿饮食与营养》课件-2-2-1 学习活动1 7-12月龄婴儿喂养
- E1000变频器产品手册
- 出版合同的书稿保密协议
评论
0/150
提交评论