Verilog基础(四)
四、Verilog语法
1、空白符
2、注释符:
1、单行注释: //
2、多行注释: /* */
3、标识符和转义字符
标识符用来命名信号、模块、参数等,可以是任何字母、数字、$符号以及下划线的组合,标识符区分大小写,并且第一个字符必须是英文字母或下划线
4、关键字
5、数据类型
1、数值
Verilog的数值状态有四种,在逻辑数值中,x和z都不区分大小写。
状态 | 含义 |
0 | 低电平、逻辑0、假 |
1 | 高电平、逻辑1、真 |
X | 不确定状态或者未知逻辑 |
Z | 高阻态 |
在数值中,下划线符号“_”除了不能放在数值的首位外,可以随意在整型数与实例数中,他们对数值的大小没有改变,只是为了提高可读性。
- 整数的表示形式:+/-<size>’<base_format><number>其中,“+,-”是正负数的表示,size表示换算后的二进制宽度,“ ’ ”为基础格式表示的固有字符,不能缺省,base_format表示基数的符号;number是可以使用数字字符集。
注意:
- 在较长的数之间可以使用下划线来划分,目的是提高可读性
- 当数字没有说明位宽时,默认是32
- X或者z在二进制代表1位x或z;在八进制代表3位;16进制代表4位
- 若没有定义一个整数的位宽,其宽度应为相应值中定义的位数
- 若定义的位宽比实际数的位数大,则在左边用0补齐,若最左边为0或者x则用0或者x补齐。
- 如果定义的位宽比实际数的位宽小,则最左边的位被截断
- 整数可以带正负号,并且正负号应写在最左边,负数用二进制的补码表示
- 如果位宽与进制都缺省,则代表十进制数,数字中不能有空格,但在表示进制的字母两侧可以有空格。
- “ ?”表示高阻态
- 数字中不能有空格,表示进制的字母两侧可以有空格
- 实数的表示方法
- 十进制表示:小数点两侧必须有数值
- 科学计数法
2、字符串及其表示
双引号括起来的字符序列
1、数据类型
物理数据类型
最主要的物理数据类型是连线型、寄存器型和存储器型,并使用四种逻辑电平和八种信号强度对实际的硬件电路建模。信号强度表示数字电路中不同强度的驱动源,用来解决不同驱动强度下的赋值冲突。
标识符 | 名称 | 类型 | 强弱程度 |
Supply | 电源级驱动 | 驱动 | 强 |
Strong | 强驱动 | 驱动 | |
Pull | 上拉级驱动 | 驱动 | |
Large | 大容性 | 存储 | |
Weak | 弱驱动 | 驱动 | |
Medium | 中性驱动 | 存储 | |
Small | 小容性 | 存储 | |
Highz | 高容性 | 高阻 |
连线型
连线型数据类型 | 功能说明 |
Wire\tri | 标准连线型 |
Wor\trior | 多重驱动时,具有线或特性的连线型 |
Trireg | 多重驱动时,具有线与特性的连线型 |
Tri1 | 上拉电阻 |
Tri0 | 下拉电阻 |
Supply1 | 电源线,对电源建模,高电平为1 |
Supply0 | 电源线,对于地建模,低电平为0 |
注意:
连线表示逻辑单元的物理连接,可以对应位电路中的物理信号线,这种变量类型能保持电荷,连线型变量必须有驱动源,一种是连接到一个门或者模块的输出端,另一种是用assign连续赋值语句对他进行赋值。若没有驱动源,则保持高阻态。
Wire和tri
在众多连线型数据类型中,常见的是wire(连线)和tri(三态线)两种,语法一致。不同之处在于:wire常用表示单个门驱动或连续赋值语句驱动的连线型数据,tri型变量则用来表示多驱动器驱动的连线型数据,主要用于三态的线网。
真值表
Wire、tri | 0 | 1 | x | Z |
0 | 0 | x | x | 0 |
1 | X | 1 | X | 1 |
X | x | X | X | X |
z | 0 | 1 | x | z |
例如:
Wire【2:0】 c = 3’b0x1
Assign c = 3’b0x1;
Assign c = 3’b1z1;
C=3’bxx1
Wor\trior:当多个驱动源驱动wor和trior型数据时,将产生线或结构
Wor、trior | 0 | 1 | x | Z |
0 | 0 | 1 | x | 0 |
1 | 1 | 1 | 1 | 1 |
X | x | 1 | x | X |
Z | 0 | 1 | x | Z |
Wand、triand
当多个驱动源驱动wand和triand型数据时,将产生线与结构
Wand、triand | 0 | 1 | X | z |
0 | 0 | 0 | 0 | 0 |
1 | 0 | 1 | x | 1 |
X | 0 | x | x | X |
Z | 0 | 1 | x | z |
Tri0和tri1
Tri0(tri1)的特征:若无驱动源驱动,其值为0,在多个驱动源的情况下,tri0和tri1的真值表如图
Tri0\tri1 | 0 | 1 | x | Z |
0 | 0 | x | x | 0 |
1 | x | 1 | x | 1 |
X | x | x | x | X |
z | 0 | 1 | x | 0/1 |
Supply0和supply1
Trireg线网
能存储数值,并且用于电容节点的建模,当三态寄存器的所有驱动源都处于高阻态z时,三态寄存器线网将保存作用在线网上的最后一个逻辑值,三态寄存器线网的缺省初始值为x
Reg寄存器类型
寄存器数据保持最后一次的赋值,而wire型数据需要持续的驱动,一般情况下,reg型数据默认的初始值为不定值x,缺省时的位宽为1位。
2、连线型与寄存器的数据类型的声明
连线型的语法:
<net_declaration><drive_strength><range><delay>[list_of_variables]
解释:
net_declaration:网络型数据类型,可以是wire\tri\tri0\tri1\wand\triand\trior\wor\trireg中的任意一种
drive_strength:连线变量的驱动强度
range:指定数据为标量或者矢量
delay:指定仿真延迟的时间
[list_of_variables]:变量名称,一次可以定义多个名称
寄存器型语法:
reg<range>[list_of_register_variables]
存储器型:存储器本身是寄存器型变量阵列,只是verilogHDL中没有多维数组,所以用reg建立寄存器组来实现存储器功能。
存储器的变量一般声明为:
Reg<rangel><name_of_register><range2>
Rangel:存储器中寄存器的位宽,格式为[msb:lsb]
name_of_register:变量名
range2:寄存器的个数,格式为[msb:lsb],有msb-lsb+1个
存储器类型
存储器本质上还是寄存器类型变量阵列,存储器型可以描述RAM型、ROM型存储器以及reg文件。数组中的每一个单元通过一个数组索引进行寻址。
存储器类型变量的声明一般为
reg<range1><name><range2>
说明:
Range1:位宽
Range2:个数
注意:一个n位的寄存器可以在一条赋值语句中进行赋值,一个完整的存储器则不行,想要对存储器中的存储单元进行读写,必须指定该单元在存储中的地址。
抽象数据类型
整型
整型数据通常用于对循环的控制说明,在算术运算中被视为二进制补码形式的有符号整数。除了寄存器类型数据被当作无符号数处理之外,整型数据与32位寄存器型数据在实际意义上相同。
其格式:
Integer< list_of_register_variable >;
说明
Integer index; //定义一个32位的有符号整数
Integer i [31:0]; //定义一个整数型数组,他有32个元素
时间型
时间型与整型一样,不过是64位无符号数。常与系统函数$time一起使用。
时间型数据声明如下:
time<list_of_register_variable>
实型
实型数据在机器码表示法中表示浮点型数值,用于延迟时间的计算
参数型
参数型定义为:
Parameter length = 32,weigh = 16;
对于同一个模块来说,参数一旦被定义就不能通过其他语句对它重新赋值,但可以通过模块之间的参数传递来实现。
6、运算符
运算符的优先级
运算符 | 功能 | 优先级 |
!、~ | 反逻辑 | |
*、/、% | 乘、除、取模 | |
+、- | 加、减 | |
<<、>> | 左移、右移 | |
<、<=、>、>= | 小于、小于等于、大于、大于等于 | |
==、!=、===、!== | 等、不等、全等、非全等 | |
& | 按位与 | |
^、^~ | 按位逻辑异或、同或 | |
| | 按位逻辑或 | |
&& | 逻辑与 | |
|| | 逻辑或 | |
?: | 条件运算符、等于if——else |
算术运算符
取模运算就是计算余数
算术运算结果的位宽,算术表达式结果的长度由最长的操作数决定,在赋值语句下,算术运算结果的长度由等号操作符左端的目标长度决定。
例如:
Reg [3:0] A,B,C;
Reg [5:0] D;
A = B+C;
D = B+C;
第一个加法重,表达式“B+C”的位宽由B\C中最长的位宽决定,为4位,结果位宽由A决定,为4位;第二个加法中,右侧由B\C位宽最长的位宽决定,为4位,结果位宽由D决定,为6位。若位宽不足溢出部分,高位被丢弃,反之被存储在高位。
有符号数和无符号数的使用
无符号数值一般存储在线网、reg型变量及普通的基数格式表示整型数中。
有符号数值一般存储在整型变量、十进制形式的整数、有符号的reg型变量及有符号的线网中。
关系运算符
关系运算符也是双目运算符,对两个操作数的大小比较,若为真则返还1’b1,若为假则1’b0;
当操作数长度不同,长度短的操作数应该在左边用0补齐。
相等关系运算符
相等关系是对连个操作数作比较,比较结果有三种:
== :全等
!=:不等
===:按位相等
逻辑运算符
逻辑与(&&)、逻辑或(||)、逻辑非(!)
真值表如下:
a | b | !a | !b | a&&b | a||b |
1 | 1 | 0 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 0 | 1 |
0 | 1 | 1 | 0 | 0 | 1 |
0 | 0 | 1 | 1 | 0 | 0 |
在逻辑运算符的操作过程中,如果操作数是1位的,则1就代表逻辑真,若果操作数是多位的则只有全为0时,代表逻辑假,否则为逻辑真。
按位运算
按位运算包括:按位取反~、按位与&、按位或|、按位异或^、按位同或^~。
按位运算符对其自变量的每一位进行操作
计算实例:
约归运算符
约归运算符按位进行逻辑运算,属于单目运算符。缩位运算符包括&(与)、|(或)、^(异或)以及对应的非操作。
归约运算的过程是:设a是一个4位的寄存器型变量,其4位分别是a[0]、a[1]、a[2]、a[3]。
当对a进行缩位运算时,先对a[0]、a[1]进行缩位运算,产生1位的结果,再将这个结果与a[2]进行缩位运算,接着是a[3]、a[4]。最后产生1位的操作结果。
计算实例:
如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0
两个值相同,则同或结果为1
移位运算符
移位运算符有两种:左移位、右移位,将左(右)操作数向左(右)移动,用0补充移出的空位。
程序实例:
条件运算符
表达式形式:
<条件表达式>?<表达式1>:<表达式2>
其真值表:
?: | 0 | 1 | x | Z |
0 | 0 | x | x | x |
1 | x | 1 | x | x |
X | X | x | x | X |
z | x | x | x | x |
程序实例:
连接和复制运算符
连接运算符是把位于大括号{ } 中的两个或两个以上信号或数值用逗号分开的小表达式按位连接在一起,最后用大括号表示一个整体。形成一个大表达式。
重复运算符{ { } }表示复制因子放在第一层括号中
举例: