第二章Verilog 基本知识Word文档格式.docx
《第二章Verilog 基本知识Word文档格式.docx》由会员分享,可在线阅读,更多相关《第二章Verilog 基本知识Word文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
基数符号
合法标识符
二进制
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、?
需要注意的是
1)在较长的数之间可以用下划线来分开,目的是提高可读性,下划线本身没有意义,
1)在数值中,下划线符号“_”除了不能放于数值的首位外,可以随意用在整型数与实型数中,他们对数值大小没有任何改变,只是为了提高可读性。
例如16’b1011000110001100和16’b1011_0001_1000_1100的数值大小是相同的,只是后一种的表达方式可读性更强。
如16’b1011_0001_1000_1100,但下划线不能用作首字符。
2)当数字没有说明位宽时,默认为32位
3)z或x在二进制中代表1位z或x,在八进制中代表3位z或x,在十六进制中代表4位z或x,其代表的宽度取决于所用的进制。
8’b1011xxxx//等价于8’hBx
8’b1001zzzz//等价于8’h9z
4.若没有定义一个整数的位宽,其宽度为相应值中定义的为数。
例如‘o642//9位八进制数
‘hBD//8位16进制数
5.若定义的位宽比实际数的为数大,则在左边用0补齐。
但如果输最左边一位为x或者z,就相应的用x或z左边补齐。
如10’b101//左边补0,得0000000101
8b’zx01//左边补z,得zzzzz0x1
如果定义的位宽比实际数的位数大,那么最左边的位被截断。
6.“?
”是高阻态z的另一种表示符号。
在数字的表示中,字符“?
”和Z或z是等价的,可以互相替换。
7.整数可以带正、负号,并且正、负号应写在最左边。
负数表示为二进制的补码形式。
8.如果位宽和进制都缺省,则代表十进制数
9.数字中不能有空格,但在表示进制的字母两则可以有空格。
例:
5’hx//5位十六进制数x(扩展的x),即xxxxx
8‘h2A//在位宽和字符之间以及进制和数值之间可以
//有空格,但数字之间不能有空格
2.实数极其表示
1)十进制表示法。
采用十进制格式,小数点两边必须都有数字,否则为非法的表示形式
2)科学计数法。
如564.2e2的值为54620.0
3)VerilogHDL还定义了实数转换为整数的方法,实数通过四舍五入转换为最相近的整数。
3.字符串及其表示
字符串是指用双引号括起来的字符序列,它必须包含在同一行中,不能分行书写。
若字符串用作VerilogHDL表达式或赋值语句中的操作数,则字符串被看作8位的ASCII值序列,即一个字符对应8位的ASCII码。
如“helloworld”和“AnexampleforVerilogHDL”
2.2数据类型
在VerilogHDL中,数据类型共有19种。
分为两类:
物理数据类型(主要包括连线型及寄存器型)和抽象数据类型(主要包括、整型、时间型、实型及参数型)
物理数据类型的抽象数据程度比较低,与实际硬件电路的映射关系比较明显;
而抽象数据类型则是进行辅助设计和验证的数据类型。
2.2.1物理数据类型
VerilogHDL最主要的物理数据类型是连线型、寄存器型和存储器型,并使用四种逻辑电平和八种信号强度对实际的电路建模。
四值逻辑电平是对信号的抽象方式。
信号强度表示数字电路中不同强度的驱动源,用来解决不同驱动强度下的赋值冲突,逻辑0和1可以用下表列出的强度值表示,驱动强度从supply到highz依次递减。
标记符
名称
类型
强弱程度
supply
电源级驱动
驱动
最强
最弱
strong
强驱动
pull
上拉级驱动
large
大容性
存储
weak
弱驱动
medium
中性驱动
small
小容性
highz
高容性
高阻
连线型
连线型数据类型
功能说明
wire,tri
标准连线(缺省为该类型)
wor,trior
多重驱动时,具有线或特性的连线型
trireg
具有电荷保持特性的连线型数据
tri1
上拉电阻
tri0
下拉电阻
sypply0
电源线,用于对“地”建模,为低电平0
supply1
电源线,用于对电源线建模,为高电平1
wand,trand
多重驱动时,具有线与特性的连线型
连线表示逻辑单元的物理连接,可以对应为电路中的物理信号连线,这种变量类型不能保持电荷(除trieg之外)。
连线型变量必须要有驱动源,一种是连接到一个们或者模块的输出端,另一种是用assign连续赋值语句对它进行赋值。
若没有驱动源,将保持高阻态z.
1)wire和tri
最常见的是wire(连线)和tri(三态线)两种,它们的语法和语义一致。
不同之处在于:
wire型变量通常用来表示单个门驱动或连续赋值语句驱动的连线型数据
tri型数据变量则用来表示多驱动器驱动的连线型数据,主要用于定义三态的线网。
wire/tri
x
z
上述真值表明:
同时有两个驱动强度相同的驱动源来驱动wire或tri变量时的输出结果。
2)wor和tiror
Wor/tiror
3)wand和triand
wand/triand
4)trio和tri1
tri0(tri1)的特征是,若无驱动源驱动,其值为0(tri的值为1)
trio/tri1
0/1
5)supply0和supply1
supply0用于对“地”建模,即低电平0;
supply1用于对电源建模,即高电平1.如supply0表示Gnd.Supply1表示Vcc。
6)trireg线网
trireg线网能存储数值(类似于寄存器型数据类型),并且用于电容节点的建模。
当三态寄存器(trireg)的所有驱动源都处于高阻态(z)时,三态寄存器线网将保持作用在线网上的最后一个逻辑值。
三态寄存器线网的缺省初始值为x
一个trireg网络型数据用于模拟电荷存储。
电荷量强度可以下面的关键字来控制:
samll、medium、;
large。
默认的电荷强度为medium。
一个trireg网络型数据能够模拟一个电荷存储节点,该节点的电荷量将随时间而逐渐衰减。
对于一个trireg网络型数据,仿真时其电荷衰减时间应当制定为延迟时间。
2.寄存器型
Reg型变量时最常见也是最重要的寄存器型数据类型,它是数据存储单元的抽象类型,其对应的硬件电路元件具有状态保持作用,能够存储数据,如触发器、锁存器等。
reg型变量常用于行为级描述中,由过程赋值语句对其进行赋值。
reg型数据域wire型数据的区别在于,reg型数据类型保持最后一次的赋值,而wire型数据需要有持续的驱动。
一般情况下,reg型数据的默认初始值为不定值x,缺省时的位宽为1位。
reg型数据变量举例:
rega;
//定义一个1位的名为a的reg型变量
reg[3:
0]b;
//定义一个4位的名为b的reg型变量
reg[8:
1]c,d,e;
//定义三个名称分别为c、d、e的8位reg型的变量。
reg型变量一般是无符号数,若将一个负数赋给一个reg型变量,则自动转换成其二进制补码形式。
在过程块内被赋值的每一个信号都必须定义为reg型,并且只能在always或initial过程块中赋值,大多数reg型信号常常是寄存器或触发器的输出。
2.2.2连线型和寄存器数据类型的声明
1.连线型数据类型的声明
缺省的连线型数据的默认类型为1位(标量)wire类型。
Verilog禁止对已经声明过的网络、变量或参数再次声明。
连线型数据类型声明的一般语法如下:
<
net_declaration>
drive_strength>
range>
delay>
list_of_variables>
其中,drive_strength、range、delay为可选项。
而list_of_variables为必选项
1)net_declaration:
表示网络型数据的类型,可以是wire,tri、tri0、tri1、wand、triand、trior、wor、trireg中的任意一种。
对于trireg类型,其声明还有一个charge_strength(电荷强度)的可选项
2)drive_strength:
表示连线变量的驱动强度
3)range:
用来指定数据位标量或矢量。
若该项默认,表示数据类型为1位的标量,超过1位就为矢量形式。
4)delay:
指定仿真延迟时间
5)list_of_variables:
变量名称,一次可定义多个名称,之间用逗号分开。
2.寄存器型数据类型的声明
reg型数据类型声明的一般语法格式:
reg<
list_of_register_variables>
其中,range为可选项,它制定了reg型变量的位宽,缺省时为1位。
说明:
list_of_register_variables:
变量名称列表,一次可以定义多个名称,之间用逗号分开。
物理数据类型声明举例:
reg[7:
0]regb;
//定义一个8位的寄存器变量
tri[7:
0]tribus;
//定义了一个8位的三态总线
tri0[15:
0]busa;
//定义了一个16位的连线型,处于三态时为上拉电阻
tri1[31:
0]busb;
//定义了一个32位的连线型,处于三态时为下拉电阻
regscalared[1:
4]b;
//定义了一个4位的标量型寄存器矢量
wire(pull,strong())c=a+b;
//定义了一个1和0的驱动强度不同的1位连线型变量c
trireg(large)storeline;
//定义了一个具有强度的电荷存储功能的存储线
2.2.3存储器型
存储器型(memory)本质上还是寄存器型变量阵列,只是VerilogHDL语言中没有多维数组,所有就用reg型变量建立寄存器组来实现存储器的功能,也就是扩展的reg型数据地址范围。
存储器型变量可以描述RAM型、ROM型存储器以及reg文件。
数组中的每一个单元通过一个数组索引进行寻址。
存储器型变量的一般声明格式:
rangel1>
name_of_register>
range2>
;
其中,range1和range2都是可选项,缺省时都为1.
(1)range1:
表示存储器中寄存器的位宽,格式为[msb:
lsb]
(2)range2:
表示寄存器的个数,格式为[msb:
lsb],即有msb-lsb+1个
(3)name_of_register:
reg[7:
0]mem1[255:
0];
//定义了一个有256个8位寄存器的存储器mem1地址范围是0到255.
reg[15:
0]mem2[127:
0],reg1,reg2;
//定义了一个具有128个16位寄存器的存储器,mem2和2个16位的寄存器reg1和reg2
注意:
memory型和reg型数据的差别。
一个由n个1位寄存器构成的寄存器和一个n位寄存器的意义是不同的。
reg[n-1:
0]a;
//表示一个n位的寄存器a
regmem1[n-1:
//表示一个由n个1位寄存器构成的存储器mem1.
一个n位的寄存器可以在一条赋值语句里进行赋值,而一个完整的存储器则不行。
如果想对存储器中的存储单元进行读写操作,则必须指定该单元在存储器中的地址。
如:
mem1[2]=0;
//给mem1存储器中的第三个存储单元赋值为0
2.2.4抽象数据类型
除了物理数据类型外,VerilogHDL还提供了一下几种抽象数据类型:
整形(integer)、时间型(time)、实型(real)及参数型(parameter)。
他们只是纯数学的抽象描述,不能够与实际的硬件电路相映射。
1.整型
整型数据常用于对循环控制变量的说明,在算术运算中被视为二进制补码形式的有符号数。
除了寄存器数据被当作无符号数来处理之外,整数型据与32位寄存器型数据在实际意义上相同。
整型数据的声明格式:
integer<
integerindex;
//简单的32位有符号整数
integeri[31:
//定义了整数数组,它有32个元素
2时间型
时间型数据与整型数据类似,只是它是64位的无符号数。
时间型数据主要用于对模拟时间的存储与计算处理,常与系统函数$time一起使用
声明格式如下:
time<
timea,b;
//定义了两个64位的时间变量
3实型
VerilogHDL支持实型常量与变量。
实型数据在机器码表示法中是浮点型数据,,可用于对延迟时间的计算。
声明格式:
real<
realstime;
//定义了一个实型数据
4参数型
在VerilogHDL中,参数是一个非常重要的数据类型,属于常量,在仿真开始之前就被赋值,在仿真过程中保持不变。
采用参数定义方法可以提高程序的可读性和维护性。
参数常用来定义延迟时间和变量的位宽。
参数类型的定义格式:
parameter参数名1=表达式1,参数名2=表达式2,………,参数名n=表达式n;
其中,表达式既可以是常数,也可以是表达式。
参数定义完以后,程序中出现的所有的参数名都将被替换为相对应的表达式。
parameterlength=32,weight=16;
运算符
VerilogHDL语言的运算符主要针对数字逻辑电路的制定,覆盖范围广泛。
请参见VerilogHDL中的运算符和优先级。
2.3.1算术运算符
VerilogHDL中常用的算术运算符主要有5种,分别是加法(+)、减法(-)、乘法(*)、除法(/)、取模(%),均为双目运算符
1)算术操作结果的位宽
算术表达式结果的长度由最长的操作数决定。
在赋值语句中,算术操作结果的长度由操作左端的目标长度决定。
2)有符号与无符号的使用
无符号数的值一般存储在线网、reg(寄存器)变量及普通(没有符号标记s)的基数格式表示的整数型中
有符号数值一般存储在存储在整型变量、十进制形式的整数、有符号的reg(寄存器)变量及有符号的线网中
2.3.2关系运算符
双目运算符:
大于(>
)、小于(<
)、大于等于、小于等于、
在进行关系比较时,如果成立则结果为“1”,否则返回的结果为“0”.
若不确定则返回结果为不定值(x)
2.3.4相等关系运算符
相等关系运算符是对两个操作数进行比较,比较的结果有三种:
真1,假0,和不定值(x).
VerilogHD语言中四种相等关系运算符:
等于(==)、不等于(!
=)、全等于(===)。
这四种运算符都是双目运算符,要求有两个操作数。
他们的优先级是相同的。
“==”和“!
=”称为逻辑等式运算符,其结果有两个操作数的值决定,由于操作数中某些位可能是不定值x和高阻态值z,所以结果可能是不定值x。
“===”和“!
==”运算符则不同,他是对操作数按位比较,两个操作数必须完全一样,其结果才是1,否则都是0.但是,若两个操作数对应位出现不定值x和高阻值z,则可以认为是相同的。
“===”和“!
==”运算符常用于case表达式的判别,所以又称为“case”等式运算符。
2.3.4逻辑运算符
逻辑与运算符“&
&
”逻辑或运算符“||”,逻辑非运算符(!
)
其中逻辑与和逻辑或,是双目运算符。
逻辑非为单目运算符。
在逻辑运算符的操作中,如果操作数是1位的,那么1就代表逻辑真,0就代表逻辑假。
如果是操作数是由多位的,则当操作数每一位都是0时才是逻辑0值,只要有一位1,这个操作数就是逻辑1值。
例如:
寄存器变量a、b的初值分别是4’b1110和4’b0000,则
!
a=0,!
b=1;
a&
b=0;
a||b=1;
需要注意的是,若操作数中存在不定态x,则逻辑运算的结果也是不定态。
2.3.5按位运算符
数字逻辑电路中,信号与信号之间的运算称之位运算。
VerilogHDL提供了一下五种类型的位运算符:
按位取反(~)、按位与(&
)、按位或(|)、按位异或(^)、按位同或(^~)
位逻辑运算对其自变量的每一位进行操作。
2.3.6归纳运算符
归纳运算符按位进行逻辑运算,属于单目运算符。
由于这一类运算符操作的结果产生1位逻辑值,因而被形象地称为缩位运算符。
在VerilogHDL中,缩位运算符包括&
(与)、|(或)、^(异或)以及相应的非操作~&
、~|、~^、^~.归纳运算符的操作数只有一个。
2.3.7移位运算符
移位运算符有两种:
左移位运算符(<
)、右移位运算符(>
>
)。
运算过程是将左边(右边)的操作数向左(右)移,所移动的位数由右边的操作数来决定,然后用0来填补移出的空位。
2.3.8条件运算符
条件运算符是VerilogHDL里唯一的三目运算符。
它根据条件表达式的值来选择执行表达式,其表达形式为
条件表达式>
?
表达式1>
:
表达式2>
其中,条件表达式的计算结果有真
(1)、假(0)和不定时(x)三种。
当条件表达式的结果为真时,执行表达式1,当条件表达式的结果为假时,执行表达式为2.
当条件表达式的结果为不定态x,则模拟器按位对表达式1的值与表达式2的值进行比较。
2.3.9链接和复制运算符
连接运算符({})和复制运算符({{}})
连接运算符是把位于大括号({})中的两个或两个以上信号或数值用逗号(,)分隔的小表达式按位连接在一起,最后用大括号括起来表示一个整体信号,形成一个大的表达式,其格式为:
{信号1的某几位,信号2的某几位,……,信号n的某几位}
重复运算符({{}})将一个表达式放入双重花括号中,复制因子放在第一层括号中,它为复制一个常量提供了一种简便的方法。
2.4模块
2.4.1模块的基本概念
模块(module)是VerilogHDL语言的基本单元,它代表一个基本的功能块,用于描述某个设计的功能或结构,以及与其它模块通信的一个外部端口,一个电路设计不仅仅局限于一个模块的设计,而是由多个模块组合而成,因此一个模块的设计只是一个系统设计中某个层次的设计。
基本的模块结构组成
(1).模块的开始与结束:
模块在语言形式上是以关键字module开始,以关键词endmodule结束的一段程序,其中模块开始语句必须要以分号结束。
模块的开始部分包括模块名(name)和端口列表(Port_list),模块名是模块唯一性的标识符,而端口列表是由模块各个输入、输出和双向端口变量组成的一张列表,这些端口用
来与其它模块进行连接(不妨理解为集成电路的引脚)
(2)模块端口定义:
用来定义端口列表里的变量那些是输入(input)、输出(output)和双向端口(inout)以及位宽。
(3)模块数据类型的说明:
数据类型包括wire、reg、memory和parameter等,用来说明模块中所用到的内部信号、调用模块等的声明语句和功能定义语句。
一般来说,module的input缺省定义为wire类型,output信号可以是wire类型,也可以是reg类型(条件是在always或initial语句块中被赋值);
inout一般为tri(三态类型),表示有多个驱动源。
(4)模块逻辑功能描述:
用来产生各种逻辑(主要是组合逻辑和时序逻辑),主要包括initial语句、always语句、其它子模块实例化语句、门实例化语句、用户自定义原语(UDP)实例化语句、连续赋值语句(assign)、函数(function)和任务(task)
因此由上述模块的结构组成可以看出,模块在概念上可等同于一个器件,比如通用器件(与门、三态门)或通用宏单元(计数器、ALU、CPU)等。
一个模块可在另一个模块中调用,一个模块代表了一个特定功能块。
一个电路设计可由多个模块组合而成,因此一个模块的设计只是一个系统设计中某个层次的设计。
模块设计可采用多中建模方式,一般包括行