简介
本文将涉及verilog的设计方法,探索使用verilog hdl描述数字电路,探索verilog的语言特性。
内容总结于诚聘英才 > 在线课堂_西安电子科技大学微电子学院
【电子】Verilog硬件描述语言 西安电子科技大学 蔡觉平等主讲_哔哩哔哩_bilibili
语言要素和数据类型
语言要素
空白符:空格符(\b),制表符(\t),换行符,换页符
注释符:
单行注释:单行注释以“//”开始
多行注释:多行注释以“/*”开始,到“*/”结束
标识符和转义标识符:
标识符:字母、数字、$符号和_(下划线)符号
转义标识符:“\”(反斜线)符号开头,以空白结尾(空白可以是一个空格、一个制表字符或换行符)。
关键字:用来组织语言结构。
数值:
四值电平逻辑:
状态 | 含义 |
0 | 低电平、逻辑0或''假” |
1 | 高电平、逻辑1或“真” |
x或X | 不确定或未知的逻辑状态 |
z或Z | 高阻态 |
整数:+/-<size>'<base_format><number>
数制 | 基数符号 | 数字字符集 |
二进制 | b或B | 0、1、X、X、z、Z、?、_ |
八进制 | o或O | 0~7、X、X、z、Z、?、_ |
十进制 | d或D | 0~9、_ |
十六进制 | h或H | 0~9、a〜f、A〜F、X、X、z、Z^ ?、_ |
注意事项:
- 在较长的数之间可以用下划线来分开
-
当数字没有说明位宽时,默认为32位
-
x或z在二进制中代表1位x或z,在八进制中代表3位x或z,在十六进制中代表4位x或z
-
若没有定义一个整数的位宽,其宽度为相应值中定义的位数。
-
若定义的位宽比实际数的位数大,则在左边用0补齐。但如果数最左边一位为x或z,就相应地用x或z在左边补齐。如果定义的位宽比实际数的位宽小,那么最左边的位被截断。
-
“?”是高阻态z的另一种表示符号。在数字的表示中,字符"?”和z或Z是等价的,可互相替代。
-
整数可以带正、负号,并且正、负号应写在最左边。负数表示为二进制的补码形式。-4等价于4'b1100
-
如果位宽和进制都缺省,则代表十进制数。
-
数字中不能有空格,但在表示进制的字母两侧可以有空格。
实数:
十进制表示法:小数点两边必须都有数字
科学计数法:564.2e2的值为56420.0。
字符串:字符串是指用双引号括起来的字符序列。
数据类型
数据类型共有19 种:
wire、tri、tri0、tri1、wand、triand 、trireg、 trior、 wor、 reg、large、small、scalared、 medium、 vectored、integer、time、real、parameter
物理数据类型:
强度等级:
标记符 | 名称 | 类型 | 强弱程度 |
supply | 电源级驱动 | 驱动 | 1 |
strong | 强驱动 | 驱动 | 2 |
pull | 上拉级驱动 | 驱动 | 3 |
large | 大容性 | 存储 | 4 |
weak | 弱驱动 | 驱动 | 5 |
medium | 中性驱动 | 存储 | 6 |
small | 小容性 | 存储 | 7 |
highz | 高容性 | 高阻 | 8 |
连线型:<net_declaration> <drive_strength><rangexdelay>[list_of_variables];
连线型数据类型 | 功能说明 |
wire, tri | 标准连线型(缺省为该类型) |
wor, trior | 多重驱动时,具有线或特性的连线型 |
wand, trand | 多重驱动时,具有线与特性的连线型 |
trireg | 具有电荷保持特性的连线型(特例) |
tri1 | 上拉电阻 |
tri0 | 下拉电阻 |
supply1 | 电源线,用于对电源建模,为高电平1 |
suppIy0 | 电源线,用于对“地”建模,为低电平0 |
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 |
寄存器型:reg型:数据储存单元的抽象类型,能够存储数据,如触发器、锁存器等,
reg型变量:常用于行为级描述中,由过程赋值语句对其进行赋值。
格式:reg<range><list_of_register_variables>;
存储器型:存储器型(memory)本质上还是寄存器型变量阵列,存储器型变量可以描述RAM型、ROM型存储器以及reg文件。
用reg型变量建立寄存器组(数组)来实现存储器的功能
格式:reg<range 1><name_of_regisler><range2>;
抽象数据类型:
整型:integer<list_of_register_variables>;
整型数据常用于对循环控制变量的说明,在算术运算中被视为二进制补码形式的有符
号数。
时间型:lime<list_of_register_variables>;
时间型数据与整型数据类似,只是它是64位的无符号数。
实型:real<list_of_variables>;
参数型:parameter 参数名1=表达式1,参数名2 =表达式2, ...,参数名n =表达式n;
- 表达式既可以是常数,也可以是表达式。参数定义完以后,程序中出现的所有的参
数名都将被替换为相对应的表达式。
- 另外,对于同一个模块来说,参数一旦被定义就不能够通过其它语句对它重新赋值。
运算符和表达式
优先级:
运算符 | 功 能 | 优先级别 |
!、~ | 反逻辑、位反相 | 1 |
*、/、% | 乘、除、取模 | 2 |
+、- | 加、减 | 3 |
<<、>> | 左移、右移 | 4 |
<、<=、>、>= | 小于、小于等于、大于、大于等于 | 5 |
==、!=、===、!== | 等、不等、全等、非全等 | 6 |
& | 按位与 | 7 |
^、^~ | 按位逻辑异或和同或 | 8 |
I | 按位逻辑或 | 9 |
&& | 逻辑与 | 10 |
II | 逻辑或 | 11 |
?: | 条件运算符,唯一的三目运算符,等同于if-else | 12 |
算术运算符:
注意事项:
- 算术运算结果的位宽:算术表达式结果的长度由最长的操作数决定。
- 有符号数和无符号数的使用:
- 无符号数值一般存储在线网、reg(寄存器)型变量及普通(没有符号标记s)的基数格式表示的整型数中。
- 有符号数值一般存储在整型变量、十进制形式的整数、有符号的reg(寄存器)型变量及
有符号的线网中。
关系运算符
相等关系运算符
==:
== | 0 | 1 | x | z |
0 | 1 | 0 | x | x |
1 | 0 | 1 | x | x |
x | x | x | x | x |
z | x | x | x | x |
===:
=== | 0 | 1 | x | z |
0 | 1 | 0 | 0 | 0 |
1 | 0 | 1 | 0 | 0 |
x | 0 | 0 | 1 | 0 |
z | 0 | 0 | 0 | 1 |
逻辑运算符:
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 |
按位运算符:
&:
& | 0 | 1 | x |
0 | 0 | 0 | 0 |
1 | 0 | 1 | x |
x | 0 | x | x |
|:
| | 0 | 1 | x |
0 | 0 | 1 | x |
1 | 1 | 1 | 1 |
x | x | 1 | x |
^:
^ | 0 | 1 | x |
0 | 0 | 1 | x |
1 | 1 | 0 | x |
x | x | x | x |
两个不同长度的数据进行位运算时,会自动地将两个操作数按右端对齐,位数少的操作数会在高位用0补齐,然后逐位进行运算,运算结果的位宽与操作数中位宽较大者相同。
规约运算符:
缩位运算符包括&(与)、I (或)、^(异或)以及相应的非操作~&、~|、~^、^~。
归约运算符的操作数只有一个。
移位运算符:
左移位运算符(<<)、右移位运算符(>>)。
条件运算符:
<条件表达式>?<表达式1>:<表达式2>
条件表达式的运算结果有真(1)、假(0)和不定态(x)三种。当条件表达式的结果为真时,
执行表达式1,当条件表达式的结果为假时,执行表达式2。
如果条件表达式的运算结果为不定态x,则模拟器将按位对表达式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 |
连接和复制运算符:
连接运算符 {} :{信号1的某几位,信号2的某几位,信号n的某几位}。
复制运算符 {{}} :将一个表达式放入双重花括号中,复制因子放在第一层括号中。
模块 module:
端口:
声明方式:
输入端口: input[倩号位宽-1:0]端口名1;
输出端口: output[信号位宽-1:0]端口名1:
输入输出端口: inout[信号位宽-1:0]端口名1;
模块引用时端口的对应方式:
模块名(连接端口 1信号名,连接端口 2信号名…);
模块名(.端口 1名(连接信号1名),.端口 2名(连接信号2名)…);