
(仅供内部使用)
| 拟制: | xxx | 日期: | xxx |
| 审核: | 审核者 | 日期: | yyyy-mm-dd |
| 批准: | 批准者 | 日期: | yyyy-mm-dd |
修订记录
修订日期 | 修订版本 | 描述 | 修订者 |
2 代码编写规范 8
版面 8
编写代码规范 8
3 电路设计规则 17
时钟 17
复位 17
避免LATCH 18
避免组合反馈 18
赋值语句 18
case语句和if-then-else语句 19
状态机 19
异步逻辑 21
4 模块划分 21
5 提高可移植性的编码风格 21
采用参数化设计 21
采用于工具平台和工艺库的设计 22
尽量使用已经得到验证的IP 22
6 其他一些设计建议 23
7 附件 25
8 参考文档: 30
基本原则:简单,一致,可重用。
简单指尽量使用简单的语句,尽量使用简单的设计,尽量使用简单的时钟,尽量使用简单的复位。
一致指尽量保持代码风格一致,尽量保持命名一致。
可重用指有成熟的IP尽量使用IP,设计的代码要尽量可重用。
1
命名规范
给信号命名就像给孩子取名字一样,有区别,有根源,有深度,还有一点,要简单,别冗长。
有区别指取名字不要一样,假如大家只有一个手机号码,那这个号码还能有什么用处?
有根源指取名字要能象姓氏一样,让人一看就直到是张家的后代而不是李家的。
有深度就是取名字要有涵义,张一,张二,张三虽然也是名字,但是请考虑一下被取名字人的感受。
简单点,几十个字母长的名字,打字的和看字的都累。
大小写规则:只有parameter,`define和module名称才能享受大写。
Module 名应与文件名保持一致(文件名是小写),假如不想在设计后面遇到麻烦的话。
不要尝试使用任何保留字,因为他们已经被保留了。
不要重复使用同样的名字去命名不同的数据。
(建议)对module名加”_LVx”的后缀,增强module名称的结构层次含义
如:设计顶层为TOP LEVEL,即LEVEL1,命名为QTRxxxx_LV1;
时钟模块,IO_PAD,CORE,为LEVEL2,命名为CLK_PROC_LV2等等;
CORE内子模块为LEVEL3,然后以此类推。
对于来自同一驱动源的所有时钟信号使用相同的名字。
对于低电平有效的信号,应该以_n结尾。
模块间相连端口名称要一致。
(建议)使用下表所列的命名缩写方式。
| 全称 | 名称 |
| clock | Clk |
| reset | rst |
| clear | clr |
| address | addr |
| data_in | din |
| data_out | dout |
| interrupt request | int |
| read enable | rden |
| write enable | wren |
| count | cnt |
| request | req |
| control | ctrl |
| arbiter | arb |
| pointer | ptr |
| segment | seg |
| memory | mem |
| register | reg |
| 全称 | 添加后缀 |
| active low | _n |
| enable | _en |
| select | _sel |
| flag | _flg |
| delay | _dly |
信号命名尽量不要使用孤立的、小写的英文字母L
2
代码编写规范
2.1版面
语句成行,增加可读性和可维护性。
行的长度
保持每行小于或等于72个字符。因为有的终端或打印机每行不能超过80个字符。规定72个字符是为了留出边空,提高可读性。还有一个原因是为象vi这样的编辑器留有显示行号的地方。
用回车来分割超过72个字符的行,并且在下一行用缩进来表示该行是前一行的继续。
缩进。
用缩进来提高续行和嵌套循环的可读性。
缩进采用4个空格。
避免使用TAB键。不同的编辑器或用户环境使得TAB的位置差别很大,造成缩进的混乱。有一些工具可以将TAB替换成空格。
(建议)使用注释
使用注释来解释端口、信号、信号组、always块、函数等。注释应该放在它所描述的代码的附近。注释应该简明扼要,并足够说明问题。避免注释杂乱。显而易见的功能不用加注释。注释关键是说明设计意图。
2.2编写代码规范
在源文件中要有文件头
在源文件、script文件的开始应包含一个文件头。文件头至少应包含下列信息:文件名、作者、模块的功能描述和关键特征的列表、文件产生的日期、更改记录(日期、更改者、更改的内容)。(参见代码模板)
模块名称用大写,例如:module MEM_CTRL。
端口声明时每行声明一个端口,并有注释(最好在同一行),也可对同一类型的一组端口加注释。对于时钟,复位以及其他控制信号,需要注释有效工作沿或者有效工作值
建议用下述顺序声明端口。
.)
if (...) 0 = A + B;
else d0 = C + D;
中,DC可能只会生成一个加法器。
条件算子中不存在资源共享
如:z = (cond==1’b1)? (a+b) : (c+d);
必须使用两个加法器;
而等效的条件if-else语句可以资源共享,如:
if (cond==1’b1)
z = (a+b);
else
z = (c+d);
只要加法器的输入端复用,就可以实现加法器的共享,使用一个加法器实现。
(d)尽量采用公共子表达式
如 :
x=a+b+c
y=d+a+b
改为:z=a+b
x=z+c
y=d+z
(2)算符
(a)条件运算符
r1 = gate? r2 : r3;
避免使用条件嵌套:
r1 = (aa = 0)? ((bb == 0)? r2 : r3) : r4; or
r1 = {aa,bb} == 0? r2:
(b)逻辑操作符
在if(),while(),()?A:B 之类的表达式中,括号中的表达式应该是一个逻辑表达式,相应的操作符应该用逻辑操作符。
如:wire x,A,B;
(x) ? A:B 与 (x == 1'b1) ? A:B
与 if((A&&B)==1’b1)
与 while(A==B)
操作结果相同,但显然前者不规范。
(c)乘法运算符“*”
对于一个变量data与常数constant相乘data * constant,如果常数不是2的整数次幂,建议先将其分解,如constant= 53 = 32 + 16 + 4 + 1 = 2^5 + 2^4 + 2^2 + 2^0,这样乘积就可以表示为变量data移位结果的相加。对于乘法运算符“*”,综合后通常得到的是乘法器,时延较大。
赋值语句
(1)不要在信号列表中进行运算操作
如:Bad: addr(a,b,d&e);
Good: addr(a,b,c); c=d&e;
(2)BLOCK赋值和NON-BLOCK赋值的使用
(a)组合逻辑采用BLOCK赋值(=)
如:
(b)非组合逻辑(主要是寄存器)采用NON-BLOCK赋值并加delay以保证前仿真和后仿真的一致
如:
DEL d;
(3)在同一块语句中不允许同时出现阻塞赋值和非阻塞赋值
条件语句
(1)IF语句
(a)向量比较时,比较的向量长度要相等,同样向量和常量比较时长度也要求匹配,长度不同时要求进行显式位扩展(verilog对位数小的向量做0扩展以使它们的长度相匹配,该扩展是隐式的)
如:
reg [7:0] abc;
reg [3:0] def;
.......
if (abc == {4'b0,def}) begin
.......
if (abc == 8'h0) begin
(b)不要采用if表达式的简写形式
例如:
if等同于 if (variable != 0)
if (!variable) 等同于 if (variable == 0)
但后者才合乎规范
(c)每个if都应该有一个else与之相对应,如果条件为假时不进行任何操作,则用一条空语句else;避免产生latch
(d)if...else if...else if...else的代码书写格式如下,要注意优先级
if (...)
begin
end
else
begin
end
(d)如果变量在if-else语句中非完全赋值,则应给变量一个缺省值
如:
begin
v2 = 2'b10; ....
end
always语句
(1)在使用always生成组合逻辑时,敏感表要列全,敏感表中也不能包含没有用到的变量。
Rule:
Combinational sensitivity lists should include
1)Any signal on right hand side of assignment
2)Any signal in if or case expression
For example:
......
module sense_list_ex(
1’1’....
end
else
begin
....
end
采用时钟上升沿触发。
有限状态机(FSM)
(1)组合逻辑和时序逻辑分开描述;
COMBINATERIAL LOGIC FOR NEXT STATELOGIC FOR CURRENT STATE1’COMBINATERIAL LOGIC FOR NEXT STATELOGIC FOR CURRENT STATE1’1’1’1’1’1’1’ Ltd.
77m cpu_cs,
cpu_addr,
cpu_datain,
cpu_rd,
cpu_we,
.
);
77m77mst (rst),
.addr (sts_num),
.77m_sys),
.din (din),
.we (1'b1),
.dout_en (1'b1),
out (dout_tmp)
3参考文档:
1.Reuse Methodolgy Manual_2, by Michael Keating and Pierre Bricaud
2.The Ten Commandments of Excellent Designs, by Peter Chambers
