内容发布更新时间 : 2024/11/15 18:00:00星期一 下面是文章的全部内容请认真阅读。
1.逻辑运算符
在VHDL语言中定义了七种基本的逻辑运算符,它们分别是: AND(与)、OR(或)、NOT(非)、NAND(与非)、NOR(或非)、XOR(异或) 和NXOR(异或非)等。
由逻辑运算符和操作数组成了逻辑表达式。在VHDL语言中,逻辑表达式中的操作数的 数据类型可以是BIT和STD_LOGIC数据类型,也可以是一维数组类型BIT_VECTOR和 STD_LOGIC_VECTOR,要求运算符两边的操作数的数据类型相同、位宽相同。逻辑运算是 按位进行的,运算的结果的数据类型与操作数的数据类型相同。 例如用VHDL描述逻辑表达式是Y=AB,Z=A+B+C的程序如下: ENTITY loga IS
PORT(
A, B, C : IN STD_LOGIC; Y, Z : OUT STD_LOGIC );
END loga;
ARCHITECTURE stra OF loga IS BEGIN
Y<= A AND B; Z <= A OR B OR C;
END stra;
例如用VHDL描述两个位向量的逻辑运算的程序如下: ENTITY logb IS PORT(
A, B : IN BIT_VECTOR(0 TO 3); Y : OUT BIT_VECTOR(0 TO 3) ); END logb;
ARCHITECTURE strb OF logb IS BEGIN
Y<=A AND B;
END strb;
如果A=1011,B=1101,则程序仿真的结果是Y=1001。
在一个逻辑表达式中有两个以上的运算符时,需要用括号对这些运算进行分组。 例如语句
X1 <=(A AND B ) OR (C AND B); X2 <=( A OR B) AND C; 是正确的。
如果一个逻辑表达式中只有AND、OR和XOR三种运算符中的一种运算符,那么改变运 算顺序不会影响电路的逻辑关系,表达式中的括号是可以省略的。例如下列语句是正确的。 Y1 <=A AND B AND C; Y2 <= A OR B OR D; 2.算术运算符
VHDL语言定义了五种常用的算术运算符,分别是 + 加或正, A+B,+A - 减或负, A-B, -B
* 乘, A*B
/ 除, A/B
** 指数, N**2 以及MOD(求模)、REM(取余)、ABS(求绝对值)等算术运算符。
在算术运算表达式中,两个操作数必须具有相同的数据类型,加法和减法的操作数的数 据类型可以是整数、实数或物理量,乘除法的操作数可以是整数或实数。为了节约硬件资源, 除法和乘法的操作数应该选用INTEGER、STD_LOGIC_VECTOR或BIT_VECTOR等数据类型。 例如 X<=A+B;
Y<=C*D; Z<=A-C**2 小提示:
对于 / , MOD, REM运算,要求操作符的右操作数必须为2的正整数次幂,可以用实际电 路移位实现,才可以综合。 3.关系运算符
关系运算符是将两个相同类型的操作数进行数值比较或关系比较,关系运算的结果的
数据类型是TRUE或FALSE,即BOOLEAN类型。VHDL语言中定义了六种关系运算符, 分别是: = 等于 /= 不等于 > 大于 < 小于
>= 大于或等于 <= 小于或等于
在VHDL中,关系运算符的数据类型根据不同的运算符有不同的要求。其中 “=”(等于) 和 “/=”(不等于)操作数的数据类型可以是所有类型的数据,其他关系运算符可以使用整 数类型、实数类型、枚举类型和数组。整数和实数的大小排序方法与数学中的比较大小方法 相同。枚举型数据的大小排序方法与它们的定义顺序一致,例如BIT型数据1>0,BOOLEAN 型数据TRUE>FALSE。
在利用关系运算符对位向量数据进行比较时,比较过程是从左到右的顺序按位进行比较 的,操作数的位宽可以不同,但有时会产生错误的结果。
如果A、B是STD_LOGIC_VECTOR数据类型, A = “1110”,B= “10110”,关系表达式 A>B的比较结果是TRUE,也就是说A>B。对于以上出现的错误可以利用STD_LOGIC_ARITH
程序包中定义的数据类型UNSIGNED来解决,把要比较的操作数定义成UNSIGNED数据类型。
4.移位运算符
VHDL93标准中增加了六个移位运算符,分别是SLL逻辑左移,SRL逻辑右移,SLA算术 左移,SRA算术右移,ROL逻辑循环左移,ROR逻辑循环右移。移位运算符的格式是: 操作数名称 移位运算符 移位位数;
操作数的数据类型可以是BIT_VECTOR、STD_LOGIC_VECTOR等一维数组,也可以是 INTEGER型,移位位数必须是INTEGER型常数。 六条移位运算符所执行的操作如图1-2-1所示。
其中SLL是将位向量左移,右边移空位补零。SLA是将位向量左移,右边第一位的数值 保持原值不变。 SRL是将位向量右移,左边移空位补零。SRA是将位向量右移,左边第一 位的数值保持原值不变。ROR和ROL是自循环移位方式。 例如
A<= “0101”; B <=A SLL 1;
仿真的结果是B = 1010。 5.连接运算符(&)
用连接运算符可以将多个数据对象合并成一个新的一维数组,也可以将两个一维数组中 的元素分解合并成新的一维数组。连接两个操作符产生新的一维数组的位宽等于两个操作 数的位宽之和,新的数组元素的顺序是由操作数的位置决定的,连接符“&”左边的操作数的元素在左,连接符 “&”右边的操作数的元素在右。操作数可以是BIT或STD_LOGIC 如果
1011,0010 A :BIT_VECTOR(0 TO 7) 0001,0110 B :BIT_VECTOR(0 TO 7) C <=B(0 TO 3)&A( 5 TO 7)&.1.; 则C=1011,1101
1.2.4 VHDL的数据对象
在算法语言中,定义了多种数据对象,如常数、变量和数组等,用来存放不同类型的数 据,如整数、实数、复数、逻辑常数和逻辑变量等。在VHDL程序中,常用的数据对象分为三种类型,即常数(CONSTANT)、变量(VARIABLE)和信号(SIGNAL),在使用过 程中,这三种数据对象除了具有一定的数据功能外,还赋予了不同的物理意义,在应用时要 特别注意。
1. 常数(CONSTANT)
常数被赋值后就保持某一固定的值不变。在VHDL中,常数通常用来表示计数器的模的 大小、数组数据的位宽和循环计数次数等,也可以表示电源电压值的大小。常数的使用范围 与其在设计程序中的位置有关,如果常数在结构体中赋值,则这个常数可供整个设计单元使 用,属于全局量,如果常数在PROCESS语句或子程序中赋值,只能供进程或子程序使用, 属于局部量。程序设计中使用常数有利于提高程序的可读性和方便对程序进行修改。通常常 数的赋值在程序开始前进行,其数据类型在常数说明语句中指明,赋值符号为 “:=”。 常数定义语句的格式为:
CONSTANT 常数名称:数据类型 := 表达式 例如:
CONSTANT Vcc: REAL := 5.0;
CONSTANT DALY : TIME := 20ns;
CONSTANT KN : INTEGER := 60;
在上面的例子中,Vcc的数据类型是实数,被赋值为5.0,DALY被赋值为时间常数20ns, KN被赋值为60的整数。
注意:常数所赋的值的数据类型必须与定义的数据类型一致,在程序中常数被赋值后不能 再改变。
2.变量(VARIABLE)
在VHDL程序中,变量只能在进程和子程序中定义和使用,不能在进程外部定义使用, 变量属于局部量,在进程内部主要用来暂存数据。对变量操作有变量定义语句和变量赋值 语句,变量在赋值前必须通过定义,可以在变量定义语句中赋初值,变量初值不是必需的, 变量初值的赋值的符号是“ :=”。 小提示:
变量与信号赋初值语句仅可用于仿真,在综合时被忽略,不起作用。 变量定义语句的格式为:
VARABLE 变量名称:数据类型 := 初值; 例如:
VARABLE S1 :INTEGER := 0 ; VARABLE S2, S3 :INTEGER
VARABLE CON1 :INTEGER RANGER 0 TO 20 ;
VARABLE D1, D2 :STD_LOGIC ;
S1是整数型变量、初值是0;CON1是整数型变量,其变化范围是0到20;D1,D2是一 位标准逻辑位型变量。 变量赋值语句的格式为: 变量名称 := 表达式 ;
在对变量进行赋值时,要求表达式的数据类型必须与变量定义语句中的数据类型一致, 表达式的数据对象可以是常数、变量和信号。变量赋值是立即发生的,没有任何时间延迟 的,所以变量只有当前值,并且对同一个变量可以多次赋予新值。多个变量的赋值是根据 赋值语句在程序中的书写位置,按照自上而下顺序进行的,所以变量赋值语句属于顺序执 行语句。变量不能放在进程的敏感信号表中。 例如:
PROCESS(D, E)
VARIABLE AV, BV, CV :INTEGER := 0 ; BEGIN AV := 1 ; BV := AV + D ; AV := E + 2 ; CV := AV * 2 ; A <= AV ; B <= BV ; C <= CV ;
END PROCESS ;
这是一个进程语句,定义AV,BV,CV是整数型变量,当敏感信号D,E只要有一个发 生变化,放在进程中的语句就要全部执行一次,如D = 1,E 变化为 2,则这段程序的执行 结果是:A = 4,B =2,C = 8。
3. 信号(SIGNAL)
在VHDL中,信号分为外部端口信号和内部信号,外部端口信号是设计单元电路的引脚, 在程序实体中定义,外部信号对应四种I/O状态是IN,OUT,INOUT,BUFFER等,其作用是在设计单元电路之间起互连作用,外部信号可以供整个设计单元使用属于全局量。例如在结构体中,外部信号可以直接使用,不需要加以说明,可以通过信号赋值语句给外部输出信号赋值。 小提示:
内部信号是用来描述设计单元内部的传输信号,它除了没有外部信号的流动方向之外, 其它性质与外部信号一致。
内部信号的使用范围(可见性)与其在设计程序中的位置有关,内部信号可以在包体、 结构体和块语句中定义,如果信号在结构体中定义,则可以在供整个结构体中使用,如果在 块语句中定义的信号,只能供块内使用,不能在进程和子程序中定义内部信号。信号在状态 机中表示状态变量。
对内部信号操作有信号定义语句和信号赋值语句,内部信号在赋值前必须通过定义, 可以在信号定义语句中赋初值,内部信号初值不是必需的,内部信号的定义格式与变量的 定义格式基本相同,只要将变量定义中的保留字VARIABLE换成SIGNAL即可。 内部信号定义语句的格式为:
SIGNAL 信号名称:数据类型 := 初值; 例如:
SIGNAL S1 :STD_LOGIC := .0. ;
SIGNAL D1 :STD_LOGIC _VECTOR(3 DOWNTO 0):= “1001” ;
定义信号S1是标准逻辑位型,初值是逻辑0 ;信号D1是标准逻辑位向量,初值是逻 辑向量1001。
信号赋值符号与变量赋值符号不同,信号赋值符号为 “ <=”。 小提示:
对于赋值语句还可以采用如下格式:
SIGNAL VEC1,VEC2: BIT_VECTOR( 3 DOWNTO 0);
VEC1<=( 0=>.1. OTHERS=> .0.);-- 表示判别性的整集内涵赋值,VEC的第三位为1,其 余为0
VEC2 (1 TO 2)<=”10”; --对VEC2部分位赋值 信号赋值语句的格式为: 信号名称 <= 表达式;
在对信号进行赋值时,表达式的数据对象可以是常数、变量和信号,但是要求表达式
的数据类型必须与信号定义语句中的数据类型一致。在结构体中信号的赋值可以在进程中 也可以在进程外,但两者的赋值方式是不同的。在进程外,信号的赋值是并行执行的,所 以被称之为并行信号赋值语句。在进程内,信号的赋值方式具有特殊性。
信号不能在进程中定义,但可以在进程中赋值。在进程中,变量赋值是立即起作用的, 信号只有在进程被激活(敏感信号发生变化)后,在进程结束时才能赋予新的值。信号具 有时间特性,信号赋值不是立即发生的,需要经过固有的时间延迟,所以信号具有过去值 和当前发生值,这与实际电路的特性是一致的。信号的赋值过程分为顺序处理和并行赋值 两个阶段。顺序处理是按照自上而下的顺序,用信号原来的值对所有的表达式进行运算, 运算结果不影响下一个表达式的运算,直到处理好进程中的最后一个表达式。并行赋值是 把表达式的值并行同时赋给信号。整个过程是一个无限循环的过程,循环停止的条件是敏 感信号保持不变,所以在进程中的信号赋值语句属于顺序执行语句。在进程之外的信号赋