神州龙芯公司
Verilog编码
软IP重用
(草案 2007-1-10)
(仅供公司内部使用)
1. 宗旨
本规范为神州龙芯公司内部强制实施的 Verilog HDL 编码规范。每个IP设计人员必须严格遵守,以避免不必要的重复劳动,从而提高设计效率。本规范适用于下列三种 Verilog代码文件的编写:1)可综合逻辑部件;2)虚拟部件(Virtual Component--VC);3)测试模块(testbenches)。规范还对模块文件的命名习惯、代码文件的储存、代码文件的编写风格做了强制性的规定。
公司内的每个设计人员必须严格遵照本规范来编写代码,以提高代码的可读性。这不仅能提高 IP 设计人员的工作效率,也能及时帮助系统或者软件设计人员在调试复杂系统时发现和分析 IP 代码或者自己编写的代码所存在的问题。 遵照本规范编写的代码,不但容易理解,也容易修改,而且设计者之间可以互相利用各自拥有的 IP 设计资源,有的可以直接利用,有的只需要对现成模块的部分参数或接口稍做修改就可以使用,以便于实现 IP 重用的目标。严格按照本规范编写的代码,可以显著地提高公司整体的设计效率。这种可读性更强的代码,不但能帮助我们达到 IP 重用的目标,节省人力资源,提高工作质量,而且还能确保编写的代码能被绝大多数仿真和综合工具所接受,大大减少代码在不同设计、综合和仿真平台之间移植的工作量。
在 IP 设计的阶段验收过程中,一旦发现任何不符合本规范的代码,每个负责IP验收的人员有义务向设计者指出不符合规范的地方,令其及时做出修正,然后再进入下一个验收程序。否则即使代码已经通过测试,也没有任何发现问题,验收人员仍有权因为设计者的代码注释不完整或不符合规范拒绝验收,并作出设计工作尚未完成的评价和结论,命令其返工。
本规范的目的是:1)保证 Verilog RTL 模块经综合所产生的门级结构与Verilog仿真器所理解寄存器传输级的HDL代码的行为是一致的;2)利用参数传递可修改代码中的常数,使可综合模块、虚拟部件或者测试模块的输入/输出信号位宽扩展变得非常容易;3)使模块分割(PARTITIONING)尽量优化,使每个模块都具有可重用的构造,便于以后的扩展。 本规范在模块化一节着重阐述了在综合开发环境中难以表达清楚的典型结构,以及如何确保前仿真和后仿真行为一致的代码风格。本规范将可综合代码和行为级代码的编写要点分成两部分,分别予以阐述,而对两者均合适的部分放在规范的后面予以阐述。因而本规范也适用于测试模块、VC模块和监视模块代码的编写。
本规范的宗旨是:便于软IP模块、虚拟器件和测试模块的扩展和重复使用,方便非原作者对代码进行维护,为各种SOC的快速建模和仿真创造条件;降低系统芯片的设计风险,从而降低设计成本。
需要注意的是:原则上本规范是普遍适用的,但在很多场合可能会出现个别意外的情况,例如某工具的局限性,这可能会给本规范中个别条款的实施造成一定的困难。
2.编写可综合的RTL级 Verilog 模块代码时必须遵守的要点:
2.1 不允许在代码中出现的语句要点:
· 任何变量不能赋初始值X ,对任何寄存器所赋的初始值必须是确定的。
· 代码语句中不能加时间延迟,不允许出现如下语句: #4 out = cin;
· 不允许使用门控时钟和门控复位。
· 不允许使用锁存器。(商用综合器可帮助执行这项规范,如使用了锁存器,综合结果会出现Latch inferred)。
· 不允许在可综合的设计代码中使用`Define 来定义参数, 应该使用参数Parameter来定义。`Define只用于编写不可综合的仿真测试模块。
· 不允许在可综合代码中使用initial、wait、fork-join、while 。
· 不允许使用UDP ( 用户定义的原语元件 )
· 不允许在可综合代码中出现逻辑反馈环路,否则会生成不可预知的逻辑电路。
· 不允许在可综合模块中使用casex, casez 语句,只允许使用case 和if-else语句作条件分支语句。
· 在时序逻辑的设计中不允许用阻塞赋值 = ,只允许用非阻塞赋值 <=。
· 在组合逻辑的设计中而不允许使用非阻塞赋值 <= ,只允许用阻塞赋值 =。
· 只允许用Verilog2001 中的always (*) 来生成组合逻辑,其他Verilog 2001语法在可综合模块中目前都不建议采用。
2.2 建议尽量采用的要点
· 用高电平有效的硬件异步复位reset。
· 用高电平有效的同步软件复位reset。
· 尽可能使用高电平有效信号,不使用低电平有效信号(除某些总线、器件有特殊要求外)。只有复位信号reset 在特定情况下可以设置为低电平有效信号。
· 尽可能使用assign语句设计组合逻辑。
· 模块之间数据交换总线应该尽量用多路器实现。尽量不使用三态总线。 三态总线只用于对外接口或者顶层内部总线。
· 模块中的每个输出信号原则上必须通过寄存器输出。任何不通过寄存器输出的信号必须加以注释,注意防止出现反馈回路。
· 尽量合并源代码,使其简洁明了,不要试图依靠综合器的功能。
· case语句和if else语句必须保证其完整性,即所有分支项应该完全列出,case语句应该加缺省项(default),if语句应该有对应的else项。
· 使用参数(parameter)作为可变化的常数,例如总线的位宽。
· 端口声明的顺序--在保证先输入再输出的基础上按如下顺序clocks,resets,control signals,address bus,data bus
· 端口和连接端口的信号尽量同名。
2.3 技术文档和文件的要点
· 为了使代码容易理解,应该尽可能地在代码中添加必要的注释,特别遇到有诀窍的部分更应该如此。验收人员有权要求源代码设计者对理解比较难的代码部分提添加注释。源代码的设计者不得以代码已经联合调试成功,而予以拒绝或者拖延,否则验收人员有权向上级主管对源代码的设计者提出投诉。
· 注释应尽量靠近被注释的语句。大段的注释必须用由注释符号组成的边框/////////////// 围绕。
· 代码中的所有常数都应该使用参数(parameter),将这些参数的定义放在一个独立的文件中,然后在设计模块中用`include 宏命令将其包含。参数文件必须用如下规则命名:xxxx _ parameter.v
· 文件名与模块名必须完全一致。
2.4. 命名规则:
1) 常用规则:
· 常数、DEFINE和参数必须用大写字母定义。不允许将大小写字母混用来表示词的间隔,应该用下横线来表示词间隔,例如:ddr_address_bus
· 所有端口、信号、变量均采用小写
· 用n结尾的下横线表示低电平有效。例如: reset_memory_n, reset_n
· 声明总线宽度的语句必须用 [n:0], 而不能用 [0:n],标记0表示LSB, 标记n表示MSB
· 输入/输出端口和信号的声明必须每个信号一行,然后组合起来,必要时在端口信号后添加注释。
· 表示组合逻辑的always块的电平敏感列表,必须每个变量一行(见样板模块)。
2) 信号命名规则:
· 时钟信号用clk 做前缀,把具体名放在后面, 例如:clk_memory.
· 复位信号用 reset做前缀,把具体名放在后面,例如:reset_memory.
· 单个输入信号用i做前缀,把具体名放在后面,例如: i_memory_enable
· 总线输入信号用iv做前缀,把具体名放在后面,例如:iv_memory_data
· 单个输出信号用o做前缀,把具体名放在后面,例如: o_memory_read
· 总线输出信号用ov做前缀,把具体名放在后面,例如:ov_memory_wdata
· 单条线网用w做前缀,把具体名放在后面,例如:w_tmp_enable
· 线网总线用wv做前缀,把具体名放在后面,例如:wv_tmp_data
3) 状态机变量的命名规则:
· 状态机的状态变量必须用以下两个名字:
· 当前状态用 cstate 命名
· 下一个状态用 nstate 命名
如果有一个以上的状态可以用后缀来命名该状态,例如: cstate_fetch
· 把状态机的初始状态定义为: IDLE
---------------------------------------------------------------------------------------
4) 可综合模块的样板代码:
---------------------------------------------------------------------------------------
//+FHEADER /////////////////////////////////////////////////////////////////////////////
// 版权所有者:神州龙芯公司.
// Copyright 2007. All Rights Reserved.
// 保密级别: 绝密,本代码绝对不能外传
//-------------------------------------------------------------------------------
// 文件名 : memif_transfer.v
// 设计部门 : SoC 部门
// 原始作者:周鹏飞
// 联系方式:电子邮件: zhoupengfei@china-cpu.com
// 内部电话:2802
// --------------------------------------------------------------------------
// 版本升级历史:
// 版本生效日期:
// 1.0 2005-09-12 周鹏飞 第1版
// 2.0 2006-11-11 宋兴嘉 第2.0版
// 2.1 2007-01-18 杨雷 第2.1版
// 记录每次升级的改进点。。。。。。。。。。。。。。。。。.
// 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
// 。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
---------------------------------------------------------------------------
// 关键字 : memory, decoder, address
//--------------------------------------------------------------------------
// 模块功能: 将最终像素传至存储器……………………………………………………………………
// ……………………………………………………………………………………………
// --------------------------------------------------------------------------
// 参数文件名: decoder_parameters.v
// -----------------------------------------------------------------------
// 重复使用问题:
// 复位策略:负跳变沿异步复位信号 i_reset
// 时钟域 : i_clock
// 关键时序: N/A
// 是否需要实例引用别的模块 : Yes
// 可综合否 : Yes
//-FHEADER //////////////////////////////////////////////////////////////////////
module memif_transfer(
i_clk,
i_reset_n,
// COUNT CONTROL
i_store_set,
iv_ext_mem_addr,
// SET THE EXT. MEMORY ADDRESS
o_store_avail,
// DATA IN
i_store_we,
iv_store_addr,
iv_store_data,
// EXT. MEMORY CONTROL
o_ext_req,
i_ext_ack,
o_ext_we,
o_ext_oe,
ov_ext_addr,
ov_ext_wdata,
iv_ext_rdata
);
///////////////////////////////////////////////////////////////////////////////
`include “decoder_parameters.v”
///////////////////////////////////////////////////////////////////////////////
input
i_clk;
input
i_reset_n;
input
i_store_set;
input[EXT_ADDR_SIZE-1:0]
iv_ext_mem_addr;
output
o_store_avail;
input
i_store_we;
input[ST_ADDR_SIZE-1:0]
iv_store_addr;
input[ST_DATA_SIZE-1:0]
iv_store_data;
output
o_ext_req;
input
i_ext_ack;
output
o_ext_we;
output
o_ext_oe;
output[EXT_ADDR_SIZE-1:0]
ov_ext_addr;
output[EXT_BITWIDTH-1:0]
ov_ext_wdata;
input[EXT_BITWIDTH-1:0]
iv_ext_rdata;
///////////////////////////////////////////////////////////////////////////////
// STATE MACHINE
parameter
IDLE = 0;
parameter
REQ = 1;
parameter
WRITE = 2;
///////////////////////////////////////////////////////////////////////////////
reg[1:0]
cstate;
reg[1:0]
nstate;
wire[EXT_ADDR_SIZE-1:0]
wv_ext_mem_addr;
wire
wv_load_addr;
wire[31:0]
wv_load_data;
reg
write_count;
wire
w_load_clear;
wire
w_load_ready;
///////////////////////////////////////////////////////////////////////////////
assign
o_ext_oe = 0;
assign
o_ext_req = (cstate==REQ)|(cstate==WRITE) ;
assign
o_ext_we = (cstate==WRITE);
assign
ov_ext_addr = wv_ext_mem_addr + write_count;
assign
w_load_clear = (write_count==1);
assign
wv_load_addr = write_count;
assign
ov_ext_wdata = wv_load_data;
always @(posedge i_clk or negedge i_reset_n)
begin
if (~i_reset_n)
begin
write_count <= 0;
end
else
begin
if (cstate==IDLE)
begin
write_count <= 0;
end
if (cstate==WRITE)
begin
write_count <= write_count + 1;
end
end
end
always @(posedge i_clk or negedge i_reset_n)
begin
if (~i_reset_n)
begin
cstate <= IDLE;
end
else
begin
cstate <= nstate;
end
end
always @ ( cstate
or w_load_ready
or i_ext_ack
or write_count )
begin
nstate = cstate;
case (cstate)
IDLE:
begin
if (w_load_ready)
begin
nstate = REQ;
end
end
REQ:
begin
if (i_ext_ack)
begin
nstate = WRITE;
end
end
WRITE:
begin
if (write_count==1)
begin
nstate = IDLE;
end
end
default:
begin
nstate = cstate;
end
endcase
end
memif_wfifo8
u_memif_wfifo8( .i_clk (i_clk),
.i_reset_n (i_reset_n),
// COUNT CONTROL
.i_store_set
(i_store_set),
.iv_ext_mem_addr
(iv_ext_mem_addr),
.o_store_avail (o_store_avail),
.o_load_ready (w_load_ready),
.i_load_clear (w_load_clear),
// DATA IN
.i_store_we
(i_store_we),
.iv_store_addr (iv_store_addr),
.iv_store_data (iv_store_data),
// DATA OUT
.iv_load_addr (wv_load_addr),
.ov_ext_mem_addr (wv_ext_mem_addr),
.ov_load_data (wv_load_data) );
endmodule
2.5 重要名词的中英文对照和解释
· 基地址( Base address) : 确定地址空间基本位置的地址,为了得到访问的具体地址还必须加上偏移量才能生成真实的地址。
· 硬件描述语言(HDL): Hardware Description Language 的英文缩写。
· 掩膜插头(即跳线插头)(Mask plug): 从物理上看,掩膜插头只是一个连接VDD或者VSS的线网,或者在高/低两个电平中选取一个作为输入的硬线开关。从而可以不需要在模块内部做任何修改,重新配置模块。有了掩膜插头,需要改变电路配置时,只要改换插头位置,因而不需要再重新综合一次以生成新配置电路。
· 锁相环 (PLL): Phase Locked Loop 的英文缩写
· 寄存器传输级 ( RTL): Register Transfer Level 的英文缩写
· 宏文本 (Text macro): `define 可以定义字符串的编译预处理指令
· 顶层模块 (Top level module): 虚拟器件设计层次中级别最高的模块。
· 用户定义原语 (UDP): User Defined Primitive 的英文缩写
3命名习惯
注意:以下各条款中凡是以R起头的条款是神州龙芯公司对编写Verilog代码的IP设计者所做的强制性规定,以G起头的条款是建议采用的规范。每个设计者必须严格遵守本规范。若有不同意见可以逐级上报,经过协商后形成本规范的新版本,再按照新规范执行。只有每个员工都严格遵守本规范,并能积极提出改进意见,才能形成一个高效率的,互相协作的良好工作环境。
3.1文件命名
R3.1 每文件最多只能包含一个模块。
每个模块必须用一个文件表示。在一个文件中不允许编写一个以上的模块。
(该模块的测试文件必须用另外一个文件表示,因此一个经过初步验证的模块必须用一个包含可综合模块和测试文件的文件夹来表示。)
原因:简化设计修改
R3.2 文件命名方式
文件名必须以下列方式构成:<设计单元名>:[<文件类型>]。<扩展名>。
其中,<设计单元名>是设计的单元名。
[<文件类型>] 标明文件类型(可选):
_task文件由任务构成,
_func文件由函数构成,
_parameter 文件由参数构成,
_defines文件由宏文本构成。
_disc文件是规则文件
_connect 文件是连接规则和连接模块文件
表示是个Verilog文件 .v是Verilog文件 .va是Verilog-AMS文件
原因:从文件名就可以知道设计代码的构成,简化了代码维护人员对设计结构和文件内容的理解
例子:spooler.v是模块spooler的代码。spooler_task.v 是包含spooler模块所用任务的文件。
R3.3 用不同的扩展名区分模拟信号、数字信号和混合信号的Verilog文件。
每个文件只能含有:(1)单一的数字Verilog文件 (以.v后缀)或者 (2)单一的模拟Verilog文件(以.va后缀)或者(3)单一的混合Verilog文件。(以 .vams后缀)
原因:数字编译器无法处理模拟结构或混合结构;同时,模拟编译器也无法处理数字结构或混合结构的文件,所以从文件名就能区分三种不同类型的文件可以减少混乱。
3.2 HDL代码部件的命名
有含义的名字比几行注释对代码的维护人员更有帮助。因此,名字必须有含义(有含义是指名字所涉及对象的性质和目的可在该名字中清楚地体现)。
R3.4 命名必须由字母和数字和下划线构成
模块部件的命名必须由字母和数字和下划线构成[A-Z,0-9,a-z],不允许使用连续的下划线。原因: 由下划线分隔的名字,其含义比较容易理解。
R3.5命名必须以字母开头,不能以下划线开头
模块部件和信号的命名必须以字母开头,不允许用下划线起头的命名
原因:综合和仿真工具不支持以下划线起头的文件名。
R3.6 名字中不能包含任何转义字符(ESCAPED NAMES)
模块名、信号名和文件名中不能包含转义字符 。
原因:有些工具不允许使用包含转义字符的文件名。
R3.7 必须用下划线隔开由几个词组成的部件名
对于有几个词组成的命名,应用下划线分开每个词。不允许用头一个字母大写的字来区分字段。
原因:这样做,不但为了改进名字的可读性,也是为了统一。
例子:ram_addr。
R3.8 在整个设计中,命名风格和拼写风格必须保持一致和连贯
在整个设计中,线网和变量的命名风格和拼写风格必须保持一致和连贯,这也包括命名习惯。
原因:一看信号名就可以知道信号的类型(例如:分辨出低电平有效信号、时钟、输入、输出、单个信号、总线等),便于调试。
R3.9 Verilog代码中模块的命名要必须与文件名字完全一致(扩展名除外)
所有在Verilog RTL代码中涉及到的模块和信号名必须与技术文档中的名字保持一致。在Verilog RTL的注释中对信号和模块名的引用也要保持一致。
原因:确保文挡和代码之间的交叉引用的正确。
R3.10 表示常量的命名必须大写
表示常量的命名必须全由大写字母组成。这里常量是指:参数名和宏名。
原因:在配置和仿真时,可以立即分辨出哪些对象的值是不会改变的,例如参数值是不变的。
例子:parameter BYTE_SIZE = 16, MSB = 7;
R3.11 线网名,变量名,结构名和对象名必须都用小写字母表示
与电路结构有密切关系的硬件结构名必须全部都用小写字母表示。这包括:线网名、变量名、结构名(如functions, tasks, 命名的块、模块、或是用户原语)和对象名(如门级电路、模块等)。
原因:便于将仿真时将值会发生变化的对象和值不会发生变化的对象区分开来。
R3.12 每个部件必须有自己独特的名字,绝对不允许用与别的部件相同的名字(不允许用字母大小写来区分不同的名字)
绝对不允许用字母的大小来区分结构名、线网名、或变量名
原因:有的工具不能区分字母的大小写。如,可以把VHDL代码转换到Verilog 代码的工具不能区分字母的大小写。
R3.13 必须使用有意义的命名
命名必须有含义,以便对命名对象的目的一目了然。应该根据对象的用途进行命名,而不是根据达到目的的手段来命名。这些对象包括:线网、变量、参数、对象(诸如functions、module)结构。所有的命名一律采用英语,不允许使用汉语拼音字。
原因:便于维护。在命名中,根据目的而不根据手段进行命名的方式有助于理解设计。手段可以通过理解代码得到,而目的则不这么明显。
例子:set_priority 用于线网名、变量
SBUS_DATA_BITS 用于参数
ram_addr_p3 用于可选的流水线级的标志(optional pipeline stage indication)。
R3.14 不允许使用Verilog和VHDL的关键词
Verilog和VHDL关键词都不能用作信号名或其他任何命名。
原因:便于Verilog和VHDL的混合使用
R3.15 宏定义必须放在模块内或者放在专门定义宏的文件中,统一管理
由 `define定义的宏文本声明语句必须放在模块名后,如:<顶层模块名>_<宏名>
原因:放在模块定义语句外的宏定义有可能被其他层次模块的宏定义搞混,从而发生无意中对某个模块外的宏定义进行重新定义的错误。
R3.16 对于后缀的使用必须制定严格的规定
后缀的使用必须符合本规范从R 3.17 节到 G3.26条款的要求。
原因:连贯一致的命名风格有助于对设计的理解。
R 3.17 对低电平有效信号进行命名时,必须使用“_n” 作为名字的后缀 ,其他情况一律不允许使用“_n”作为名字的后缀。
当且仅当为低电平有效信号命名时,才允许使用“_n”为后缀的信号名。
原因:有意义的、连贯一致的命名风格有助于对设计的理解。
例子:enable_data_n, reset_n
R 3.18以“_clk”结尾的信号名
时钟信号的名字中若没有“clock 或者clk”时,则必须使用后缀“_clk”为该时钟信号命名。
原因:有意义的、连贯一致的命名风格有助于对设计的理解。
例子:fifo_transmit_clk
例外:名字能清楚地表明该信号是时钟信号,(例如, system_clock 或者 clk32m也能清楚地表明是时钟信号 )
G 3.19 未连接的输出信号以“_nc”结尾
建议未使用的模块输出信号命名以“_nc”结尾 (nc: 表示尚未连接)
例子:blockx blockx (.result({result[15:3], result_nc[2:0]}), ...);
blockx blockx (.result(result[15:0]), ...);
wire result_nc[2:0] = result[2:0];
原因:当出现有信号尚未连接的警告时,若信号的命名是以“_nc”结尾的,则可知该信号是设计者故意不连接的,不需要进行修改。
G 3.20 三态信号名以“_z “结尾
建议三态信号名以“_z “结尾
原因:有含义的、连贯一致的命名风格有助于对设计代码的理解。
例子:ram_data1_z
G 3.21 信号名长度不超过32位字符
建议信号名长度不超过32位字符。32位字符里不包括层次名
原因:较短的命名可提高可读性
G 3.22 避免不容易理解的缩略
建议避免使用不容易理解的缩略语,尤其是只有一个字符的缩略语作为信号名称。
原因:使用有含义的命名,才能帮助代码的设计和维护者理解代码。
G 3.23 建议引用的实例化模块名与实例名相同,用索引号区别这两者
引用的实例化模块的命名应该与被引用的实例名相同,用索引号区别这两者。一个实例模块的多次实例化引用模块用整数索引加以区分。
原因:可以增进可读性、减少模糊性
例子:blockx blockx_1 (...);
blockx blockx_2 (...);
-------------------------------------------------------------
4 注释(Comments)
注释可用于描述 Verilog HDL代码的功能,特别需要提醒设计者注意的是,只依靠读代码很难理解的设计意图必须在代码中添加注释加以说明。
4.1 文件头(File Headers)
每一个可综合的Verilog RTL级电路模块、虚拟器件和测试模块文件必须具有下面格式的文件头。设计规范规定:文件头的格式必须与下面的格式一致,以便于将来可用软件对模块代码进行分析处理。文件头中大写的关键词可以用来检索。下面的这个可以保证文件头的一致性。下面所示的文件头只是最小要求。在“REUSE ISSUE”段之后,还可以再添加其他的文件头.另外,有关版权的文件头也应该包括在文件头中。
// +FHEADER-----------------------------------------------------------------
// Optional Copyright (c)
// Optional Company Confidential
// ----------------------------------------------------------------------
// FILE NAME :
// DEPARTMENT :
// AUTHOR:
// AUTHOR’S EMAIL :
// --------------------------------------------------------------------
// RELEASE HISTORY
// VERSION DATE AUTHORDESCRIPTION
// 1.0 YYYY-MM-DD name
// ---------------------------------------------------------------------
// KEYWORDS : General file searchinGkeywords, leave blank if none.
//-----------------------------------------------------------------------
// PURPOSE : Short description of functionality
// ----------------------------------------------------------------------
// PARAMETERS
// PARAM NAME RANGE : DESCRIPTION : DEFAULT : UNITS
// e.g.DATA_WIDTH [32,16] : width of the data : 32 :
// ----------------------------------------------------------------------
// REUSE ISSUES
// Reset Strategy :
// Clock Domains :
// Critical TiminG:
// Test Features :
// Asynchronous I/F :
// Scan Methodology :
// Instantiations :
// Synthesizable (y/n) :
// OtheR:
// -FHEADER-------------------------------------------------------------
R 4.1 每个文件必须有文件头(header)
每一个文件必须包括如上面代码段所示的文件头。其中,所有的区域都必须包括在内,甚至空的数据段。
原因:按照规范编写的标准文件头便于建立公司内部的设计信息查询系统。
R 4.2 使用文件头界标记 [+FHEADER & -FHEADER]
标签+FHEADER& -FHEADER一定要用来定义头信息的界限。(the boundary of the 文件头 information)
原因:这是识别文件头的简单方法,标明该头是文件头,便于用文本工具自动地查询存档的资料。
R 4.3 文件头内必须包含文件名
文件头中必须包含文件名
原因:这样做提供了一种简单的方法以便用文本处理工具自动地查询相关的设计文件。
R 4.4 文件头中必须包含联系方式
文件头中必须包含有关本代码的多种信息,其中包括开发小组的名称、作者名、版本历史、作者电话、电子邮件和邮寄地址。
原因:必要时可以找到原作者询问只从设计文档无法理解的问题。
R 4.5 文件头包含发布历史
文件头必须要包含进入虚拟器件(VC)库的修改历史,最近的修改列于最后。日期格式必须采用YYYY-MM-DD。这个信息对于集成器是有用的。本地的修改历史不应该包含其中。
原因:要求去记录设计的修改历史。
R 4.6 文件头包含一个关键字段
文件头必须包含便于搜索的关键字段。该字段应该包含有关本模块功能的简要说明,或是能与本模块配合运行的总线和系统的名称。
原因:关键字可提供快速的搜索机制,便于自动文本处理工具在庞大的虚拟器件 (VC)库中搜索合适的器件。如果没有关键字,该条目应该空着。
例子:sdram, address decoder, coldfire, sbus, amba,usb2.0
R 4.7 文件头必须包含一段描述模块功能的说明
文件头必须包含一段描述本模块功能的说明,而不是如何操作或运行方式的说明。
原因:有助于对模块功能的理解。
R 4.8 文件头必须包含参数描述文件的名和路径
文件头必须包含描述本模块代码所使用的参数文件的名和路径。缺省值必须都在参数文件中列出。有效值域也必须标出。
原因:有助于对Verilog HDL代码的理解
R 4.9 复位策略必须在头文件中说明
在头文件中必须详细说明复位策略。包括说明是同步复位还是异步复位,是内部复位还是外部上电复位,是硬复位还是软复位,以及该模块是否能用单个复位来调试。
原因:改善代码的可读性,突出重点和必需的综合步骤。
R 4.10 对时钟域(clock domain)的说明
在头文件中必须详细说明所有的时钟和时钟策略。
原因:说明内部生成的时钟或是分频的时钟,便于对代码和时钟策略的理解。
---------------------------------------------CCCCCCC------------------------------------------
R 4.11 对关键布线路径的说明
包括外部时机关系的决定性的时机必须记录。文件头的位置可以包含含有决定性的时机的文件名(如creation guide)
原因:建立时机和输出时机关系突出了必需的综合和测试。
R 4.12 记录测试的特点
任何具体的代码中的用于提高测试速度的测试特色必须记录。
原因:一旦可视化部件被集成,这点可用来改善对代码的理解和测试。
例子:parallel clocking, BIST
R 4.13 需要详细的异步接口
异步接口必须包括时间关系和相关频率
原因:有助于对设计的理解,并且有助于决定是否需要额外的同步的stages用于一个不同目标的应用。
R 4.14 标明扫描方法的风格
有关于扫描风格的标注必不可缺
原因:有助于设计的集成
例子:Mux-D oRLSSD
R 4.15 文档实例化
文件头必须包括有关于文档内每一个单元、模块、函数调用、任务是如何实例化的部分。(参考R 4.30, R 7.4, G 10.23)
原因:标明必须用于重定义技术的区域,并且帮助理解设计层次。
例子:实例化 mux2s cell, decode task
原因:绝大部分由实例组成的模块。
R4.16 标明可综合能力
综合结构的能力必须以指定的YES或NO标明
原因:直接标明模块的使用路径(如:是否该模块可被用于仿真)
G 4.17 其他头文档(OtheRheadeRdocumentation)
建议文件头包含额外的相关信息——这些信息用于集成器或可以使代码更易理解。这一部分信息有助于设计者的判断,并可保持附加信息点的位置连续性。
4.2 额外的结构头(Additional Construct Headers)
文件中每添加一个结构(如:函数、任务、用户定义的原语)必须在文件中插入如下面注释段所示的文件头。下面文件头包含了:Verilog函数、用户定义的原语和任务的说明注释。文件头的格式必须与下面注释段的格式一致,以保证该文件头可以用软件进行语法分析。头中的大写的关键词可以用于这类信息的搜索关键词。下面的模板格式保证了这类文件头的一致性。
Verilog 函数、用户定义的原语和任务的文件头
//+FHEADER/////////////////////////////////////////////////////////////
// NAME :
// TYPE :TYPE can be func, task, primitive
// ---------------------------------------------------------------------
// PURPOSE : Short description of functionality
// ---------------------------------------------------------------------
// PARAMETERS
// PARAM NAME RANGE : DESCRIPTION : DEFAULT : UNITS
// e.g. DATA_WIDTH_PP [32,16] : width of the data : 32 :
// ---------------------------------------------------------------------
// OtheR: Leave blank if none.
// -FHEADER //////////////////////////////////////////////////////////
R 4.18 文件中的额外的结构需要在头中标注
在文件中的所有的额外的结构必需要在头中如图 7-2一样被记录。所有的域都必须包括,除非那个数据是空的。
原因:这样规定了一种提供相关设计信息的标准方式。
R 4.19 使用结构头界标志(+HDR& -HDR)
结构头界标志(+HDR& -HDR)必须用来定义头信息的边界。
原因:这是一种简单的方式来定义头,表明该头是个结构头。
R 4.20 包括结构的名字
结构头必须要包括额外结构的名称。
原因:提供了一种简单确定结构内容的方式。
R 4.21 包含结构类型
结构头必须包含结构类型。
原因:提供了一种简单确定结构内容的方式。
R 4.22 包含一个目的段
结构头必须包含一个目的段来描述结构功能。该目的段必须描述该单元的设计目的而不是实现方式。
原因:有助于理解结构功能。
R 4.23 包含一个参数描述
结构头必须包含关于该结构所使用的参数的描述。参数的缺省值必须要列出来。对于Verilog-AMS文件,参数的单位也同时要列出来。
原因:有助于理解HDL代码。
G 4.24 其他的头文档
建议文件头包含额外的相关信息——这些信息用于集成器或可以使代码更易理解。
原因:有助于对设计的理解。
4.3 其他注释(OtheRComments)
用来描述HDL代码的功能和流向的注释是要求的。这些注释必须足够用来另一个设计者对该设计的理解和维护。
R 4.25 注释功能段
在每一个代码的功能段之前必须要有描述代码内容和功能的注释。
原因:有助于理解代码。
R 4.26 记录不寻常的和不明显的执行
不寻常的和不明显的执行必须解释,同时他们的局限必须在注释中记录。
原因:改善代码的可读性。不寻常的和不明显的执行的目的和含义通常是需要解释的。
R 4.27 采用单行注释
以“//”开头的单行注释必须被采用,而以“/*….*/”开头的多行注释应避免使用。
原因:改善可读性和改善代码语法分析。
R 4.28 无关信号的集成必须被记录
在设计者集成了无关信号的情况下,一定要有详细的文档。
原因:便于对模块的理解。
例子:包含无关信号的具体用途的命令总线。
R 4.29 删除旧代码
旧代码或是没用的代码必须被删掉,而不是注释出。
原因:便于理解。
R 4.30 注释单元的实例化
任何实例化单元的功能及该单元被实例化而不是引用的原因都必须被注释。这些单元可以来自库文件而不是用诸如Verilog的硬件描述语言所编制的模块,可以是具有隐藏功能的单元,或是客户定制的单元。(参看R4.15, R 7.4 and G10.23)
原因:实例化的单元限制了设计的技术移植性。这些单元也可拥有他们隐藏的功能,或是改进对代码的理解能力。
例外:不能应用于不可综合的模块(例如:具有总线功能的模块,总线监视器或是模拟模块)除非他们被用来综合仿真。
R 4.31 注释端口声明
每一个端口声明必须有一个描述性的注释,最好是位于同一行。如果注释不是与被注释的代码位于同一行,那么注释应位于被注释代码的前面。
原因:改善可读性
例外:自动生成的代码
G 4.32 注释其他的声明
诸如线网名和变量的其他的声明,必须拥有相应的描述性的注释,最好位于同一行。如果注释不是与被注释的代码位于同一行,那么注释应位于被注释代码的前面。
原因:改善可读性
例外:自动生成的代码
R 4.33 记录清楚的输入输出时钟
不被工具引用的输入输出时钟必须在代码中记录。
G 4.34 记录SR锁存器的用法
建议SR锁存器的用法在代码中被记录下来。
原因:简化HDL代码的理解。
R 4.35 注释综合指令
所有专用于综合的指令必须在使用的地方注释——说明使用它们的原因,使用的工具和指令。
原因:表明专门为某个综合工具所写的代码,或是期望某种结果的代码是建立在某种综合工具之上的。
例子:The infer_mux directive is needed to ensure that it is not optimized away during
synthesis.
// clock mux to select functional oRscan mode)
always @(test_scan oRtest_clk_en oRclk_enable)
case (test_scan) // synopsys infer_mux
1'b1 : clk_enable_mux <= test_clk_en; // scan mode
default: clk_enable_mux <= clk_enable; // functional mode
endcase
R 4.36 注释编译指令
编译器指令,诸如`ifdef, ‘ifndef and `else,必须在使用的地方注释,描述该指令的用法
原因: 这样可以改善代码的可读性和移植性。
例子: `ifdef test_messages //enable messages foRsimulation debug
...
`else //normal operation, no messages
...
`endif //end test_messages
G 4.37 注释结尾的代码和陈述
建议每一个结尾都有一段注释——说明该结尾结束了一个什么样的结构。
原因:改善可读性。可以更容易的鉴定出结构的边界。
例子:always @()
begin:
...
end //
or
case () //
...
endcase //
G 4.38 自由清楚地使用注释
建议在整个代码中自由清楚地使用注释——来描述代码目的、功能、设计过程和特殊处理。一定要避免模糊地注释。(诸如:a <= b; // save b into a)
原因:可以增进对代码的理解
5 代码风格(Code Style)
R 5.1 必须按照标准样板的格式编写代码
代码的格式必须统一。(同类的代码项要对齐)
原因:增进可读性。当写一个代码块(诸如begin,case,if statement等等)时,首先完成代码框架是非常有用的,具体来说,就是把这个代码块的“end”与“begin”对齐。
R 5.2 使用2-4格代码缩进
在代码对齐中必须采用固定的2-4格缩进。不能使用“TAB”键。使用空格键和空行来增加代码的可读性。文本编辑器的“TAB”键可能被映射成插入空格。
原因:增加可读性。不允许使用“TAB”键,因为它在不同的文本编辑器中有不同的含义。
R 5.3 每一行只有一个Verilog语句
每一行最多只能有一个Verilog语句。不要在同一行中集中多个分号分开的Verilog的语句。
原因:增加可读性。简化用设计工具来对代码进行语法分析。