2,Verilog-2005标准篇:verilog规则预览

正如博主小飞的上一篇博文所述,Verilog 是一种硬件描述语言 (HDL),其标准化版本为 IEEE Std 1364™-1995,首次修订版本为 IEEE Std 1364-2001。IEEE Std 1364-2005(即verilog-2005)版本则修订更正并澄清了verilog-1995版和verilog-2001版中描述不明确的功能。它还解决了 IEEE 1364-2001 与 IEEE 1800™-2005 (即SystemVerilog-2005)标准不兼容和不一致的问题。

在接下来学习verilog的博文之前,博主先在本篇对Verilog HDL语法的国际统一格式(BNF:Backus-Naur Form)进行说明。约定如下:

- 小写单词(有些包含下划线)用于表示语法类别,例如:

module_declaration

- 粗体单词用于表示保留关键字、运算符和标点符号,它们是语法的必要组成部分。例如:

module  =>  ;

- 竖条“|”分隔备选类别,但竖条以黑体字出现时,竖条就代表其本身。例如博主小飞后面将要介绍的一元操作符:

unary_operator ::= + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~

- 方括号“[ ]”表示可选项。例如:

input_declaration ::= input [range] list_of_variables

- 花括号“{ }”括起来的内容是重复项,除非它以粗体字出现,在这种情况下,它代表它自己。 重复项可以出现零次或多次;从左到右重复,就像等效的左递归规则一样。因此,以下两条规则是等价的:

list_of_param_assignments ::= param_assignment { , param_assignment }

list_of_param_assignments ::= param_assignment

                              | list_of_param_assignment ,param_assignment

- 如果任何类别的名称以斜体部分开头,则等同于没有斜体部分的类别名称。斜体部分旨在传达一些语义信息。例如,"msb_index "和 "lsb_index "等同于 "index"。

另外,我们写Verilog代码时,在Verilog HDL 源文件中所能出现的字符类型汇总如下:

- 空白符

空白符包含空格、制表符、换行符和换页符,这些字符将被编译器忽略。不过,在verilog字符串的表示中,空格和制表符就应视为字符串的重要字符。

- 注释

Verilog HDL 有两种引入注释的形式。单行注释以两个字符 “//”开始,以换行符结束。代码块注释以 “/*”开始,以 “*/”结束。但我们需要注意的是代码块注释不得嵌套,单行注释符号“//”在代码块注释中也没有任何特殊含义。

- 运算符

运算符分为一元、二元和三元运算符,它们用在表达式中。一元运算符应出现在其操作数的左边。二元运算符应出现在其操作数之间。三元运算符(条件运算符)应使用两个运算符字符分隔三个操作数。

- 常量

Verilog中的常量可指定为整数常量或实数常量。Verilog-2005标准给出的整数常量和实数常量语法规则汇总如下:

图1:verilog-2005的整数(integer number)和实数(real number)常量语法

下面先介绍整数常量:

整数常量可以按十进制、十六进制、八进制或二进制格式指定,且整数常量有两种表达形式。第一种形式是简单的十进制数,即指定为0至9的数字序列,可选择以正负一元运算符开头,代表正负数。第二种形式是标准格式的常数,该常数最多由三个标记组成:一个可选的位宽常量、一个撇号字符(')后跟一个基数字符以及代表数值的数字,另外我们对这三个标记进行宏替换也是合法的。

第一个标记是位宽常量,应按所表示整数的确切位数指定位宽常量的大小,它应指定为一个非零的无符号十进制数。例如,表示一个十六进制数字需要 4 个比特,则表示两个十六进制数字的位宽常量应该设置为8。

第二个标记是基数格式(base_format),由一个不区分大小写的字母组成,该字母指定数字的基数,前面可选择使用单字符 s(或 S)表示有符号的数量,且在单字符前面使用撇号字符,撇号字符和基数字符之间不得有任何空白分隔。十进制、十六进制、八进制和二进制的合法基数格式分别为 d , D , h , H , o , O , b 或 B。

第三个标记是无符号数字,应由指定基数的合法数字组成。无符号数字标记应紧跟在基数之后,但之间可插入空格。十六进制数字 a 至 f 不区分大小写。

不含位宽和基数的简单十进制数应被视为有符号整数,而指定了基数格式的十进制数,如果包含 s 标记,则被视为有符号整数,如果只使用基数格式,则被视为无符号整数。 s 指定符不影响指定数的位结构,只影响编译软件对指定数的解释。

位宽常量前的加减运算符是一元加减运算符,基数和其后数字标记之间的加减运算符是非法语法。

x 表示十六进制、八进制和二进制常数中的未知值。z 代表高阻抗值。x 将在十六进制基数中设置 4 位未知值,在八进制基数中设置 3 位未知值,在二进制基数中设置 1 位未知值。同样,z 分别将 4 位、3 位和 1 位设置为高阻抗值。

如果无符号数的位宽小于为其指定的位宽大小,则无符号数应向左填充零。如果无符号数最左边的位是 x 或 z,则应分别使用 x 或 z 填充到左边。如果无符号数的位宽大于为其指定的位宽大小,则应从左截断无符号数。

组成无符号数(简单十进制数或无符号数)的位宽至少为 32 位。高位为未知数(X 或 x)或高阻抗值(Z 或 z)的无符号常量应扩展到包含该常量的表达式的位宽大小,且使用 x 和 z 定义一个数字的值是不区分大小写的。

在数字常量中经常使用的问号(?)字符是 Verilog HDL 中 高阻抗值z 字符的替代字符。它在十六进制数字中为高阻抗值设置 4 位,在八进制中设置 3 位,在二进制中设置 1 位。在高阻抗值为 "不关心 "条件的情况下,问号可用于提高代码可读性。

下划线字符 (_) 除作为第一个字符外,在常数的任何位置都是合法的,下划线字符将被忽略。博主小飞一般用此下划线字符分割长数字,以提高verilog代码的可读性。

上面罗列了这么多整数常数的规范,小伙伴们如果第一次接触verilog,头肯定晕乎了!别急,小飞下面举几个例子带大家深入掌握这些整数规范!

例子1:无位宽定义的整数常数

前3个数的表示都是合法的,只有最后的4af是非法,因为如果常数不带基数格式,就只能表示十进制数,符合a和f显然不是十进制0~9中的某一个。

例子2:带位宽定义的整数常数

以上的五种表示均合法,但这里小飞要强调一下,第二个数5 ’D 3虽然合法,但不建议大家这么标新立异,正常写成5’D3,不要加空格!

例子3:带符号位的整数常数

根据前面介绍的规范,上图的第一种有符号表示显然不合法,剩下的四种表示均合法。但博主小飞同样在这里强调一下,倒数第二种表示方法-4’sd15同样是恶心人,不建议这么表示一个有符号常数,写成4’sd1即可!

例子4:自动左填充

根据前面介绍的规范,以上的填充确实都合法,不明白的小伙伴们再琢磨一下!

例子5:常数中下划线的使用

这没啥好说的吧,只要下划线不在常数的开头,在其它任意位置都是合法的!

下面介绍实数常量:

在verilog中,实数常数按照 IEEE 754-1985 标准(IEEE 双精度浮点数标准)来表示。实数常数可以用十进制符号(如14.72)或科学符号(如39e8,表示39乘以10的8次方)表示。用小数点表示的实数,小数点两边至少各有一位数。例如:

以上的实数表示均合法。但如下的表示在verilog中则是非法的,因为它们在小数点两边都没有至少一位数。

- 字符串

字符串是由双引号(" ")括起来并包含在一行中的字符序列。在表达式和赋值中用作操作数的字符串应视为无符号整数常量,由一串8位ASCII值表示,一个8位ASCII值代表一个字符。字符串变量是 reg 类型的变量,其位宽等于字符串中的字符数乘以 8。

比如我们要存储 12 个字符的字符串 "Hello world!",则需要一个 8 * 12 或 96 位宽的寄存器:

下面再举一个例子:

其输出为:

如果变量声明的位宽大小超过了字符串赋值所需的位宽大小,那么该值将右对齐,最左边的多余位将用零填充,就像处理非字符串值一样。 如果赋值字符串的位宽大于目标字符串变量所定义的位宽,字符串将右对齐,最左边的字符将被截断。

- 标识符

标识符用于给对象一个唯一的名称,以便引用。标识符可以是简单标识符,也可以是转义标识符。我们常用的简单标识符可以是字母、数字、美元符号 ( $ ) 和下划线字符 ( _ ) 的任意序列。但简单标识符的第一个字符可以是字母或下划线,不应是数字或$,且标识符应区分大小写。比如如下表示都合法:

不同的编译器可设定不同的标识符最大长度,但至少应为 1024 个字符。如果一个标识符超过了编译器所规定的长度限制,就会语法报错。

- 关键字

关键字是verilog标准定义的专用标识符,用于定义语法结构,且所有关键字均以小写定义,变量名不能与关键字重名,否则编译器报错。如下图所示为verilog标准所以的关键字:

美元符号($)引入了一种语言结构,可用于开发用户定义的系统任务和功能。$不是硬件设计语义,而是用于verilog模拟仿真。$后面的名称被解释为系统任务或系统函数。比如:

字符 `(ASCII 值 0x60)引入了一种语言结构,用于执行编译器指令。编译器指令所规定的编译器行为应在编译器读到该指令后立即生效。除非编译器指令另有规定,否则该指令将在编译的其余部分一直有效。因此,一个描述文件中的编译器指令可以控制多个描述文件中的编译行为。比如:

Verilog HDL还包含了一种机制,用于指定verilog源码中对象、语句和语句组的属性,这些属性可被各种芯片综合工具(比如xilinx 公司的vivado)用于控制软件的操作或行为,这些属性称为Attributes。语法定义为:

在 Verilog 描述中,属性实例可以作为前缀出现在声明、模块项、语句或端口连接中。它可以作为表达式中运算符或 Verilog 函数名的后缀出现。如果没有为该属性特别赋值,则其值为 1。如果同一语言元素的同一属性名被定义了多次,则应使用最后一次的属性值;编译工具可发出警告,提示已出现重复的属性规范。下面举几个例子说明一下属性怎么用吧。

例子1:展示如何将属性附加到 case 语句。

以上这3种表示方法均等效!

例子2:附加 full_case 属性,但不附加 parallel_case 属性。

例子3:为模块定义附加属性。

例子4:为模块实例化附加属性。

例子5:为 reg 声明附加属性。

例子6:为操作符“+”附加属性,此操作将属性模式的值设置为字符串 cla 。

例子7:为 Verilog 函数调用附加属性。

例子8:为条件运算符附加属性。

verilog-2005的总体规则预览到这里就介绍完了,从下篇开始博主小飞和小伙伴们正式进入详细、关键的verilog知识学习。

点赞加关注博主(ID:FPGA小飞)的博文,咱们一起系统学习verilog最终标准IEEE Std 1364-2005吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值