介绍
本文档包含所有 HDL 项目必须遵循的编码和文档指南。本文档的目的是建立一组规则,指定 HDL 模块实现的布局、命名约定和一些通用编码实践。外部文档(例如1和2)描述了旨在从 FPGA 设计中获得最大性能的特定 HDL 编码实践,但未包含在本文档中。
规则有两种类型:应该规则和必须规则
- 规则应该是建议性规则。他们建议推荐的做事方式。
- 必须规则是强制性要求。
编码规则旨在应用于使用 VHDL 或 Verilog 编写的 HDL 模块。
当使用外部 IP 时,应保留IP 实行的命名约定,即使它们与本文档中指定的规则不匹配。
编码风格
A、布局
A1:对于缩进,必须使用空格而不是制表符。这使得任何编辑器都可以正确地可视化代码。不要在行尾留下空格。必须使用 以下编辑器设置:制表符大小:2,缩进大小:2
A2 : 运算符周围必须插入一个空格,例如 =、==、&&、||、&、|、^ 等。
例子:
错误:
if((my_signal1==1'b0)&&(my_bus[3:0]==4'd5))
正确的:
if ((my_signal == 1'b0) && (my_bus[3:0] == 4'd5))
A3:always块在@符号之前应该有一个空格。
例子:
错误:
always@(posedge clk) begin ... end
正确的:
always @(posedge clk) begin ... end
A4 :必须始终使用Verilog begin
/end
块,即使只有一条语句。这使得添加代码行变得更加容易并且错误更少。
A5:必须使用缩进级别来显示代码嵌套。可以根据需要使用空行以提高代码可读性,但并非在所有情况下都如此。
例子:
错误:
if (my_signal == 1'b0) begin if (my_bus[3:0]==4'd5) begin statement1; statement2; end statement3; statement4; end else statement5;
正确的:
if (my_signal == 1'b0) begin if (my_bus[3:0] == 4'd5) begin statement1; statement2; end statement3; statement4; end else begin statement5; end
A6:在定义中,必须case
使用缩进级别来偏移封装的语句,但是可以使用或省略空行来最好地显示语句分组(如果确实有必要)。应按正确示例中的方式缩进。end
例子:
错误:
case ( my_bus[3:0] ) 4'b0000 : my_signal1 = TRUE; 4'b0001 : my_signal1 = FALSE; 4'b0010 : begin my_signal1 = TRUE; my_signal2 = FALSE; end 4'b0100 : my_signal2 = FALSE; default : my_signal1 = TRUE; endcase
正确的:
case (my_bus[3:0]) 4'b0000: begin my_signal1 = TRUE; end 4'b0001: begin my_signal1 = FALSE; end 4'b0010: begin my_signal1 = TRUE; my_signal2 = FALSE; end 4'b0100: begin my_signal2 = FALSE; end default: begin my_signal1 = TRUE; end endcase
A7:对齐应该用在声明、赋值、多行语句和行尾注释中。代码必须以表格格式编写。
例子:
错误:
reg[3:0] my_signal1; //description reg[31:0] my_decoded_signal1; //description reg[4:0] my_signal2, my_signal3; //description wire[2:0] my_select; //description
正确的:
reg [ 3:0] my_signal1; //description reg [31:0] my_decoded_signal1; //description reg [ 4:0] my_signal2; //description reg my_signal3; //description wire [ 2:0] my_select; //description
A8:所有布尔语句和复杂方程中都必须使用括号,以强制执行运算顺序并避免混淆。复杂的布尔表达式应表示为多行对齐语句。
例子:
错误:
if ((my_signal1 && your_signal1) || (my_signal2 && your_signal2) || (my_signal3 && your_signal3)) begin my_signal1 = TRUE; my_delayed_signal1 = !your_signal; end
正确的:
if ((my_signal1 && your_signal1) || (my_signal2 && your_signal2) || (my_signal3 && your_signal3)) begin my_signal1 = TRUE; my_delayed_signal1 = !your_signal; end
A9:一行不得包含多个语句。不要在同一行上连接多个语句。
例子:
错误:
upper_en = (p5type && xadr1[0]); lower_en = (p5type && !xadr1[0]);
正确的:
upper_en = (p5type && xadr1[0]); lower_en = (p5type && !xadr1[0]);
A10:在模块实例中:
A10.1:所有参数和端口都必须写在单独的行上,即使它们的数量很少或者名称很短。
例子:
错误:
my_module #(.PARAMETER1 (PARAMETER1)) i_my_module (.clk (clk));
正确的:
my_module #( .PARAMETER1 (PARAMETER1) ) i_my_module ( .clk (clk));
A10.2:实例化模块时,模块实例的标签必须位于单独的行上,带有参数列表的右括号(如果是这种情况)和端口列表的左括号。端口列表的右括号必须紧邻最后一个端口的最后一个括号。
例子:
my_module #( .PARAMETER1 (PARAMETER1), .PARAMETER2 (PARAMETER2) ) i_my_module ( .clk (clk), .rst (rst), .data_in (data_in), .en (en), .response_out (response_out));
A10.3:代码的注释部分不得添加到主分支(即 if、case、模块实例等)。
A11:在模块声明中:
A11.1:Verilog 模块必须使用 Verilog-2001 风格的参数声明。这提高了易读性和一致性。
例子:
module my_module #( parameter PARAMETER1 = 0 ) ( input clk, input rst, input [7:0] data_0, input [7:0] data_1, input enable, input valid, // interface 1 input interf1_clk, inout interf1_some_signal, output [15:0] interf1_data_i, output [15:0] interf1_data_q, // interface 2 input interf2_some_signal, output interf2_data_out );
A11.2:模块声明内允许注释,仅用于通过指定名称和提供补充说明来分隔接口。
A11.3:声明模块时,参数列表的右括号 必须与最后一个参数以及端口列表的左括号在同一行(如正确示例所示)。
A11.4:后面只能endmodule
有一个换行符,后面不能有其他内容。
A12:端口必须单独注明;也就是说,每行必须声明一个端口,并使用每个端口的方向指示和数据类型。
A13:信号和变量必须单独声明;也就是说,每行必须声明一个信号/变量。
A14:所有端口和信号必须按接口分组。按方向对端口声明进行分组,从输入、输入输出和输出端口开始。
A15 :必须首先声明时钟和复位端口。
A16:Verilog 连线和寄存器声明必须分组在单独的部分中。首先注册类型,然后注册电线类型。
A17 : Verilog 代码的源文件应具有附件 1 所示的格式,VHDL 代码的源文件应具有附件 2 所示的格式。
B. 命名约定
B1:源代码中的所有名称必须用英文书写。
B2:名称必须以字母开头,由字母数字字符或下划线组成[AZ, az, 0-9,_]。
B3:所有模块、信号和寄存器名称必须小写,并用下划线“_”分隔。
例子:
module my_module ( input ena_fft, input ena_mdi, input fft_in, output mdi_out, output [15:0] my_signal1 );
B4:一个文件必须包含单个模块。文件名必须与模块名相同。对于子模块,名称必须按以下方式组成:
<top_module_name>_<sub_module_description>.
B5:所有参数名称必须大写并带有下划线分隔符。
B6 : 信号名称应按以下方式组成:
[interface|clock domain]_<signal_name>[_ns][_l][_p][_n][_m1][_m2][_s]
后缀组件可以如下所述使用,并且在同一信号名称中使用多个后缀的情况下,必须仅按照上述信号名称描述中指定的顺序使用。
_ns – 状态机的下一个状态。
_l – 锁存器输出。对于离开顶层模块或子模块的信号是可选的,对于模块内部的信号是必需的
_p – 差分信号的正极。
_n – 差分信号的负端。 – 低电平有效信号。也可用于差分信号的负端。
_m1/_m2 – 用于描述寄存器同步器(例如 up_ack_m1、up_ack_m2)
_s – 用于限定电线/信号(例如 up_ack_s)
此规则对于复杂模块很有用,如果信号名称不包含用于指定其用途的后缀,则可能会错误地使用信号。一般来说,此规则可能会导致不必要的命名复杂性,因此可以忽略,除非绝对必要。
B7:端口名称应按以下方式组成:
<interface_name>_<port_name>[_clk][_rst][_p][_n]
_clk – 时钟信号。例外:名称明显指示时钟的信号(例如system_clock或clk32m),或者指定具有特定频率的时钟时(在这种情况下应使用clk作为前缀:例如clk_625mhz)
_rst / _rstn – 复位信号(例如 module_rst)。例外:其名称明显表明复位的信号。
_p – 差分信号的正极。
_n – 低电平有效信号。也可用于差分信号的负端。
B8‘define
:指令指定的全局文本宏必须以顶级模块名称开头,如下所示:
<top_level_module_name>_<text macro name>
B9 :整个设计中必须使用一致的网络和变量的拼写和命名风格。
B10:模块中使用的缩写必须记录在案,并且应避免不常见的缩写。
B11:复位和时钟名称在整个层次结构中必须保持相同。
三、评论
C1:必须使用注释来描述 HDL 代码的功能。强烈鼓励自由使用评论。不鼓励添加明显的注释。基本上,对代码块进行的大量注释加上稀疏的反向引用可以引导读者浏览代码。
C2:代码的每个功能部分之前都应该有描述代码的意图和功能的注释。
C3 :必须解释不寻常或不明显的实现,并用注释记录它们的局限性。
C4:每个端口声明应该有一个描述性注释,仅在前一行。
C5:其他声明,例如regs、wires、局部参数,应该有描述性注释。要么在同一行(不鼓励),要么在前一行。对于自动生成的代码,此规则是可选的。
C6:所有综合特定指令必须在使用位置进行记录,标识使用它们的原因、所使用的工具和指令。
C7:代码中插入的注释必须符合附件 1(Verilog 代码)和附件 2(VHDL 代码)所示的格式。
D. 总则
D1:文件必须包含单个模块。
D2:文件必须包含:纯数字 Verilog 代码(扩展名为 .v 的文件);仅模拟的 Verilog 代码(扩展名为 .va 或 .vams 的文件);或混合信号 Verilog 代码(扩展名为 .vams 的文件)。
D3:符号常量(局部参数)应用于寄存器字段值,而不是固定的数字常量。这些字段可以是一位或多位或整个寄存器。
D4:端口连接宽度必须匹配。在模块实例化中,连接到端口的网络必须具有与相应端口声明相同的宽度。
D5:向量端口声明和网络/变量声明中的范围必须相等。
D6:操作数大小必须匹配。任何表达式的大小都不能隐式扩展或减小。在case
语句中,所有case
项表达式和case
表达式必须具有相同的大小。
D7 :必须完整指定组合逻辑(即必须为所有输入组合的逻辑输出分配一个值)。在从case
or语句派生的构造中,可以在or语句if
之前为输出分配默认值,然后完全指定逻辑。case
if
D8 :必须完整指定Verilogalways
和 VHDLprocess
结构 的敏感度列表。
D9:模块必须使用完整的 I/O 进行实例化 – 所有端口名称和信号连接必须在所有模块实例中列出。不要将任何输入端口保持打开状态(即使它们未使用),始终将它们连接到 0 或 1。将未使用的输出保持打开状态,但将其列出。
D10: Verilog 模块中应使用timescale
最适合仿真的指令。
D11:编译警告必须被视为潜在错误,并且应 始终尝试解决。如果警告未得到解决,则必须充分了解其原因和影响。
D12 :必须处理和修复严重警告。
D13:每个文件必须包含许可证头,当对文件进行更改时,在制作 PR 时,年份应更新为当前年份。
3. 附件
附件1 Verilog文件格式
// *************************************************************************** // *************************************************************************** // Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. // // In this HDL repository, there are many different and unique modules, consisting // of various HDL (Verilog or VHDL) components. The individual modules are // developed independently, and may be accompanied by separate and unique license // terms. // // The user should read each of these license terms, and understand the // freedoms and responsibilities that he or she has by using this source/core. // // This core is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR // A PARTICULAR PURPOSE. // // Redistribution and use of source or resulting binaries, with or without modification // of this file, are permitted under one of the following two license terms: // // 1. The GNU General Public License version 2 as published by the // Free Software Foundation, which can be found in the top level directory // of this repository (LICENSE_GPL2), and also online at: // <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html> // // OR // // 2. An ADI specific BSD license, which can be found in the top level directory // of this repository (LICENSE_ADIBSD), and also on-line at: // https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD // This will allow to generate bit files and not release the source code, // as long as it attaches to an ADI device. // // *************************************************************************** // *************************************************************************** 'timescale 1ns/100ps module prescaler #( //Range = 1-16 parameter FIRST_PARAMETER = 8, //Range = N/A parameter SECOND_PARAMETER = 12 ) ( input core_32m_clk, // 32 MHz clock input system_clk, // system clock input scan_mode_test, // scan mode clock input reset_n, // active low hard reset, synch w/ // system_clk output reg div16_clk, // input clock divided by 16 output reg div16_clk_n // input clock divided by 16 and inverted ); // Local Parameters // Registers Declarations reg [3:0] count; // 4-bit counter to make clock divider reg [3:0] count1; // 4-bit counter to make clock divider // Wires Declarations wire [3:0] count1_ns; // clock divider next state input // Functions Definitions // This block updates the internal counter always @(posedge core_32m_clk or negedge reset_n) begin if (!reset_n) begin count <= 4’b0000; end else begin // update counter count <= count + 4’b0001; end end // This block updates the output clock signals always @(scan_mode_test or system_clk or count) begin if (!scan_mode_test) begin // normal operation clock assign div16_clk = count[3]; div16_clk_n = ~count[3]; end else begin // scan mode clock assign div16_clk = system_clk; div16_clk_n = system_clk; end end // Modules Instantiations endmodule
附件2 VHDL文件格式
-- *************************************************************************** -- *************************************************************************** -- Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. -- -- In this HDL repository, there are many different and unique modules, consisting -- of various HDL (Verilog or VHDL) components. The individual modules are -- developed independently, and may be accompanied by separate and unique license -- terms. -- -- The user should read each of these license terms, and understand the -- freedoms and responsibilities that he or she has by using this source/core. -- -- This core is distributed in the hope that it will be useful, but WITHOUT ANY -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -- A PARTICULAR PURPOSE. -- -- Redistribution and use of source or resulting binaries, with or without modification -- of this file, are permitted under one of the following two license terms: -- -- 1. The GNU General Public License version 2 as published by the -- Free Software Foundation, which can be found in the top level directory -- of this repository (LICENSE_GPL2), and also online at: -- <https://www.gnu.org/licenses/old-licenses/gpl-2.0.html> -- -- OR -- -- 2. An ADI specific BSD license, which can be found in the top level directory -- of this repository (LICENSE_ADIBSD), and also on-line at: -- https://github.com/analogdevicesinc/hdl/blob/master/LICENSE_ADIBSD -- This will allow to generate bit files and not release the source code, -- as long as it attaches to an ADI device. -- -- *************************************************************************** -- *************************************************************************** entity prescaler is Port ( core_32m_clk : in std_logic, -- 32 MHz clock system_clk : in std_logic, -- system clock scan_mode_test : in std_logic, -- scan mode clock reset_n : in std_logic, -- active low hard reset, synch -- w/ system_clock div16_clk : out std_logic, -- input clock divided by 16 div16_clk_n : out std_logic -- input clock divided by 16 -- and inverted ); end prescaler; architecture Behavioral of prescaler is -- Components Declarations -- Local Types Declarations -- Constants Declarations -- Signals Declarations signal count : std_logic_vector(3 downto 0); -- 4-bit counter to -- make clock divider signal count_ns : std_logic_vector(3 downto 0); -- clock divider next -- state input -- Module Implementation begin -- This process updates the internal counter process(core_32m_clk) begin if (rising_edge(core_32m_clk)) then if (reset_n = '0') then -- reset counter count <= "0000"; else -- update counter count <= count + "0001"; end if; end if; end process; -- This process updates the output clock signals process(scan_mode_test, system_clk, count) begin if (scan_mode_test = '0') then -- normal operation clock assign div16_clk <= count(3); div16_clk_n <= not count(3); else -- scan mode clock assign div16_clk <= system_clk; div16_clk_n <= system_clk; end if; end process; end Behavioral;
4. 参考文献
1 Philippe Garrault、Brian Philofsky,“加速设计性能的 HDL 编码实践”,Xilinx,2006 年,在线文档可访问: http://www.xilinx.com/support/documentation/white_papers/wp231.pdf
2 Peter Chambers,“优秀设计的十诫”,VLSI Technology,1997 年,在线文档可访问:
http://www.asic-world.com/code/verilog_tutorial/peter_chambers_10_commandments.pdf
[ 3] “Verilog 编码技术,v3.2”,飞思卡尔半导体,2005 年,在线文档可访问: http://courses.cit.cornell.edu/ece576/Verilog/FreescaleVerilog.pdf
[ 4] Jane Smith,“Verilog 编码指南,Rev. B”,Cisco Systems,2000 年,在线文档可访问:http://www.engr.sjsu.edu/cpham/VERILOG/VerilogCodingStyle.pd
致谢: 以上规范文档来自ADI官网
发表回复