VerilogHDL语言的数据类型和运算符
VerilogHDL语言数据类型运算符
2.3.1 标志符 标志符可以是一组字母、数字、_下划线和$符号的组合,且标志符的第一个字符必须是字母或者下划线。另外,标志符是区别大小写的。下面给出标志符的几个例子:Clk_100MHzdiag_state_ceP_o1_02需要注意的是,Verilog HDL定义了一系列保留字,叫作关键字,具体资料可查阅相关标准。只有小写的关键字才是保留字,因此在实际开发中,建议将不确定是否是保留字的标志符首字母大写。例如:标志符if(关键字)与标志符IF是不同的。 2.3.2 数据类型数据类型用来表示数字电路硬件中的数据存储和传送元素。Verilog HDL中总共有19种数据类型,本书只介绍4个常用的数据类型:wire型、reg型、memory型和parameter型,其他类型将在后续章节中逐步介绍。1.wire型wire型数据常用来表示以assign关键字指定的组合逻辑信号。Verilog程序模块中输入、输出信号类型默认为wire型。wire型信号可以用做方程式的输入,也可以用做“assign”语句或者实例元件的输出。 wire型信号的定义格式如下: wire [n-1:0] 数据名1,数据名2,……数据名N; 这里,总共定义了N条线,每条线的位宽为n。下面给出几个例子: wire [9:0] a, b, c; // a, b, c都是位宽为10的wire型信号 wire d;2.reg型reg是寄存器数据类型的关键字。寄存器是数据存储单元的抽象,通过赋值语句可以改变寄存器存储的值,其作用相当于改变触发器存储器的值。reg型数据常用来表示always模块内的指定信号,代表触发器。通常在设计中要由always模块通过使用行为描述语句来表达逻辑关系。在always块内被赋值的每一个信号都必须定义为reg型,即赋值操作符的右端变量必须是reg型。 reg型信号的定义格式如下: reg [n-1:0] 数据名1,数据名2,……数据名N; 这里,总共定义了N个寄存器变量,每条线的位宽为n。下面给出几个例子: reg [9:0] a, b, c; // a, b, c都是位宽为10的寄存器 reg d;reg型数据的缺省值是未知的。reg型数据可以为正值或负值。但当一个reg型数据是一个表达式中的操作数时,它的值被当作无符号值,即正值。如果一个4位的reg型数据被写入-1,在表达式中运算时,其值被认为是+15。reg型和wire型的区别在于:reg型保持最后一次的赋值,而wire型则需要持续的驱动。3.memory型Verilog通过对reg型变量建立数组来对存储器建模,可以描述RAM、ROM存储器和寄存器数组。数组中的每一个单元通过一个整数索引进行寻址。memory型通过扩展reg 型数据的地址范围来达到二维数组的效果,其定义的格式如下: reg [n-1:0] 存储器名 [m-1:0];其中,reg [n-1:0]定义了存储器中每一个存储单元的大小,即该存储器单元是一个n位位宽的寄存器;存储器后面的[m-1:0]则定义了存储器的大小,即该存储器中有多少个这样的寄存器。例如: reg [15:0] ROMA [7:0];这个例子定义了一个存储位宽为16位,存储深度为8的一个存储器。该存储器的地址范围是0到8。需要注意的是:对存储器进行地址索引的表达式必须是常数表达式。 尽管memory型和reg型数据的定义比较接近,但二者还是有很大区别的。例如,一个由n个1位寄存器构成的存储器是不同于一个n位寄存器的。 reg [n-1 : 0] rega; // 一个n位的寄存器 reg memb [n-1 : 0]; // 一个由n个1位寄存器构成的存储器组 一个n位的寄存器可以在一条赋值语句中直接进行赋值,而一个完整的存储器则不行。 rega = 0; // 合法赋值 memb = 0; // 非法赋值 如果要对memory型存储单元进行读写必须要指定地址。例如: memb[0] = 1; // 将memeb中的第0个单元赋值为1。 reg [3:0] Xrom [4:1]; Xrom[1] = 4’h0; Xrom[2] = 4’ha; Xrom[3] = 4’h9; Xrom[4] = 4’hf;4.parameter型在Verilog HDL中用parameter来定义常量,即用parameter来定义一个标志符表示一个常数。采用该类型可以提高程序的可读性和可维护性。 parameter型信号的定义格式如下: parameter 参数名1 = 数据名1; 下面给出几个例子: parameter s1 = 1; parameter [3:0] S0=4'h0, S1=4'h1, S2=4'h2, S3=4'h3, S4=4'h4;
2.3.3 模块端口模块端口是指模块与外界交互信息的接口,包括3种类型:
input: 模块从外界读取数据的接口,在模块内不可写。
output:模块往外界送出数据的接口,在模块内不可读。
inout:可读取数据也可以送出数据,数据可双向流动。
2.3.4 常量集合Verilog HDL有下列4种基本的数值: 0:逻辑0或“假” 1:逻辑1或“真” x:未知 z:高阻 其中x、z是不区分大小写的。Verilog HDL中的数字由这四类基本数值表示。Verilog HDL中的常量分为3类:整数型、实数型以及字符串型。下划线符号“_”可以随意用在整数和实数中,没有实际意义,只是为了提高可读性。例如:56等效于5_6。1.整数整数型可以按如下两种方式书写:简单的十进制数格式以及基数格式。(1)简单的十进制格式简单的十进制数格式的整数定义为带有一个“+”或“-”操作符的数字序列。下面是这种简易十进制形式整数的例子。 45 十进制数45 -46 十进制数-46简单的十进制数格式的整数值代表一个有符号的数,其中负数可使用两种补码形式表示。例如,32在6位二进制形式中表示为100000,在7位二进制形式中为0100000,这里最高位0表示符号位;-15在5位二进制中的形式为10001,最高位1表示符号位,在6位二进制中为110001,最高位1为符号扩展位。(2)基数表示格式基数格式的整数格式为: [长度] '基数 数值 长度是常量的位长,基数可以是二进制、十进制、十六进制之一。数值是基于基数的数字序列,且数值不能为负数。下面是一些具体实例: 6'b9 6位二进制数 5'o9 5位八进制数 9'd6 9位十进制数2.实数实数可以用下列两种形式定义:(1)十进制计数法,例如:2.016539.236(2)科学计数法这种形式的实数举例如下,其中e与E相同。235.12e2 其值为235125e-4 其值为0.0005根据Verilog语言的定义,实数通过四舍五入隐式地转换为最相近的整数。3.字符串字符串是双引号内的字符序列。字符串不能分成多行书写。例如:“counter”用8位ASCII值表示的字符可看作是无符号整数,因此字符串是8位ASCII值的序列。为存储字符串“counter”,变量需要 位。reg [1: 8*7] Char;Char = ''counter'';2.3.5 运算符和表达式在Verilog HDL语言中运算符所带的操作数是不同的,按其所带操作数的个数可以分为三种:
单目运算符:带一个操作数,且放在运算符的右边。
双目运算符:带两个操作数,且放在运算符的两边。
三目运算符:带三个操作数,且被运算符间隔开。
Verilog HDL语言参考了C语言中大多数算符的语法和句义,运算范围很广,其运算符按其功能分为下列9类:1. 基本算术运算符在Verilog HDL中,算术运算符又称为二进制运算符,有下列5种:
+ 加法运算符或正值运算符,如:s1+s2; +5;
- 减法运算符或负值运算符,如:s1-s2; -5;
* 乘法运算符,如s1*5;
/ 除法运算符,如s1/5;
% 模运算符,如s1%2;
在进行整数除法时,结果值要略去小数部分。在取模运算时,结果的符号位和模运算第一个操作数的符号位保持一致。例如:运算表达式 结果 说明12.5/3 4 结果为4,小数部分省去12%4 0 整除,余数为0-15%2 -1 结果取第一个数的符号,所以余数为-113/-3 1 结果取第一个数的符号,所以余数为1注意:在进行基本算术运算时,如果某一操作数有不确定的值X,则运算结果也是不确定值X。2. 赋值运算符赋值运算分为连续赋值和过程赋值两种。(1)连续赋值连续赋值语句和过程块一样也是一种行为描述语句,有的文献中将其称为数据流描述形式,但本书将其视为一种行为描述语句。连续赋值语句只能用来对线网型变量进行赋值,而不能对寄存器变量进行赋值,其基本的语法格式为: 线网型变量类型 [线网型变量位宽] 线网型变量名; assign #(延时量) 线网型变量名 = 赋值表达式; 例如: wire a; assign a = 1'b1;一个线网型变量一旦被连续赋值语句赋值之后,赋值语句右端赋值表达式的值将持续对被赋值变量产生连续驱动。只要右端表达式任一个操作数的值发生变化,就会立即触发对被赋值变量的更新操作。在实际使用中,连续赋值语句有下列几种应用:
对标量线网型赋值wire a, b;assign a = b;
对矢量线网型赋值wire [7:0] a, b;assign a = b;
对矢量线网型中的某一位赋值wire [7:0] a, b;assign a[3] = b[1];
对矢量线网型中的某几位赋值wire [7:0] a, b;assign a[3:0] = b[3:0];
对任意拼接的线网型赋值wire a, b;wire [1:0] c;assign c ={a ,b};
(2)过程赋值过程赋值主要用于两种结构化模块(initial模块和always模块)中的赋值语句。在过程块中只能使用过程赋值语句(不能在过程块中出现连续赋值语句),同时过程赋值语句也只能用在过程赋值模块中。过程赋值语句的基本格式为:<被赋值变量><赋值操作符><赋值表达式>其中,<赋值操作符>是“=”或“<=”,它分别代表了阻塞赋值和非阻塞赋值类型。3.5.1节对阻塞赋值和非阻塞赋值操作进行了详细解释。过程赋值语句只能对寄存器类型的变量(reg、integer、real和time)进行操作,经过赋值后,上面这些变量的取值将保持不变,直到另一条赋值语句对变量重新赋值为止。过程赋值操作的具体目标可以是:
reg、integer、real和time型变量(矢量和标量);
上述变量的一位或几位;
上述变量用{}操作符所组成的矢量;
存储器类型,只能对指定地址单元的整个字进行赋值,不能对其中某些位单独赋值。例2-2 给出一个过程赋值的例子。reg c;always @(a) begin c = 1'b0;end
3. 关系运算符关系运算符总共有以下8种:
> 大于
>= 大于等于
< 小于
<= 小于等于
== 逻辑相等
!= 逻辑不相等
=== 实例相等
!== 实例不相等
在进行关系运算符时,如果操作数之间的关系成立,返回值为1;关系不成立,则返回值为0;若某一个操作数的值不定,则关系是模糊的,返回的是不定值X。实例算子“===”和“!==”可以比较含有X和Z的操作数,在模块的功能仿真中有着广泛的应用。所有的关系运算符有着相同优先级,但低于算术运算符的优先级。4. 逻辑运算符Verilog HDL中有3类逻辑运算符:
&& 逻辑与
|| 逻辑或
! 逻辑非
其中“&&”和“||”是二目运算符,要求有两个操作数;而“!”是单目运算符,只要求一个操作数。“&&”和“||”的优先级高于算术运算符。逻辑运算符的真值表如下表所示:
表2-2 逻辑运算符的真值表
5. 条件运算符条件运算符的格式如下: y = x ? a : b; 条件运算符有3个操作数,若第一个操作数y = x是True,算子返回第二个操作数a,否则返回第三个操作数b。 如: wire y; assign y = (s1 == 1) ? a : b; 嵌套的条件运算符可以实现多路选择。如: wire [1:0] s; assign s = (a >=2 ) ? 1 : (a < 0) ? 2: 0; //当a >=2时,s=1;当a <0时,s=2;在其余情况,s=0。6. 位运算符作为一种针对数字电路的硬件描述语言,Verilog HDL用位运算来描述电路信号中的与、或以及非操作,总共有7种位逻辑运算符:
~ 非
& 与
| 或
^ 异或
^~ 同或
~& 与非
~| 或非
位运算符中除了“~”,都是二目运算符。位运算对其自变量的每一位进行操作,例如:s1&s2的含义就是s1和s2的对应位相与。如果两个操作数的长度不相等的话,将会对较短的数高位补零,然后进行对应位运算,使输出结果的长度与位宽较长的操作数长度保持一致。例如:s1 = ~s1;var = ce1 & ce2;7. 移位运算符移位运算符只有两种:“<<”(左移)和“>>”(右移),左移一位相当于乘2,右移一位相当于除2。其使用格式为:s1 << N; 或 s1 >>N其含义是将第一个操作数s1向左(右)移位,所移动的位数由第二个操作数N来决定,且都用0来填补移出的空位。在实际运算中,经常通过不同移位数的组合来计算简单的乘法和除法。例如s1*20,因为20=16+4,所以可以通过s1<<4+s1<<2来实现。8. 拼接运算符拼接运算符可以将两个或更多个信号的某些位并接起来进行运算操作。其使用格式为:{s1, s2, … , sn}将某些信号的某些位详细地列出来,中间用逗号隔开,最后用一个大括号表示一个整体信号。在工程实际中,拼接运算受到了广泛使用,特别是在描述移位寄存器时。例2-3 给出拼接符的Verilog实例reg [15:0] shiftreg;always @( posedge clk)shiftreg [15:0] <= {shiftreg [14:0], data_in};9. 一元约简运算符一元约简运算符是单目运算符,其运算规则类似于位运算符中的与、或、非,但其运算过程不同。约简运算符对单个操作数进行运算,最后返回一位数,其运算过程为:首先将操作数的第一位和第二位进行与、或、非运算;然后再将运算结果和第三位进行与、或、非运算;依次类推直至最后一位。常用的约简运算符的关键字和位操作符关键字一样,仅仅由单目运算和双目运算的区别。例2-4 给出一元简约运算符的Verilog实例reg [3:0] s1;reg s2;s2 = &s1; //&即为一元约简运算符“与”
关键词:
VerilogHDL
语言
数据
类型
运算符
可