马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
x
//****************************//copynoright(c):萌新转载的,大家还请见谅
//file name :coding style
//data :2017-11-29
//author :ZzItachi
//****************************
[size=15.0000pt]一、 RTL CODE 规范
1.标准的文件头 在每一个版块的开头一定要使用统一的文件头,其中包括作者名,模块名,创建日期,概要,更改记录,版权等必要信息。 统一使用以下的文件头: // ************************************************************** // COPYRIGHT(c)2005, Hislicon Technologies Co, Ltd // All rights reserved. // // IP LIB INDEX : IP lib index just sa UTOPIA_B // IP Name : the top module_name of this ip, usually, is same // as the small ip classified name just as UTOPIA
// File name : file_name of the file just as “tx_fifo.v” // Module name : module_name of this file just as “TX_FIFO” // Full name : complete Emglish nme of this abbreviated // // Author :
Athor/ID
// Email : Author’s email // Data : // Version : V 1.0 // //Abstract : // Called by : Father Module // // Modification history // ------------------------------------------------------------------------------------------------------ // // // $Log$ // // *********************************************************************
2. 标准的module 格式 (module 整体结构) 对于模块的书写采用统一的格式便于项目内部成员的理解和维护,我们用批处理建立了一个MODULE模块,其内容解释如下: [size=10.5000pt]l 端口定义按照输入,输出,双向的顺序: [size=10.5000pt]l 模块名、模块例化名统一,例化名前加大写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 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 ATRRIBUTE // // ****************************** // REGS reg [m:0] a_dout ; // ***** //WIRES wire [i:0] b_dout ; // *****
// ****************************** // INSTSNCE MODULE // // ****************************** MODULE_NAME_A U_MODULE_NAME_A( .A (A ), .B (B ), .C (C ), ); …
// ****************************** //MAIN CODE // // ****************************** … … … … … … // ****************************** // Endmodule
3.一致的排版 A. 一致的缩排 [size=10.5000pt]l 统一的缩排取4个空格宽度 [size=10.5000pt]l 输入输出信号的宽度定义与关键字之间,信号名与宽度之间要用空格分开;所有宽度定义对所有信号名对齐,代码风格统一如下:
input [3:0] input_a ; // *****
input input_b ; // ***** … output [128:0] output_a ; output [15:0] output_b ; output output_c ; A. 一致的 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 4. 一致的信号命名风格 简洁,清晰,有效是基本的信号命名规则,详见命名规范。
全称[size=10.5000pt] | 缩写[size=10.5000pt] | 中文含义[size=10.5000pt] | acknowledge[size=10.5000pt] | ack[size=10.5000pt] | 应答[size=10.5000pt] | adress[size=10.5000pt] | addr(ad)[size=10.5000pt] | 地址[size=10.5000pt] | arbiter[size=10.5000pt] | arb[size=10.5000pt] | 仲裁[size=10.5000pt] | check[size=10.5000pt] | chk[size=10.5000pt] | 校验,如CRC校验[size=10.5000pt] | clock[size=10.5000pt] | clk[size=10.5000pt] | 时钟[size=10.5000pt] | config[size=10.5000pt] | cfg[size=10.5000pt] | Configuration,装置[size=10.5000pt] | control[size=10.5000pt] | ctrl[size=10.5000pt] | 控制[size=10.5000pt] | count[size=10.5000pt] | cnt[size=10.5000pt] | 计数[size=10.5000pt] | data in[size=10.5000pt] | din(di)[size=10.5000pt] | 数据输入[size=10.5000pt] | data out[size=10.5000pt] | dout(do)[size=10.5000pt] | 数据输出[size=10.5000pt] | decode[size=10.5000pt] | de[size=10.5000pt] | 译码[size=10.5000pt] | decrease[size=10.5000pt] | dec[size=10.5000pt] | 减一[size=10.5000pt] | delay[size=10.5000pt] | dly[size=10.5000pt] |
| disable[size=10.5000pt] | dis[size=10.5000pt] | 不使能[size=10.5000pt] | error[size=10.5000pt] | err[size=10.5000pt] | 错误(指示)[size=10.5000pt] | enable[size=10.5000pt] | en[size=10.5000pt] | 使能[size=10.5000pt] | frame[size=10.5000pt] | frm[size=10.5000pt] | [size=10.5000pt]帧[size=10.5000pt] | [size=10.5000pt]generate[size=10.5000pt] | gen[size=10.5000pt] | 生成,如CRC生成[size=10.5000pt] | grant[size=10.5000pt] | gnt[size=10.5000pt] | 申请通过[size=10.5000pt] | increase[size=10.5000pt] | inc[size=10.5000pt] | 加一[size=10.5000pt] | input[size=10.5000pt] | in(i)[size=10.5000pt] |
| length[size=10.5000pt] | len[size=10.5000pt] | (帧、包)长[size=10.5000pt] | nmport[size=10.5000pt] | nm[size=10.5000pt] | 网管相关[size=10.5000pt] | output[size=10.5000pt] | out(o)[size=10.5000pt] |
| packet不推荐packet[size=10.5000pt] | pkt[size=10.5000pt] | 与帧相同[size=10.5000pt] | priority[size=10.5000pt] | pri[size=10.5000pt] | 优先级[size=10.5000pt] | pointer[size=10.5000pt] | ptr[size=10.5000pt] | 指针[size=10.5000pt] | rd enable[size=10.5000pt] | ren[size=10.5000pt] | 读使能[size=10.5000pt] | read[size=10.5000pt] | rd[size=10.5000pt] | 读(操作)[size=10.5000pt] | ready[size=10.5000pt] | rdy[size=10.5000pt] | 应答信号或准备好[size=10.5000pt] | receive[size=10.5000pt] | rx[size=10.5000pt] | (帧数据)接收[size=10.5000pt] | request[size=10.5000pt] | req[size=10.5000pt] | (服务、仲裁)请求[size=10.5000pt] | reset[size=10.5000pt] | rst[size=10.5000pt] |
| segment[size=10.5000pt] | seg[size=10.5000pt] |
| souce[size=10.5000pt] | scr[size=10.5000pt] | 源(端口)[size=10.5000pt] | ststistics[size=10.5000pt] | stat[size=10.5000pt] | 统计[size=10.5000pt] | timer[size=10.5000pt] | tmr[size=10.5000pt] | 定时器[size=10.5000pt] | switcher[size=10.5000pt] | sf[size=10.5000pt] | Switch fabric[size=10.5000pt] | temporary[size=10.5000pt] | tmp[size=10.5000pt] | 临时[size=10.5000pt] | transmit[size=10.5000pt] | tx[size=10.5000pt] | 发送(帧数据)相关[size=10.5000pt] | Valid[size=10.5000pt] | vld(v)[size=10.5000pt] | 有效、校验正确[size=10.5000pt] | wr enable[size=10.5000pt] | wen[size=10.5000pt] | 写使能[size=10.5000pt] | write[size=10.5000pt] | wr[size=10.5000pt] | 写操作[size=10.5000pt] |
a. 端口、信号、变量名的所有字母小写:函数名、宏定义、参数定义用大写 b. 使用简称、缩略词(加上列表) c. 基于含义命名(避免以数字命名的简单做法),含义可分段(最多分三段),每一小段之间加下划线”_”,如tx_data_val;命名长度一般限制在20个字符以内。 d. 低电平有效信号,加后缀”_n”,如 rst_n e. 无条件寄存的寄存信号在原信号上加ff1、ff2… 如原信号 data_in, 寄存一拍data_in_ff1,寄存两拍data_in_ff2 [size=10.5000pt]f. 不能用
”reg”,作为最后的后缀名,因为综合工具会给寄存器自动加上_reg, 如果命名里就用_reg作为后缀名则扰乱了网表的可读性。
5.统一的表达式书写 A. 括号的使用 如果一个表达式的分组情况不是很明显时,加上括号有助于理解。 例如下面的代码加上括号就清晰很多。 if (&a==1’b1&&!flag==1’b1 || b==1’b1) // 改为: if ((&a==1’b1)&&(!flag==1’b1)||( b==1’b1)) // B. 适当的使用空格 一般表达式在运算符的两侧要各留出一个空格,但定义比较长的表达式,去掉预先级高的运算符前的空格,使其与运算对象紧连在一起,可以更清晰的显示表达式结构。
还是上面的例子: if ((&a==1’b1)&&(!flag==1’b1)||( b==1’b1)) // 改为: if ((&a == 1’b1)&&(!flag == 1’b1)||( b == 1’b1)) // ”<=”, ”==”前后都要加空格。
C. 赋值要指明比特宽度
赋值或者条件判断时要注明比特宽度,注意表达式的位宽匹配。如:
reg [4:0] signal_a; 错误: 1 signal_a <= 5; 2 if(signal_a == 5) 3 signal_a <= signal_b[3:0]+4; 正确: 1 signal_a <= 5d5 2 if(signal_a == 5d5) 3 signal_a <= {1’b0, signal_b[3:0]+5d4 因为工具默认是32位宽,如果不注明位宽,工具检查会报warning,而且这样增加了设计的严谨性。
6.统一的语句书写――条件判断结构书写方式 A. 条件的完整性
If else搭配使用,对于缺省的条件要写”else;”;
If elsed 条件判别式要全面,比如if(a == 1’b0);
Case中的缺省条件要写”default”;
B.”if else”结构:适用于复杂条件判断的语句 但对于复杂的条件判断,使用?:如果不仔细分析条件的每一条路径,就让读代码搞不清它是到底要做什么。例如:
C = (!Ic&&!rc)?0(Ic?rc:Ic) // (?
改为: always @(Ic or rc) // if else begin if ((Ic==0)&&(rc==0)) c = 0; else if (Ic==1) c = rc; else c = Ic; end 即使是简单的条件判断,我们也必须使用IF-ELSE,当涉及复杂的条件判断,使用IF-ELSE结构以获得清晰的结构便于理解和维护。因此必须使用IF-ELSE。 C.”IF ELSE”结构VS”CASE”结构 IF ELSE结构综合的结构可能是与或非门构成的,也可能是一组多路选择器,而case结构综合结果一般会是多路选择器,但对于可以优化的case综合工具会综合出更简单的结构。 所有对于可以写出平行结构的条件,优先写成case结构,例如地址译码等,条件之间有重复和嵌套的情况则是写成if else结构。 D. Finite State Machine 不允许有模糊不清的状态机模式,所有的状态机必须清晰明了。 我们要求将状态机的时序部分和组合逻辑部分分开。 例如:
module state4 (
clock reset out ); input reset input clock; output [1:0] out; parameter [1:0] stateA=2’b00; parameter [1:0] stateB=2’b01; parameter [1:0] stateC=2’b10; parameter [1:0] stateD=2’b11; reg [1:0] state; reg [1:0] nextstate; reg [1:0] out; always @ (posedge clock) begin if (reset ==1,0’b0) state <= stateA; else state <= nextstate; end
always @ (state) begin case (state) stateA: begin nextstate = stateB; end stateB: begin nextstate = stateC; end stateC: begin nextstate = stateD; end stateD: begin nextstate = stateA; end endcase end always@(postdge clock or negedge reset) begin if (reset==1’b0) out <= 2’b0; else begin if (state==…) out <= …; else out <= …; end end endmodule 7. 统一格式的always程序块的书写
A. always 中的变量的赋值方式――阻塞与非阻塞赋值
当进行时序逻辑建模时,always块中使用非阻塞赋值――NON_BLOCKING; 参加如下代码: always @(posedge clk or negedge rst_n) begin if (rst_n == 1’b0; myreg <= 1’b0; else myreg <= ‘DLY1’b1; end always块中使用的NON_BLOCKING赋值时在”<=”前要加上#‘DLY,如上例; 当使用always语句进行组合逻辑建模时,always块中使用阻塞赋值――BLOCKING; 参见如下代码:
always @(addr)
begin case (addr)
2’b00 : cs0_n=1’b0; 2’b01 : cs0_n=1’b1; 2’b10 : cs0_n=1’b0; 2’b11 : cs0_n=1’b1; default: cs0_n=1’b1; endcase end ·
如果要使用always语句同时进行时序与组合逻辑建模时,一定使用非阻塞赋值;例如: //组合逻辑与时序逻辑在同一个always块中
always@(posedge clk or negedge reset_n)
begin if(reset_n==1’b0) out<=1’b0; else begin case(count) 2’b00 : out<= `DLY in_a; 2’b01 : out<= `DLY in_b; 2’b10 : out<= `DLY in_c; 2’b11 : out<= `DLY in_c; default: out<= `DLY in_a; end end B.always中变量赋值的唯一性 · 组合always块一定要注意敏感量列表中的触发项完整且不冗余;如果不是这样,综合的电路会与实际设计不符合,会报warning; · 不要再多个always模块中对同一个reg型变量进行赋值; · 更不能再同一个always中随一个变量双重赋值; 例如:
always@(posedge clk or posedge reset_n)
begin if(reset_n==1’b0) out<=1’b0; else out<= `DLY1’b1; //out 1 0 out<= `DLY1’b0; end · 推荐不要在一个always块里给多个变量赋值。如果将一组条件相同的变量写在一个always块中更有利于可读性的提高和功能的实现时候,可有例外情况,但请尽量多加注释,以增加可读性,并注意在组合always块中不要出现LATCH(不如对状态机的组合always块及它对条件相似的多个变量赋值); C.always中复位的书写
复位的条件表达式及命名要和always敏感列表中的描述相统一,并且一定要使用异步复位。所有的复位必须低有效。
例如:
//
always@(posedge clk ot negedge rst_n) // begin if(rst_n==1’b0) … else … end D.always的注释
要在每一个always块之前加一段注释,增加可读性和便于调试。
//cm carry count which …
always@(posedge clk_xc or negedge rst_n) begin if(rst_n==1’b0) cm_carry_cnt<=1’b0; else cm_carry_cnt<=#`DLY1’b1; end 8.合理的注释
· 代码中应采用英文作详细的注释,注释量应达到代码总量的50%以上。
· 指示应该与代码一致,修改程序的时候一定要修改相应的注释;
· 注释不应重复代码已经表明的内容,而是简介的点明程序的突出特征;
· 注释应该整个一个程序的线索和关键词,它连接整个程序中分散的信息并它帮助理解程序中不能表明的部分。
9.重用化设计
层次结构与模块划分
· 层次设计的原理以简单为主――尽量避免不必要的层次;层次结构设计得好,在综合中就不需要太多的优化过程;
· 模块的划分根据层次设计来决定――模块化对于布线有很大帮助,模块化的设计中要尽量减少全局信号的使用;
· 通用的部分尽量提取出来作为一个共用模块,同时为了适应需求的更改也应提供用户定制模块入库的方式。
参数传递
· 需要传递参数的模块,在多次例化的时候统一都传递参数,不要例化同一个模块,有的传参数,有的不传。
模块划分的技巧: 将不同的时钟域分离开来; 按照不同的设计目标划分成块,分块式应在数据流方向上切分; 在同一模块中实现逻辑资源和算术资源的共享。 二.关于REVIEW
1.Review目的
发现缺陷 降低成本 提高质量
2.流程
[size=10.5000pt]1. 完成第一个字模块时,请提交该模块代码,进行规范检查评审。 [size=10.5000pt]2. Coding 期间 每两星期 提交依次代码和review报告。
Review报告主要包括内容:
· Review工作时,review的代码模块
· 参与人
· 发现的缺陷和解决情况。
Review建议: [size=10.5000pt](1) 制定review计划;(2) 每次review代码不超过500行。
ANNEX
CODE STYLE TEMPLATE
This a template of verilog code file, including file header and the main body of code in which some coding rules are demonstrated.
//******************************************************** // // Copyright(c)2005, Hisilicon Technologies Co., Ltd // All rights reserved // // IP LIB INDEX : IP lib index just as UTOPIA_B // IP Name : the top module_name of this ip, usually, is same as the small ip classified name just as UTOPIA // File name : file_name of this file just as tx_fifo.v // Module name : module_name of this file just as TX_FIFO // Full name : complete English name of the abbreviated module_name // Author : Author // Email : Author’s email // Data : 2005/07/20 // Version : current version, just this: v1.0, must same as the CVS version // // Abstract : // // Called by : Father module just as TX_PROC // // Modification history // ---------------------------------------------------------------------------- // Version Data(yyyy/mm/dd) name // Description // // $Log$ // //*************************************************************
//******************* //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(s)
//******************* //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
//********************* endmodule
MACRO DEFINE TEMPLATE //******************************************************** // // Copyright(c)2005, Hisilicon Technologies Co., Ltd // All rights reserved // // IP LIB INDEX : IP lib index just as UTOPIA_B // IP Name : the top module_name of this ip, usually, is same as the small ip classified name just as UTOPIA // File name : macro.v // Module name : // Full name : complete English name of the abbreviated module_name // Author : Author // Email : Author’s email // Data : 2005/07/20 // Version : current version, just this: v1.0, must same as the CVS version // // Abstract : // // Called by : Father module . // // Modification history // ---------------------------------------------------------------------------- // Version Data(yyyy/mm/dd) name // Description // // $Log$ // //*************************************************************
//******************* //DEFINE(s) //******************* `define UDLY 1 //Unit delay, for non_blocking assignments in sequential logic `define DATA_WIDTH 32 //AHB data width `define ADDR_WIDTH 32 //AHB address width
|