1. 操作符概述
操作符(Operators)是VHDL中用于执行特定操作的符号或关键字。操作符可以应用于操作数(Operands),操作数可以是信号、变量、常量、表达式等。操作符的使用使得VHDL代码更简洁、可读性更强,并能够有效地描述硬件行为。
2. 操作符的分类
2.1 算术操作符
算术操作符用于执行数值运算,适用于integer
、unsigned
、signed
等数值类型。
操作符 | 描述 | 示例 | 结果 |
---|---|---|---|
+ | 加法 | A + B | A与B的和 |
- | 减法 | A - B | A减去B |
* | 乘法 | A * B | A与B的积 |
** | 指数 | A ** B | A的B次方 |
/ | 除法(整数除法) | A / B | A除以B的商(取整) |
mod | 取模 | A mod B | A除以B的余数 |
rem | 余数(带符号) | A rem B | A除以B的余数(保留符号) |
abs | 绝对值 | abs(A) | A的绝对值 |
not | 取反(数值类型中通常不使用) | not A | (通常用于逻辑类型) |
(1)+(加)、-(减)
是最常用的算术运算符,适用于INTEGER
、UNSIGNED
和 SIGNED
型数据:在程序包STD_LOGIC_UNSIGNED
和STD_LOGIC_SIGNED
中对+(加)、-(减)的功能做了扩展,使其可适用于STD_LOGIC_VECTOR
型数据。
(2)*(乘)
运算的适用数据类型是INTEGER
,即INTEGER*INTEGER
;在程序包STD_LOGIC_UNSIGNED
中将扩展至STD_LOGIC_VECTOR
型数据,可实现STD_LOGIC_VECTOR*STD_LOGIC_VECTOR
的乘法运算。在可综合的设计中,使用乘法运算符*时应慎重,特别是当操作数位较长时,因为综合后耗用的逻辑门数量会很大。
(3)/(除)
运算的适用数据类型是INTEGER
,除法运算只有当除数是2N2^N2N时才可综合。
(4)MOD(取模)、REM(取余)
运算符适用于整数类型。MOD和REM 的实现依赖除法电路所以其可综合性也与除法运算符相同。
注:MOD(取模)和REM(取余)之间的区别只有在负数的情况下,REM保留被除数的符号而 MOD 取模保留除数的符号。
比如:对于UNSIGNED
型无符号数,MOD(取模)和REM(取余)完全相同,综合后的电路也相同。
3/5 = 0,-9/5 = -1,14/5 = 2
7 REM 3 = 1,-7 REM 3 = -1,5 REM 3 = 2
(-5) REM 3 = -2,5 REM (-3) = 2,(-5) REM (-3) = -2
7 MOD 3 = 1,7 MOD -3 = -2,-7 MOD 3 = 2
5 MOD 3 = 2,(-5) MOD 3 = 1,5 MOD (-3) = -1,(-5) MOD (-3) = -2
(5)**(乘方)和ABS(取绝对值)
运算符适用于整数类型。
对于 Y<=x**a
,当 a=2时可综合;或者当x=2和a为整数时也可综合,其他情况,不可综合。
对于ABS(取绝对值)有:
ABS 5 = 5, ABS -3 = 3
2.2 逻辑操作符
逻辑操作符用于执行布尔逻辑运算,适用于std_logic
、std_logic_vector
以Bit
、Boolean
逻辑类型
操作符 | 描述 | 示例 | 结果 |
---|---|---|---|
and | 与 | A and B | A与B的逻辑与 |
or | 或 | A or B | A与B的逻辑或 |
nand | 与非 | A nand B | 非(A与B) |
nor | 或非 | A nor B | 非(A或B) |
xor | 异或 | A xor B | A与B的逻辑异或 |
xnor | 同或非 | A xnor B | 非(A xor B) |
not | 非 | not A | A的逻辑非 |
注意事项:
(1)逻辑运算符适用的数据类型有BOOLEAN
、BIT
、BITVECTOR
、STD_LOGIC
和STD_LOGIC_VECTOR
等。
(2)逻辑运算符左右两边操作数的数据类型必须相同。
(3)对于数组的逻辑运算来说,要求数组的维数必须相同,其结果也是相同维数的数组。
(4)逻辑运算符中,NOT的优先级最高,其余6种逻辑运算符的优先级相同;当表达式中有多个逻辑运算符时,建议使用括号控制逻辑运算的次序和优先级,防止出现综合错误。
2.3 关系操作符
关系操作符用于比较两个值,返回布尔值(true
或false
)。适用于数值类型和某些逻辑类型。
操作符 | 描述 | 示例 | 结果 |
---|---|---|---|
= | 等于 | A = B | 如果A等于B,则为true |
/= | 不等于 | A /= B | 如果A不等于B,则为true |
< | 小于 | A < B | 如果A小于B,则为true |
<= | 小于或等于 | A <= B | 如果A小于或等于B,则为true |
> | 大于 | A > B | 如果A大于B,则为true |
>= | 大于或等于 | A >= B | 如果A大于或等于B,则为true |
注意事项:
(1)关系运算符为二元运算符,要求运算符左右两边数据的类型必须相同,运算结果为 BOOLEAN型数据(即结果只能为TRUE 或FALSE)。
(2)不同关系运算符对其左右两边操作数的数据类型有不同要求。
其中,等于(=)和不等于(/=)可以适用所有类型的数据。只有当两个数据a和b的数据类型相同,其数值也相等时,“a-b”的运算结果才为 TRUE,“a/=b”的运算结果为FALSE。
其他4种关系运算符(<,<=,>,>=)在程序包STD_LOGIC_UNSIGNED
中做了功能扩展,使其不仅适用于整型(INTEGER)
数据,也适用于STD_LOGIC
和STD_LOGIC_VECTOR
型数据。
(3)在利用关系运算符对STD_LOGIC_VECTOR
型数据进行比较时,比较过程是从最左边的位开始,从左至右按位进行比较。在位长不同的情况下,只能以从左至右的比较结果作为关系运算的结果例如:
SIGNAL a:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL b:STD_LOGIC_VECTOR(2 DOWNTO 0);
a <="1010";
b <="111";
IF(a>b) THEN
上面a和b比较的结果是b比a大,因为位矢量是自左至右按位比较的,由于"111">“101”,因此比较的结果是 b大于 a。
2.4 移位操作符
移位操作符用于将位向量中的位向左或向右移动特定位数。移位操作符包括逻辑左移、逻辑右移、算术右移等。
操作符 | 描述 | 示例 | 结果 |
---|---|---|---|
sll | 逻辑左移(Shift Left Logical) | A sll 2 | 将A 左移2位,右侧填充0 |
srl | 逻辑右移(Shift Right Logical) | A srl 2 | 将A 右移2位,左侧填充0 |
sla | 算术左移(Shift Left Arithmetic) | A sla 2 | 同逻辑左移 |
sra | 算术右移(Shift Right Arithmetic) | A sra 2 | 将A 右移2位,左侧填充符号位 |
rol | 循环左移(Rotate Left) | A rol 1 | 将A 的最高位移至最低位 |
ror | 循环右移(Rotate Right) | A ror 1 | 将A 的最低位移至最高位 |
例如,若x=“01001”,则有:
y <= x SLL 2; -- y <= "00100"(y <= x(2 DOWNTO 0) & "00";)
y <= x SLA 2; -- y <= "00111"(y <= x(2 DOWNTO 0) & x(0) & x(0);)
y <= x SRL 3; -- y <= "00001"(y <= "000" & x(4 DOWNTO 3);)
y <= x SRA 3; -- y <= "00001"(y <= x(4) & x(4) & x(4) & x(4 DOWNTO 3);)
2.5 连接与切片操作符
连接操作符用于将多个位向量或位与信号连接成一个新的位向量。切片操作符用于提取位向量的特定位范围。
连接操作符 (&
)
描述:将两个或多个位向量连接成一个新的位向量。
示例:连接三个单比特信号
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Connector is
Port (
A : in std_logic;
B : in std_logic;
C : in std_logic;
Y : out std_logic_vector(2 downto 0)
);
end Connector;
architecture Behavioral of Connector is
begin
Y <= A & B & C; -- 连接A, B, C成3位向量
end Behavioral;
说明:
A & B & C
将三个单比特信号连接成一个3位向量,赋值给Y
。
切片操作符 (()
)
描述:提取位向量的特定位范围,形成一个新的位向量。
示例:提取高4位和低4位
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity SliceExample is
Port (
data_in : in std_logic_vector(7 downto 0);
upper : out std_logic_vector(7 downto 4);
lower : out std_logic_vector(3 downto 0)
);
end SliceExample;
architecture Behavioral of SliceExample is
begin
upper <= data_in(7 downto 4); -- 提取高4位
lower <= data_in(3 downto 0); -- 提取低4位
end Behavioral;
说明:
data_in(7 downto 4)
提取data_in
的高4位赋值给upper
。data_in(3 downto 0)
提取data_in
的低4位赋值给lower
。
2.6 省略赋值运算符
=>
和OTHERS
可看作是省略赋值运算符,=>
可以给矢量的某几位赋值,OTHERS
则用于给剩余的位赋值。
signal tmp1,tmp2:std_logic_vector(11 downto 0);
tmp1 <= (others => '0'); -- tmp1 <= "0000 0000 0000"
tmp2 <= (0=>'1',3=>'1',others=>'0'); -- tmp2<= "0000 0000 1001"