差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
硬禾实战营verilog代码规范 [2016/08/03 16:37]
zhijun
硬禾实战营verilog代码规范 [2021/09/15 14:54] (当前版本)
gongyu
行 1: 行 1:
 +[[stepfpga_code_spec]]
 +### 1.RTL CODE 规范
  
-====1.RTL CODE 规范==== 
 ------ ------
 +
 ===1.1标准的文件头=== ===1.1标准的文件头===
 +
 ------ ------
 在每一个版块的开头一定要使用统一的文件头,其中包括作者名,模块名,创建日期,概要,更改记录,版权等必要信息。 在每一个版块的开头一定要使用统一的文件头,其中包括作者名,模块名,创建日期,概要,更改记录,版权等必要信息。
 统一使用以下的文件头:其中*为必需的项目 统一使用以下的文件头:其中*为必需的项目
 +
 <code verilog> <code verilog>
 //​******************************************************** //​********************************************************
行 14: 行 18:
 //   File name       : ​  ​MODULE_NAME.v //   File name       : ​  ​MODULE_NAME.v
 //   ​Module name     : ​  ​MODULE_NAME //   ​Module name     : ​  ​MODULE_NAME
-//   ​Author ​         :   tony-ning+//   ​Author ​         :   STEP
 //   ​Description ​    ​:  ​ //   ​Description ​    ​:  ​
 //   ​Email ​          : ​  ​Author’s email //   ​Email ​          : ​  ​Author’s email
行 24: 行 28:
 //   ​Modification history //   ​Modification history
 //   ​---------------------------------------------------------------------------- //   ​----------------------------------------------------------------------------
-//   ​Version ​        : +// Version ​      ​Data(2016/08/01)   V1.0 
-//   Data(yyyy/mm/dd)   +// Description
-//   Name            : +
-//   Description ​    :+
 // //
 //​************************************************************* //​*************************************************************
 </​code>​ </​code>​
  
-===1.2 标准的module格式 ===(module 整体结构)+===1.2标准的module格式=== 
 ------ ------
 +
 对于模块的书写采用统一的格式便于项目内部成员的理解和维护,我们用批处理建立了一个MODULE模块,其内容解释如下: 对于模块的书写采用统一的格式便于项目内部成员的理解和维护,我们用批处理建立了一个MODULE模块,其内容解释如下:
 \\ 端口定义按照输入,输出,双向的顺序: \\ 端口定义按照输入,输出,双向的顺序:
行 41: 行 45:
 \\ 例化名 :U_XXX ​ (大写) \\ 例化名 :U_XXX ​ (大写)
 \\ IP 内部所有的模块名都要加IP名或者IP名简称作前缀,如USB_CTRL、USB_TX_FIFO。 \\ IP 内部所有的模块名都要加IP名或者IP名简称作前缀,如USB_CTRL、USB_TX_FIFO。
 +
 <code verilog> <code verilog>
 // ***************************** // *****************************
行 66: 行 71:
  // DEFINE INPUT  // DEFINE INPUT
  // ******************************  // ******************************
- input rst_n ​  ; ​   // reset, (active low) . //​input到寄存器名之间四个tab键,注意对齐 + input rst_n ​  ; ​   // reset, (active low) . //​input到寄存器名之间四个tab键,注意对齐 
- input clk_* ​  ; ​   // clock signal , 50M . //​注意注释的格式,简洁有力,尽量使用英文 + input clk_* ​  ; ​   // clock signal , 50M . //​注意注释的格式,简洁有力,尽量使用英文 
- input ​ [n:0] a_din   ; ​   // ***** //​此处是在模块名部分没有声明端口类型时用 + input ​ [n:0]         ​a_din   ; ​   // ***** //​此处是在模块名部分没有声明端口类型时用 
- input ​ [k:0] b_din   ; ​   // ***** //​注释尽量不要挨到前面,然后全左对齐+ input ​ [k:0]         ​b_din   ; ​   // ***** //​注释尽量不要挨到前面,然后全左对齐
  
  // ******************************  // ******************************
- // DEFINE OUTPUT  ​//+ // DEFINE OUTPUT  ​
  // ******************************  // ******************************
- output ​ [m:0]    a_dout ​  ; ​   // ***** //​位宽定义和output之间加一个tab或空格,统一即可+ output ​ [m:0]    a_dout ​  ; ​   // ***** //​位宽定义和output之间加一个tab或空格,统一即可
  output ​ [i:0]    b_dout ​  ; ​   // *****  output ​ [i:0]    b_dout ​  ; ​   // *****
  
  // ******************************  // ******************************
- // OUTPUT ATRRIBUTE  ​//+ // OUTPUT ATRRIBUTE  ​
  // ******************************  // ******************************
  // REGS  // REGS
行 87: 行 92:
  
  // ******************************  // ******************************
- // INSTSNCE MODULE ​  //+ // INSTSNCE MODULE ​  
  // ******************************  // ******************************
  MODULE_NAME_A ​ U_MODULE_NAME_A( //​例化名从和模块名相距四个tab,括号后换行  MODULE_NAME_A ​ U_MODULE_NAME_A( //​例化名从和模块名相距四个tab,括号后换行
行 96: 行 101:
  
  // ******************************  // ******************************
- //MAIN CODE  ​//+ //MAIN CODE  ​
  // ******************************  // ******************************
  … …  … …
行 105: 行 110:
 </​code>​ </​code>​
  
-3.一致的排版 +===1.3一致的排版=== 
-A. 一致的缩排+ 
 +------ 
 + 
 +\\ A. 一致的缩排 
 + 
 +<code verilog>
  //​统一的缩排取4个空格宽度  //​统一的缩排取4个空格宽度
  //​输入输出信号的宽度定义与关键字之间,信号名与宽度之间要用tab分开;所有宽度定义对所有信号名对齐,代码风格统一如下:  //​输入输出信号的宽度定义与关键字之间,信号名与宽度之间要用tab分开;所有宽度定义对所有信号名对齐,代码风格统一如下:
     ​     ​
- input   ​[3:​0] ​  ​ input_a ​ ;    // ***** +    ​input   ​[3:​0] ​  ​ input_a ​ ;    // ***** 
-    input input_b ​ ;    // *****+    input input_b ​ ;    // *****
        …        …
-    output ​ [128:0] output_a ; +    output ​ [128:0] output_a ; 
- output ​ [15:​0] ​ output_b ; +    output ​ [15:​0] ​ output_b ; 
- output output_c ;+    output output_c ; 
 +</​code>​
   
-B.一致的 begin end 书写方式+\\ B.一致的 begin end 书写方式
  
 +<code verilog>
  //always 中,一定要用begin end 区分,格式和代码风格统一如下:  //always 中,一定要用begin end 区分,格式和代码风格统一如下:
  always @ (postedge clk or negedge rst_n)  always @ (postedge clk or negedge rst_n)
行 132: 行 144:
  end  end
  end  end
- //if else 中仅有一个语句行时,不要使用begin end; 如果有多个语句行时,begin end和if ()或else ()空四个格。 + //if else 中仅有一个语句行时,不要使用begin end; 如果有多个语句行时,begin end和if ()或else ()空四个格。 格式如下:
- 格式如下:+
  if  (…)  if  (…)
  
行 148: 行 159:
      end      end
  else  else
-  + </code>
-4. 一致的信号命名风格 +
-//​简洁,清晰,有效是基本的信号命名规则,详见命名规范。+
  
 +===1.4 一致的信号命名风格===
  
- 全称 缩写 中文含义 +------ 
- acknowledge ack 应答 + 
- adress addr(ad) 地址 +简洁,清晰,有效是基本的信号命名规则,详见命名规范。 
- arbiter arb 仲裁 +^全称 ^缩写         ^中文含义^ 
- check chk 校验,如CRC校验 +|acknowledge |ack |应答| 
- clock clk 时钟 +|adress |addr(ad)         |地址| 
- config cfg Configuration,​装置 +|arbiter |arb |仲裁| 
- control ctrl 控制 +|check |chk |校验,如CRC校验| 
- count cnt 计数 +|clock |clk |时钟| 
- data in din(di) 数据输入 +|config |cfg |Configuration,​装置| 
- data out dout(do) 数据输出 +|control |ctrl |控制| 
- decode de 译码 +|count |cnt |计数| 
- decrease dec 减一 +|data in |din(di) |数据输入| 
- delay dly  +|data out |dout(do) |数据输出| 
- disable dis 不使能 +|decode |de |译码| 
- error err 错误(指示) +|decrease |dec |减一| 
- enable en 使能 +|delay |dly | 
- frame frm 帧 +|disable |dis |不使能| 
- generate gen 生成,如CRC生成 +|error |err |错误(指示)| 
- grant gnt 申请通过 +|enable |en |使能| 
- increase inc 加一 +|frame |frm || 
- input in(i)  +|generate |gen |生成,如CRC生成| 
- length len (帧、包)长 +|grant |gnt |申请通过| 
- nmport nm 网管相关 +|increase |inc |加一| 
- output out(o)  +|input |in(i) | 
- packet不推荐packet pkt 与帧相同 +|length |len |(帧、包)长| 
- priority pri 优先级 +|nmport |nm |网管相关| 
- pointer ptr 指针 +|output |out(o) | 
- rd enable ren 读使能 +|packet不推荐packet |pkt |与帧相同| 
- read rd 读(操作) +|priority |pri |优先级| 
- ready rdy 应答信号或准备好 +|pointer |ptr |指针| 
- receive rx (帧数据)接收 +|rd enable |ren |读使能| 
- request req (服务、仲裁)请求 +|read |rd |读(操作)| 
- reset rst  +|ready |rdy |应答信号或准备好| 
- segment seg  +|receive |rx |(帧数据)接收| 
- souce scr 源(端口) +|request |req |(服务、仲裁)请求| 
- ststistics stat 统计 +|reset |rst | 
- timer tmr 定时器 +|segment |seg | 
- switcher sf Switch fabric +|souce |scr |源(端口)| 
- temporary tmp 临时 +|ststistics |stat |统计| 
- transmit tx 发送(帧数据)相关 +|timer |tmr |定时器| 
- Valid vld(v) 有效、校验正确 +|switcher |sf |Switch fabric| 
- wr enable wen 写使能 +|temporary |tmp |临时| 
- write wr 写操作+|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.模板示例==== 
 + 
 +------ 
 + 
 +<code verilog>​ 
 +//​******************************************************** 
 +// 
 +//   ​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
   
- a.端口、信号、变量名的所有字母小写:函数名、宏定义、参数定义用大写 + assign out = expression ? (1’b0):​(1’b1)
- b.使用简称、缩略词(加上列表) + 
- c.基于含义命名(避免以数字命名的简单做法),含义可分段(最多分三段),每一小段之间加下划线”_”,​如tx_data_val;命名长度一般限制在20个字符以内。 + //​********************* 
- d.低电平有效信号,加后缀”_n”,​如 rst_n +endmodule
- e.无条件寄存的寄存信号在原信号上加ff1、ff2… 如原信号 data_in, 寄存一拍data_in_ff1,​寄存两拍data_in_ff2 +
- f.不能用 ”reg”,​作为最后的后缀名,因为综合工具会给寄存器自动加上_reg,​ 如果命名里就用_reg作为后缀名则扰乱了网表的可读性。+
  
-                 + </​code> ​