[[stepfpga_code_spec]]
### 1.RTL CODE 规范
------
===1.1标准的文件头===
------
在每一个版块的开头一定要使用统一的文件头,其中包括作者名,模块名,创建日期,概要,更改记录,版权等必要信息。
统一使用以下的文件头:其中*为必需的项目
//********************************************************
//
// Copyright(c)2016, ECBC
// All rights reserved
//
// File name : MODULE_NAME.v
// Module name : MODULE_NAME
// Author : STEP
// Description :
// Email : Author’s email
// Data : 2016/08/01
// Version : current version, just this: v1.0
//
// Abstract :
//
// Modification history
// ----------------------------------------------------------------------------
// Version Data(2016/08/01) V1.0
// Description
//
//*************************************************************
===1.2标准的module格式===
------
对于模块的书写采用统一的格式便于项目内部成员的理解和维护,我们用批处理建立了一个MODULE模块,其内容解释如下:
\\ 端口定义按照输入,输出,双向的顺序:
\\ 模块名、模块例化名统一,例化名前加大写U_以区分 ( 多次例化另加标识 ),三者关系:
\\ 文件名 :xxx .v (小写)
\\ 模块名 :XXX (大写)
\\ 例化名 :U_XXX (大写)
\\ IP 内部所有的模块名都要加IP名或者IP名简称作前缀,如USB_CTRL、USB_TX_FIFO。
// *****************************
// DEFINE MODULE PORT //
// ******************************
//
module MODULE_NAME //模块名一行
( //括号顶格,端口部分换行
// INPUT //尽量先输入,后输出定义
input_port_1, //可同时按接口对象等分类,一行一个
…
input_port_m,
// OUTPUT
output_port_1,
…
output_port_m,
);
// *****************************
// DEFINE PARAMETER
// ******************************
parameter… //参数名采用大写
// ******************************
// DEFINE INPUT
// ******************************
input rst_n ; // reset, (active low) . //input到寄存器名之间四个tab键,注意对齐
input clk_* ; // clock signal , 50M . //注意注释的格式,简洁有力,尽量使用英文
input [n:0] a_din ; // ***** //此处是在模块名部分没有声明端口类型时用
input [k:0] b_din ; // ***** //注释尽量不要挨到前面,然后全左对齐
// ******************************
// DEFINE OUTPUT
// ******************************
output [m:0] a_dout ; // ***** //位宽定义和output之间加一个tab或空格,统一即可
output [i:0] b_dout ; // *****
// ******************************
// OUTPUT ATRRIBUTE
// ******************************
// REGS
reg [m:0] a_dout ; // *****
//WIRES
wire [i:0] b_dout ; // *****
// ******************************
// INSTSNCE MODULE
// ******************************
MODULE_NAME_A U_MODULE_NAME_A( //例化名从和模块名相距四个tab,括号后换行
.A (A ), //端口和例化名对齐,后3个tab再括号连线
.B (B ), //括号内3个tab的宽度,全对齐
.C (C ),
); …
// ******************************
//MAIN CODE
// ******************************
… …
… …
… …
// ****************************** //
endmodule //结尾顶格,中间部分均从一个tab开始
===1.3一致的排版===
------
\\ A. 一致的缩排
//统一的缩排取4个空格宽度
//输入输出信号的宽度定义与关键字之间,信号名与宽度之间要用tab分开;所有宽度定义对所有信号名对齐,代码风格统一如下:
input [3:0] input_a ; // *****
input input_b ; // *****
…
output [128:0] output_a ;
output [15:0] output_b ;
output output_c ;
\\ B.一致的 begin end 书写方式
//always 中,一定要用begin end 区分,格式和代码风格统一如下:
always @ (postedge clk or negedge rst_n)
begin
if (rst_n==1’b0)
syn_rst<= ‘DLY 1’b0;
else
begin
if (a==b)
syn_rst<= ‘DLY 1’b1;
else
syn_rst<= ‘DLY 1’b0;
end
end
//if else 中仅有一个语句行时,不要使用begin end; 如果有多个语句行时,begin end和if ()或else ()空四个格。 格式如下:
if (…)
…
else if (…)
else
//********************************************************************
if (…)
…
else if (…)
begin
…
…(
end
else
===1.4 一致的信号命名风格===
------
简洁,清晰,有效是基本的信号命名规则,详见命名规范。
^全称 ^缩写 ^中文含义^
|acknowledge |ack |应答|
|adress |addr(ad) |地址|
|arbiter |arb |仲裁|
|check |chk |校验,如CRC校验|
|clock |clk |时钟|
|config |cfg |Configuration,装置|
|control |ctrl |控制|
|count |cnt |计数|
|data in |din(di) |数据输入|
|data out |dout(do) |数据输出|
|decode |de |译码|
|decrease |dec |减一|
|delay |dly |
|disable |dis |不使能|
|error |err |错误(指示)|
|enable |en |使能|
|frame |frm |帧|
|generate |gen |生成,如CRC生成|
|grant |gnt |申请通过|
|increase |inc |加一|
|input |in(i) |
|length |len |(帧、包)长|
|nmport |nm |网管相关|
|output |out(o) |
|packet不推荐packet |pkt |与帧相同|
|priority |pri |优先级|
|pointer |ptr |指针|
|rd enable |ren |读使能|
|read |rd |读(操作)|
|ready |rdy |应答信号或准备好|
|receive |rx |(帧数据)接收|
|request |req |(服务、仲裁)请求|
|reset |rst |
|segment |seg |
|souce |scr |源(端口)|
|ststistics |stat |统计|
|timer |tmr |定时器|
|switcher |sf |Switch fabric|
|temporary |tmp |临时|
|transmit |tx |发送(帧数据)相关|
|Valid |vld(v) |有效、校验正确|
|wr enable |wen |写使能|
|write |wr |写操作|
\\ a.端口、信号、变量名的所有字母小写:函数名、宏定义、参数定义用大写
\\ b.使用简称、缩略词(加上列表)
\\ c.基于含义命名(避免以数字命名的简单做法),含义可分段(最多分三段),每一小段之间加下划线”_”,如tx_data_val;命名长度一般限制在20个字符以内。
\\ d.低电平有效信号,加后缀”_n”,如 rst_n
\\ e.无条件寄存的寄存信号在原信号上加ff1、ff2… 如原信号 data_in, 寄存一拍data_in_ff1,寄存两拍data_in_ff2
\\ f.不能用 ”reg”,作为最后的后缀名,因为综合工具会给寄存器自动加上_reg, 如果命名里就用_reg作为后缀名则扰乱了网表的可读性。
====2.模板示例====
------
//********************************************************
//
// Copyright(c)2016, ECBC
// All rights reserved
//
// File name : MODULE_NAME.v
// Module name : MODULE_NAME
// Author : STEP
// Description :
// Email : Author’s email
// Data : 2016/08/01
// Version : current version, just this: v1.0
//
// Abstract :
//
// Modification history
// ----------------------------------------------------------------------------
// Version Data(2016/08/01) V1.0
// Description
//
//*************************************************************
//*******************
//DEFINE(s)
//*******************
//*******************
//DEFINE(s)
//*******************
//`define UDLY 1 //Unit delay, for non-blocking assignments in sequential logic
//*******************
//DEFINE MODULE PORT
//*******************
module MODULE_NAME
(
//INPUT
rest_n ,
clk_* ,
a_din ,
b_din ,
//OUTPUT
a_dout ,
b_dout
);
//*******************
//DEFINE PARAMETER
//*******************
parameter T1S = 24_999_999;
//*******************
//DEFINE INPUT
//*******************
input rst_n ; //reset, active low .
input clk_* ; //clock signal, 50M .
input [n:0] a_din ; //*****
input [k:0] b_din ; //*****
//*******************
//DEFINE OUTPUT
//*******************
output [m:0] a_dout ; //*****
output [i:0] b_dout ; //*****
//********************
//OUTPUT ATTRIBUTE
//********************
//REGS
reg [m:0] a_dout ; //*****
//WIRES
wire [i:0] b_dout ; //*****
//*********************
//INNER SIGNAL DECLARATION
//*********************
//REGS
reg [3:0] counter ; //*****
//WIRES
wire [7:0] temp1 ; //*****
//*********************
//INSTANTCE MODULE
//*********************
//**************************************************************
//instance of module MODULE_NAME_A filename:module_name_a.v
//**************************************************************
MODULE_NAME_A U_MUDULE_NAME_A(
.A (A ),
.B (B ),
.C (C )
);
//*********************
//MAIN CORE
//*********************
//Sequential logic style
always@(posedge clk_* or negedge rest_n)
begin : SEQ_BLOCK_NAME
if (rst_n==1’b0)
counter<=4’b0;
else
begin
if (expression)
counter <= #`DLY siginal_b;
else;
end
end // SEQ_BLOCK_NAME
//Combinational logic style
always@(signal_a or signal_b)
begin:COM_BLOCK-NAME
case (expression)
item1 :begin
signal_c=*****;
end
item2 : //statement;
default ://statement;
endcase
end // COM_BLOCK_NAME
assign out = expression ? (1’b0):(1’b1);
//*********************
endmodule