碎碎思 · 2022年05月13日

数字硬件建模SystemVerilog(八)-端口声明

端口声明

模块定义包括一个端口列表,该列表用括号括起来。端口用于将数据传入或传出模块。模块可以有四种类型的端口:输入、输出、双向输入输出和接口(input,output, bidirectional inout,和 interface)。输入、输出和输入输出端口是离散端口,其中每个端口通信一个值或用户定义的类型。接口端口是复合端口,可以通信多个值的集合。本文介绍离散端口的语法和使用指南。后续将介绍接口端口。

可综合端口声明

端口声明定义端口的方向、类型、数据类型、符号、大小和名称(direction, type, data type, sign, size 和 name)。

  • 端口方向用关键字input、output或inout声明,
  • port类型和数据类型可以是变量,也可以是之前介绍的任何网络类型和数据类型。
  • 端口标志可以是有符号的,也可以是无符号的。
  • 端口大小的范围从1位宽到2^16(65536)位宽。在实践中,工程师必须考虑FPGA技术将用于实现设计的尺寸限制。

端口在模块端口列表中声明,该列表用简单的括号括起来。端口可以按任何顺序列出。一些工程师喜欢先列出输入,然后列出输出。其他工程师更喜欢先列出输出,然后列出输入。一些公司对端口的顺序有严格的编码风格规则,而其他公司则将顺序留给编写模块定义的工程师。对于缩进的使用,工程师们在编码风格上也有很大的不同,是否在同一行或单独的行上列出多个端口,这些都没有统一的标准。

SystemVerilog提供用于声明端口列表和端口声明的编码样式:组合样式、传统样式和具有组合类型和大小的传统样式(combined-style, legacy-style and legacy-style with combined type and size)。

组合样式端口列表,组合样式端口列表将每个端口的完整声明放在端口列表括号内。大多数工程师都喜欢这种风格。

2e85734912beb9838471fe3c08a7dcdc.png

请注意,每个端口声明都用逗号分隔,并且列表中的最后一个端口在右括号前没有逗号

可以使用以逗号分隔的端口名列表声明具有相同方向、类型、数据类型和大小的多个端口。通过组合相似端口的声明,前面的端口列表可以简化为:

eadf93a42fbcc1aaeb7760c2bd5c6f2f.png

IEEE SystemVerilog标准将端口声明的组合样式定义为ANSI样式的端口列表,因为该样式类似于函数声明的ANSI C样式。这种类型的端口声明作为Verilog2001标准的一部分添加到Verilog中。

传统样式端口列表。最初的Verilog-1995标准将端口列表和每个端口的类型、数据类型、符号和大小声明分开。SystemVerilog标准将此分离样式称为非ANSI样式端口列表。此样式类似于原始的、ANSI C之前的函数声明样式。下面的示例使用Verilog-2001数据类型。SystemVeriIog逻辑类型也可用于传统Verilog样式的端口列表:

706a83f50959e988140d7a8ab28bcee9.png

请注意,每个端口声明都以分号结尾,但可以对具有相同方向和大小,或相同类型、数据类型和大小(例如端口a和b,或前面端口声明中的overflow和error)的端口使用逗号分隔的端口名列表。

如果端口列表中的第一个端口上的端口方向、类型、数据类型、符号和大小都被省略,则整个端口列表将采用传统的非ANSI样式的端口列表。端口列表中的所有端口必须是组合的ANSI样式或传统的ANSI样式。在同一端口列表中混合使用这两种样式是非法的。

具有组合方向和大小的传统样式端口列表。Verilog-2001标准允许传统样式的端口列表将方向声明和类型/数据类型声明组合到单个语句中。

a3505822f39c106c5ec74f797353b5bd.png

模块端口默认值。每个端口的方向、类型、数据类型、有无符号和大小都有隐式默认值。端口类型可以是网络(如wire)或变量(如var)。端口数据类型可以是logic(4态)或bit(2态)。端口方向、类型、数据类型、有无符号和大小的默认规则为:

  • 未指定方向-模块端口的默认方向为inout,但仅在定义方向之前,一旦指定方向,该方向将应用于所有后续端口,直到指定新方向。
  • 未指定类型No type specified-未指定数据类型(如逻辑)时,默认类型端口为wire,指定数据类型时,默认类型为wire(输入和输入输出端口)和var(输出端口),并且可以使用'default_nettype编译器指令更改wire。
  • 未指定数据类型No data type specified-所有端口的默认数据类型为logic(4态)。
  • 未指定有无符号No signedness specified-默认有无符号是端口数据类型的默认有无符号,reg、logic、bit和time数据类型默认为unsigned。byte、shortint、int、integer和longint数据类型默认为signed。
  • 未指定大小No size specified-默认大小是端口数据类型的默认大小。该条例;逻辑和位数据类型默认为1位宽。

下面的代码片段不是真实的RTL编码样式,但用于说明模块端口声明的隐式默认值。

09cd11da43b28d2ca8b3ad6fbd6b2433.png

尽管前面代码段中的端口声明是可综合的,但对于可综合的RTL模型,不建议使用这种编码样式。

继承的端口声明。端口的方向、类型、数据类型、有无符号或大小的显式声明可以由端口列表中的后续端口继承。继承的端口特征是“粘滞的”,因为特征会一直粘滞(保持有效),直到发生更改。

端口声明继承规则包括:

  • 继承的端口方向-显式端口方向声明在指定新方向之前保持有效,即使端口类型发生更改。
  • 继承的端口类型-在指定新的方向或类型之前,显式端口类型声明保持有效。
  • 继承的端口数据类型-在指定新的方向、类型或数据类型之前,显式端口数据类型声明保持有效。
  • 继承的端口有无符号-显式端口有无符号声明在指定新的方向或类型或数据类型或大小之前保持有效,
  • 继承的端口大小-在指定新的方向或类型或数据类型或大小之前,显式端口大小声明保持有效。

下面代码段不是推荐的RTL编码样式,但说明了后续端口如何从模块端口列表中先前的端口声明继承特征。

af9639ce933d81191a11cbb21eadf7d6.png

不可综合的端口声明

SystemVerilog具有几种主要综合编译器不普遍支持的其他端口类型和声明功能,包括:

  • 模块ref参考端口
  • 模块互连端口
  • 输入端口默认值(如input logic [7:0] a=0)
  • 输出端口默认值(如output logic [7:0] y=l
  • 端口表达式(例如.b({c,d}))
  • 具有隐式端口的外部模块和嵌套模块

一些综合编译器可能支持其中一些构造,但本文中没有讨论它们,因为在本文编写时,并非所有主要综合编译器都支持它们。这些构造对于验证非常有用,并且超出了本文关于RTL建模的范围。

模块端口声明建议

SystemVerilog为声明模块端口提供了相当大的能力和灵活性,如本节所示。工程师应对端口声明采用一致的编码风格,以确保模型能够自我记录,更易于维护,并且更易于在未来项目中重复使用。

最佳做法准则3-9

1652409634(1).png

声明模块端口的一些最佳实践编码建议包括:

  • 使用组合的ANSI-C样式端口列表,以便所有端口信息都包含在端口列表中。
  • 声明每个端口的方向,而不是依赖默认端口方向和继承的(粘性)端口方向。
  • 将所有端口数据类型声明为logic数据类型。避免RTL模型中的2态数据类型-它们可能隐藏设计错误。
  • 不要声明端口类型,允许语言推断wire或var类型。输入和输出端口的隐式默认类型适用于可综合的RTL级别模型。例外:三态端口可以选择性地声明为三态类型。tri类型与wire相同,但显式声明有助于记录端口应为三态声明,
  • 在单独的行上声明每个端口。这允许添加注释来描述每个端口的用法或假设,例外情况:可以接受以逗号分隔的端口名称列表,这些端口名称都具有相同的方向、数据类型、大小和类似用法。

示例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几乎在所有情况下都能正确推断出网络或变量。

原文:OpenFPGA
作者:碎碎思

相关文章推荐

更多FPGA技术干货请关注FPGA 的逻辑技术专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
10614
内容数
577
FPGA Logic 二三事
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息