模块定义包括一个端口列表,该列表用括号括起来。端口用于将数据传入或传出模块。模块可以有四种类型的端口:输入、输出、双向输入输出和接口(input,output, bidirectional inout,和 interface)。输入、输出和输入输出端口是离散端口,其中每个端口通信一个值或用户定义的类型。接口端口是复合端口,可以通信多个值的集合。本文介绍离散端口的语法和使用指南。后续将介绍接口端口。
端口声明定义端口的方向、类型、数据类型、符号、大小和名称(direction, type, data type, sign, size 和 name)。
端口在模块端口列表中声明,该列表用简单的括号括起来。端口可以按任何顺序列出。一些工程师喜欢先列出输入,然后列出输出。其他工程师更喜欢先列出输出,然后列出输入。一些公司对端口的顺序有严格的编码风格规则,而其他公司则将顺序留给编写模块定义的工程师。对于缩进的使用,工程师们在编码风格上也有很大的不同,是否在同一行或单独的行上列出多个端口,这些都没有统一的标准。
SystemVerilog提供用于声明端口列表和端口声明的编码样式:组合样式、传统样式和具有组合类型和大小的传统样式(combined-style, legacy-style and legacy-style with combined type and size)。
组合样式端口列表,组合样式端口列表将每个端口的完整声明放在端口列表括号内。大多数工程师都喜欢这种风格。
请注意,每个端口声明都用逗号分隔,并且列表中的最后一个端口在右括号前没有逗号。
可以使用以逗号分隔的端口名列表声明具有相同方向、类型、数据类型和大小的多个端口。通过组合相似端口的声明,前面的端口列表可以简化为:
IEEE SystemVerilog标准将端口声明的组合样式定义为ANSI样式的端口列表,因为该样式类似于函数声明的ANSI C样式。这种类型的端口声明作为Verilog2001标准的一部分添加到Verilog中。
传统样式端口列表。最初的Verilog-1995标准将端口列表和每个端口的类型、数据类型、符号和大小声明分开。SystemVerilog标准将此分离样式称为非ANSI样式端口列表。此样式类似于原始的、ANSI C之前的函数声明样式。下面的示例使用Verilog-2001数据类型。SystemVeriIog逻辑类型也可用于传统Verilog样式的端口列表:
请注意,每个端口声明都以分号结尾,但可以对具有相同方向和大小,或相同类型、数据类型和大小(例如端口a和b,或前面端口声明中的overflow和error)的端口使用逗号分隔的端口名列表。
如果端口列表中的第一个端口上的端口方向、类型、数据类型、符号和大小都被省略,则整个端口列表将采用传统的非ANSI样式的端口列表。端口列表中的所有端口必须是组合的ANSI样式或传统的ANSI样式。在同一端口列表中混合使用这两种样式是非法的。
具有组合方向和大小的传统样式端口列表。Verilog-2001标准允许传统样式的端口列表将方向声明和类型/数据类型声明组合到单个语句中。
模块端口默认值。每个端口的方向、类型、数据类型、有无符号和大小都有隐式默认值。端口类型可以是网络(如wire)或变量(如var)。端口数据类型可以是logic(4态)或bit(2态)。端口方向、类型、数据类型、有无符号和大小的默认规则为:
下面的代码片段不是真实的RTL编码样式,但用于说明模块端口声明的隐式默认值。
尽管前面代码段中的端口声明是可综合的,但对于可综合的RTL模型,不建议使用这种编码样式。
继承的端口声明。端口的方向、类型、数据类型、有无符号或大小的显式声明可以由端口列表中的后续端口继承。继承的端口特征是“粘滞的”,因为特征会一直粘滞(保持有效),直到发生更改。
端口声明继承规则包括:
下面代码段不是推荐的RTL编码样式,但说明了后续端口如何从模块端口列表中先前的端口声明继承特征。
SystemVerilog具有几种主要综合编译器不普遍支持的其他端口类型和声明功能,包括:
一些综合编译器可能支持其中一些构造,但本文中没有讨论它们,因为在本文编写时,并非所有主要综合编译器都支持它们。这些构造对于验证非常有用,并且超出了本文关于RTL建模的范围。
SystemVerilog为声明模块端口提供了相当大的能力和灵活性,如本节所示。工程师应对端口声明采用一致的编码风格,以确保模型能够自我记录,更易于维护,并且更易于在未来项目中重复使用。
最佳做法准则3-9
最佳做法准则3-9 |
---|
对模块端口列表使用ANSI-C样式声明。将输入端口和输出端口声明为logic类型。 |
声明模块端口的一些最佳实践编码建议包括:
示例3-3说明了使用这些编码准则的模块端口列表。
示例3-3:使用推荐编码准则的模块端口声明
`begin_keywords "1800-2012" // use SystemVerilog-2012 keywords
module alu
(input logic signed [31:0] a, b, // ALU operand inputs
input logic [ 3:0] opcode, // ALU operation code
output logic signed [31:0] result, // Operation result
output logic overflow, // Set if result overflowed
output logic error // Set if operation errored
);
timeunit 1ns; timeprecision 100ps;
/////////////////////////////////////////////
// model functionality not shown //
/////////////////////////////////////////////
endmodule: alu
`end_keywords
传统的Verilog考虑因素。在SystemVeriIog之前,传统的Verilog没有logic数据类型,对于隐式默认端口类型有不同的规则。传统的Verilog会为所有端口假定一种端口类型wire,除非该端口被显式声明为reg,这将推断出一个变量。工程师必须小心地使用显式端口声明,以确保每个端口具有模块内功能的正确类型和数据类型。要使所有声明正确,通常需要编译代码、检查编译错误或更糟的情况、容易忽略的警告、修复错误或警告,然后重新编译。对功能建模方式的更改通常会导致新的编译错误,因为还需要更改端口数据类型。
SystemVerilog使端口声明更加容易。只需将所有端口声明为logic数据类型,并让语言正确推断出正确的网络或变量类型。SystemVerilog几乎在所有情况下都能正确推断出网络或变量。