VHDL概述
VHDL概述
实体说明
不论是简单的数字电路还是一个微处理器或者系统,都由实体构成,实体的结构
ENTITY 实体名 IS
[类属参数说明];
[端口说明];
END ENTITY 实体名
以上就是一个基本设计单元的实体说明
类属参数说明
必须放在端口说明之前,用于指定参数
端口说明
端口说明是对基本设计实体(单元)与外部接口的描述, 书写格式的描述
PORT(端口名{, 端口名}:方向 数据类型名;
……
端口名{, 端口名}:方向 数据类型名;
);
端口名
一般是赋予外部引脚的名称,为英文字母加数字
端口方向
用BUFFER时与该端口连接的另外一个元器件的端口也要用BUFFER说明,而OUT则没有此要求
顺序语句
与书写顺序有关,只能出现在进程、过程、函数中
变量赋值语句
格式:[variable]目标变量名[: 数据类型]: = 表达式
variable a,b: std_logic
a:='1';
b:='0';
注: 变量是局部的,暂时性的数据对象,变量的赋值立即生效
std_logic
std_logic是长度为1的逻辑 与bit 相似,只是bit只能是'0 ’和'1‘ 而std_logic有以下九种状态:
'U'——初始值, 'X'——不定,
‘0’——0, '1'——1,
‘Z’——高阻, 'W'——弱信号不定,
‘L’——弱信号0, 'H'——弱信号1,
'-'——不可能的情况
单元素赋值
VARIABLE a, b: STD_LOGIC;
VARIABLE x,y:INTEGER RANGE 15 DOWNTO 0;
a:='1';
b:='0';
x:=11;
y:=2+x;
注意: signal e:integer range 0 to 8; 是不是指随便怎么编,e的...答:e的取值只能是0 1 2 3 4 5 6 7 8 超过8会自动返回到0,
数组赋值
数组元素赋值目标的表示格式
单个元素:标识符(下标名) 比如 b(5)
多个元素:标识符(下标1 to / downto 下标2)
VARIABLE a,b:STD_LOGIC_VECTOR(7 DOWNTO 0);
b(7 DOWNTO 0):=“10110010”;
a:=b;
VARIABLE a,b : STD_LOGIC_VECTOR (1 TO 4);
b(1 TO 4):="1011";
a(1 TO 2):=b(3 TO 4);
信号赋值语句
格式:目标信号名 <= 表达式[after时间量]
注: 信号的赋值时有延时性的,信号量是全局量
SIGNAL y,z : STD_LOGIC;
SIGNAL a,b :STD_LOGIC_VECTOR(0 TO 3);
a <= "1010";
b <= "1000";
y <= a(1);
z <= b(3);
STD_LOGIC_VECTOR
是数组
延时性举例
PROCESS ( a, b, c, d ) BEGIN d<=a; x <= c XOR d; d<=b; y <= c XOR d; END PROCESS;
x <= c XOR b;
y <= c XOR b;
IF语句
IF 条件 THEN
顺序处理语句;
ENDIF
# 二选一
IF 条件 THEN
顺序处理语句1;
ELSE
顺序处理语句2;
ENDIF
# 多路选择
IF 条件1 THEN
顺序处理语句1;
ELSIF 条件2 THEN
顺序处理语句2;
……
ELSE
顺序处理语句x;
ENDIF
示例
IF sel='1'THEN
c<=a;
ELSE
c<=b;
END IF;
case 语句
CASE 表达式 IS
WHEN 选择值=>顺序语句1;
WHEN 选择值=>顺序语句2;
【WHEN OTHERS=>顺序语句n】;
END CASE
注意:IF语句是具有优先级;case语句没有优先级,必须穷举尽
loop语句
无限loop
[标号]:LOOP
顺序处理语句;
END LOOP[标号];
无线循环功能,只有通过控制转向语句才可退出循环。
示例
L2:LOOP
A:=A+1;
EXIT L2 WHEN A>10;
END LOOP L2
for loop
[标号]:FOR 循环变量 IN 循环次数范围 LOOP
顺序处理语句;
END LOOP[标号];
实现循环功能,每次循环时变量在范围内变化一次。循环变量不用事先说明,但不能含有信号和变量。
while loop
[标号]:WHILE 循环条件 LOOP
顺序处理语句;
END LOOP[标号];
若条件为真,则进行循环;若条件为假则结束循环
next 语句
-
NEXT
无条件终止当 前循环,跳回到本次循环LOOP语句处,开始下一次循环。
-
NEXT LOOP
标号表明下一次循环的起始位置。当有多重LOOP语句嵌套时,可以跳转到指定标号的LOOP语句处,重新开始执行循环操作。
-
NEXT LOOP标号WHEN条件表达式
如果条件表达式的值为TRUE,则执行NEXT语句,否,则循环正常继续。
exit 语句
- exit
- exit loop
- exit loop 标号 when 条件表达式
wait语句
-
wait 无线等待
-
wait on 敏感信号变化是结束挂起
PROCESS BEGIN Y<=a AND b; WAIT ON a, b; -- 当a,b任一信号变化时发生变化时,结束挂起,继续执行之后的语句 END PROCESS;
-
wait until 布尔表达式 条件满足时结束挂起
表达式方式
信号=VALUE; 信号’EVENT AND 信号=VALUE; NOT信号’STABLE AND 信号=VALUE;
-
wait for 表达式 时间到时结束挂起
当执行到该语句时,进程被挂起,直到指定的时间到,结束挂起,继续执行后面的语句。
-
多条WAIT语句
指WAIT语句可以使用多个等待条件,只要一个或多个满足,则结束挂起。
-
超时等待处理
为防止“死锁”增加的超时处理语句。常与断言语句合用。
子程序调用语句
子程序包括过程和函数,子程序可以在结构体或程序包的任何位置被调用
-
过程调用格式
过程名(参数表 );=
-
函数调用格式
函数名(参数表);
-
过程和函数的区别
过程的参数可以是IN、INOUT或OUT模式,而函数只能是IN模式。
函数调用返回一个指定类型的值,过程没有。
return
子程序返回。当“表达式”缺省时,只能用于过程;当有“表达式”时,只能用于函数,并且必须返回一个值。
RETURE [表达式];
null语句
空操作
格式: NULL;
预定义属性描述语句
属性:是关于实体、结构体、类型、信号、变量等项目的一些特征。属性可通过一个值或一个表达式表示。
属性描述语句作用:实现对项目的特性进行检测或统计。
预定义属性描述语句的格式:项目名’属性标识符
格式 | 含义 |
---|---|
信号’event | 在一段时间内若有信号事件发生则返回“true”,反之,返回“false”。 |
信号’active | 在一段时间内若信号活跃则返回“true”,反之,返回“false”。 |
信号’last_event | 返回信号从前一个事件发生到现在时刻所经历的时间值; |
信号’last_value | 返回信号在最近一个事件发生以前的值; |
信号’last_active | 返回信号从前一次信号活跃到现在时刻所经历的时间值; |
信号’STABLE[t] | 在时间t内若没有事件发生则返回“true”的布尔信号,反之,返回“false”的布尔信号。 |
[示例]
-- 检查时钟信号clk上升沿方式:
clk‘EVENT AND clk=‘1’;
NOTclk‘STABLE AND clk=‘1’;
-- 检查脉冲宽度方式
(falling_edge(clk)) AND (clk'LAST_EVENT>=10 ns); ---最小正脉冲宽度检查
( rising_edge(clk)) AND (clk'LAST_EVENT>=10ns); --最小负脉冲宽度检查
并行语句
语句的执行与书写顺序无关。各并行语句之间可以通过信号交换信息或相互独立。
每个并行语句代表一个功能单元,一个或多个功能单元组成一个结构体。
进程语句(PROCESS)
PROCESS语句格式:
[进程名]:PROCESS[(敏感信号参数)]
[变量说明语句;]
BEGIN
顺序描述语句;
END PROCESS[标号];
PROCESS内部语句为顺序执行语句 ,但进程本身是并发语句。
进程在敏感信号变化时触发执行,也可以用WAIT等待语句实现触发。
但需要注意,在进程语句中,敏感信号表和WAIT语句不能共同存在于一个进程之中。
-
不含敏感信号表的进程
ARCHITECTURE ART OF STAT IS BEGIN P1:PROCESS BEGIN WAIT UNTIL CLOCK; IF(DRIVER=‘1’)THEN CASE OUTPUT IS WHEN S1=>OUTPUT<=S2; WHEN S2=>OUTPUT<=S3; WHEN S3=>OUTPUT<=S4 WHEN S4=>OUTPUT<=S1; END CASE; END IF; END PROCESS P1; END ART;
-
含敏感信号表的进程
-
同步进程的敏感信号表中只有时钟信号
PROCESS(CLOCK) BEGIN IF(CLOCK’EVENT AND CLOCK=‘1’ ) THEN IF RESET=‘1’ THEN DATA<=“00”; ELSE DATA<=IN_DATA; END IF; END IF; END PROCESS;
-
异步进程的敏感信号表中除时钟信号外还有其他信号
PROCESS(CLK,RESET) BEGIN IF RESET=‘1’ THEN DATA<=“00”; ELSE IF CLK’EVENT AND CLK=‘1’ THEN DATA<=IN_DATA; END IF; END IF; END PROCESS;
-
并发信号赋值语句
简单信号赋值语句
格式:赋值目标 <= 信号量表达式;
当右边值发生变化时完成代入功能。
在进程之外执行语句,等效于一个进程的缩写。
ARCHITECTURE behave OF a_bar IS
BEGIN
output <= a;
END behave;
-- 等价于
ARCHITECTURE behave OF a_bar IS
BEGIN
PROCESS(a,)
output <= a;
END PROCESS;
END behave;
并发信号赋值语句
简单信号赋值语句
格式:赋值目标 <= 信号量表达式;
当右边值发生变化时完成代入功能。
在进程之外执行语句,等效于一个进程的缩写。
ARCHITECTURE behave OF a_bar IS
BEGIN
output <= a;
END behave;
-- 等价于
ARCHITECTURE behave OF a_bar IS
BEGIN
PROCESS(a,)
output <= a;
END PROCESS;
END behave;
条件赋值语句
格式: 赋值目标 <= 表达式1 WHEN 条件1 ELSE
表达式2 WHEN 条件2 ELSE
……
表达式n;
当条件满足时代入表达式值,当以上n-1个条件都不满足时,将表达式n的值代入目的信号量。
条件有优先级。
示例
Signal s: integer;
s <= 0 WHEN a='0‘ AND b='0' ELSE
1 WHEN a=' 1’ AND b='0' ELSE
2 WHEN a='0‘ AND b=' 1' ELSE
3 WHEN a=' 1’ AND b=' 1' ELSE
4;
选择信号带入语句
格式: WITH 选择表达式 SELECT
赋值目标 <= 表达式1 WHEN 选择值1 ,
表达式2 WHEN 选择值2,
…… 表达式n WHEN 选择值n;
[表达式 WHEN OTHERS]
根据表达式值,代入相应的信号量。
选择值没有优先级。
示例
Signal s: integer;
WITH s SELECT
y <= d0 WHEN 0,
d1 WHEN 1
d2 WHEN 2,
d3 WHEN 3,
‘X’ WHEN OTHERS;
元件例化语句
元件例化是将预先设计好的设计实体作为一个元件,然后利用特定的语句将此元件与当前的设计实体中的指定端口相连接,从而为当前设计实体引入一个新的低一级的设计层次。
元件声明语句
格式:
COMPONENT 例化元件名 IS
[GENERIC(参数表);]
PORT(端口名表);
END COMPONENT;
描述一个元件的外观,与实体的外观相同。
元件例化语句
格式
例化名: 例化元件名
[GENERIC MAP(参数表)]
PORT MAP ([端口名称=>]连接端口名
{,([端口名称=>]连接端口名});
例化名是必须存在的,表示当前系统的插座名,例化元件名是在元件说明语句中声明过的元件。
连接端口名是当前的实体的信号名,它们与例化元件端口名之间的连接方式有二种:
名称关联:用“=〉”将端口名与信号名一一对应。
位置关联:只写连接端口名,但顺序必须与例化元件一致。
【例子】——4位移位寄存器设计。
-- 先设计一位寄存器
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY dff IS
PORT(d,clk : IN std_logic ;
q: OUT std_logic );
END dff;
ARCHITECTURE bhv OF dff IS
BEGIN
PROCESS(clk)
BEGIN
IF clk’EVENT AND clk =‘1’
THEN q<=d;
END IF
END PROCESS;
END bhv;
-- 再设计4位移位寄存器。
ENTITY shifter_register IS
PORT(a,clk : IN std_logic ;
b: OUT std_logic );
END shifter_register;
ARCHITECTURE four_bit_shift_register OF shifte_register IS
COMPONENT dff
PORT(d,clk:IN std_logic;
q: OUT std_logic);
END COMPONENT;
SIGNAL x: std_logic_vector(0 TO 4);
BEGIN
x(0) <= a;
dff1: dff PORT MAP(x(0),clk,x(1)); 位置映射
dff2: dff PORT MAP(x(1),clk,x(2));
dff3: dff PORT MAP(d=>x(2),clk=>clk,q=>x(3)); 名称映射
dff4: dff PORT MAP(x(3),clk,q=>x(4)); 混合映射
b <= x (4);
END four_bit_shift_register;
块语句
块标号: BLOCK 【(块保护表达式)】
[接口说明、类属说明]
BEGIN
并发语句 ……END BLOCK 块标号;
块的作用是将结构体进行分块组合,以增强结构体的可读性。
BLOCK内语句为并发语句。
ENTITY half IS
PORT(a,b:IN BIT;
s,c:OUT BIT);
END ENTITY half;
ARCHITECTURE adder1 OF half IS --结构体1的名字为adder1
BEGIN
s<=a XOR b;
c<=a AND b;
END adder1;
ARCHITECTURE adder2 OF half IS --结构体2的名字为adder2
BEGIN
Example:BLOCK --块名为example
PORT(a,b:IN BIT; --端口接口说明语句
s,c:OUT BIT);
PORT MAP(a,b,s,c); --信号的映射
BEGIN
P1:PROCESS(a,b)
BEGIN
s<=a XOR b;
END PROCESS P1;
P2:PROCESS(a,b)
BEGIN
c<=a AND b;
END PROCESS P2;
END BLOCK example;
END adder2;
四、VHDL语言要素
文字规则
数字型文字
整数文字:由数字和下划线(代分割符)组成;
如:2,15E2(=1500),45_234_287。
实数文字:由数字、小数点和下划线(代分割符)组成;
如:188.993,88_551.909。
不同进制文字:由数字基数和#号组成;
如:10#170#、16#fe#、2#11010001#
物理量文字:由数字和物理量单位组成。
如:60s,100m
字符串文字
字符:由单引号括起来的ASCII码字符,由数字、字母和符号组成。
如:’a’、’1’
字符串:文字字符串:由双引号括起来的一维字符数组。
如:“abc”、 “10b10”;
数值字符串(位矢量):由数值进制基数符号(B/O/X/)与数值字符组成。
如:B”10101111”、X”FEA”(暂未找到材料)-- B代表二进制、O代表八进制、X代表十六进制
标识符
即操作符号,用以定义常数、变量、信号、端口、子程序或参数的名字。VHDL标识符规则
- 基本的标识符由字母、数字、
- 下划线组成;
- 第一个字符必须为英文字母;英文不区分大小写,不能有空格;
- 不能与VHDL的保留字,关键字相同;
- 最后一个字符不能是下划线;
- 不允许连续2个下划线;
- 允许包含图形符号(如回车符、换行符等)。
下标名
指示数组型变量或信号的某一元素。
格式:标识符(表达式)。示例: a(1)
下标段名
指示数组型变量或信号的某一段元素。
格式:标识符(表达式 1[TO/DOWNTO 表达式2]),
TO 表示下标序号由低到高;
DOWNTO 表示下标序号由高到低;
如:SIGNAL a : bit_vector(0 to 7)
则a(3)表示a中第4个元素
a(4 to 7) 表示 a 中第5到8个元素。
数据对象
指可以存放数据的容器。 分成常数、变量、信号
对象 | 物理含义 | 使用场合 |
---|---|---|
常数 | 指不会发生变化的值,全局量。只能赋值一次 | 下面场合均适用 |
变量 | 用于对暂时数据的局部存储;只能用于进程和子程序中; 变量的赋值立即生效. |
PROCESS FUNCTION PROCEDURE |
信号 | 硬件连接线; 信号是全局量; 信号赋值具有延时性. |
ARCHITECTURE PACKAGE ENTITY |
定义格式
对象 | 声明语句格式 | 例 |
---|---|---|
常数 | CONSTANT 常数名:数据类型[:=表达式]; 常数只能赋一次值。 |
CONSTANT Vcc:real: =5.0v |
变量 | VARIABLE 变量名:数据类型 [约束条件:=初始值]; 赋值符号 ==: === 变量赋值时不能附加延时. |
VARIABLE count: INTEGER RANGE 0 TO 255:=10 |
信号 | SIGNAL 信号名:数据类型[约束条件:初始值]; 信号赋值称为”代入”,符号:<= 信号赋值时可以附加延时. |
SIGNAL sys_clk: BIT <=‘0’; |
变量和信号的区别
- 信号赋值至少有△延迟(可为0延迟),而变量赋值没有延迟。
- 信号除当前值之外,还有许多相关信息,而变量只有当前值。
- 信号可以是多个进程的全局信号,而变量只在定义它们的顺序域(进程、子程序)内出现。
- 进程对信号敏感,而不对变量敏感。
- 信号是硬件中连线的抽象描述,而变量中无类似的对应关系。
- 赋值的符号不同。
数据类型
数据类型(符号) | 含 义(取值范围) |
---|---|
布尔量(Boolean) | 逻辑“假”或逻辑‘‘真” |
位(Bit) | 位数据.只能取值“0”或“1” |
位矢量(Bit_vector) | 位类型的数组.用双引号括起来的一组位数据 |
字符(Character) | ASCII字符,用单引号括起来. |
整数(Integer) | 32位整数。范围-(231-1)~(231-1) |
自然数(Natural) 正整数(Positive) | 自然数:大于等于0的整数 正整数,大于0的整数 |
*实数(Real) | 浮点数.范围:-1.0E+38~+1.0E+38 |
字符串(String) | 用双引号括起来的一个字符序列. |
*时间(Time) | 物理类型,由整数和物理单位组成,如:fs,ps,ns,us,ms,sec,min,hr |
*错误等级 (Severity Level) | 系统状态,有4种:NOTE,WARNINC,ERROR,FAILURE |
用户自定义的数据类型
定义格式:
TYPE 数据类型名 IS 数据类型定义[OF 基本数据类型]
常见自定义数据类型
枚举类型
定义:一组以列表形式给出的适合于特定操作所需要的二进制值,即状态符号化。
定义格式:
TYPE 枚举数据类型名 IS(元素,元素,……);
特点:元素有顺序性.
例:枚举类型定义
TYPE year IS (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec);
SIGNAL thismonth:year;
result <=‘1’ WHEN thismonth >= Sep ELSE ‘0’;整数类型、实数类型
定义格式:
TYPE 数据类型名 IS 数据类型定义 约束范围;
例:
TYPE digit IS INTEGER RANGE 0 TO 9;数组类型
定义格式:
TYPE 数据类型名 IS ARRAY(下标范围) OF 数据类型;
例:
TYPE matrix IS ARRAY(1 TO 8) OF REAL;
IEEE 预定义的标准数据类型
(定义在STD_LOGIC_1164中)
STD_LOGIC:标准逻辑位数据类型,是对BIT的扩展.数据可以有9种取值:
- ‘U’-末初始化值
- ‘X’-强未知
- ‘0’-强0
- ‘1’-强1
- ‘Z’-高阻
- ‘W’-弱未知
- ‘L’-弱信号0
- ‘H’-弱信号1
- ‘-’-不可能情况,忽略
数据字符必须大写。
STD_LOGIC_VECTOR:标准逻辑矢量数据类型,是一维数组为STD_LOGIC的非限制型数组。
操作符
类型 | 操作符 | 功能 |
---|---|---|
混合 | ABS | 取绝对值 |
** | 指数 | |
求积 | REM | 取余 |
MOD | 求模 | |
/ | 除 | |
* | 乘 | |
符号 | - | 负 |
+ | 正 | |
求和 | & | 并置 |
- | 减 | |
+ | 加 | |
移位 | sll、srl、sla、sra、rol、ror | |
关系 | >= | 大于等于 |
<= | 小于等于 | |
> | 大于 | |
< | 小于 | |
/= | 不等号 | |
= | 等号 | |
逻辑 | XNOR | 逻辑异或非 |
NOT | 取反 | |
XOR | 逻辑异或 | |
NOR | 逻辑或非 | |
NAND | 逻辑与非 | |
OR | 逻辑或 | |
AND | 逻辑与 |
五、子程序
特点
可被反复调用,且每次调用将产生同一个电路模块。
子程序内语句为顺序执行语句。
子程序可以在程序包、结构体和进程中定义。只有在程序包中定义的子程序可以被其他不同的设计调用。子程序类型
- 函数(FUNCTION)
- 过程(PROCEDURE)
过程与函数的区别
过程的参数可以是IN、INOUT或OUT模式,而函数只能是IN模式。
函数调用返回一个指定类型的值,过程没有。
函数定义格式
-
函数首格式
FUNCTION 函数名 (参数表) RETURN 数据类型
-
函数体格式
FUNCTION 函数名 (参数表) RETURN 数据类型名 IS [说明语句] BEGIN [顺序处理语句] RETURN [返回变量名] END 函数名;
若函数定义在结构体中,则不需函数首定义;若函数定义在程序包中,函数首定义需放在程序包的说明部分。
示例
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY TEST IS
PORT(IN1,IN2:IN STD_LOGIC;
OUT1:OUT STD_LOGIC);
END TEST;
ARCHITECTURE EXAMPLE OF TEST IS
FUNCTION RISING_EDGE(SIGNAL S:STD_LOGIC) RETURN BOOLEAN IS
BEGIN
IF (S’EVENT) AND (S=’1’) AND (S’LAST_VALUE=’0’) THEN
RETURN TRUE;
ELSE
RETURN FALSE;
END IF;
END RISING_EDGE;
BEGIN
PROCESS(IN2)
BEGIN
IF RISING_EDGE(IN2) THEN
OUT1<=IN1;
END IF;
END PROCESS;
END EXAMPLE
过程定义格式
-
过程定义格式
PROCEDURE 过程名 (参数表);
-
过程体格式
PROCEDURE 过程名 (参数表)IS [说明语句] BEGIN [顺序处理语句] END 过程名;
- 过程调用语句在结构体的进程内部执行时,它是一种顺序语句;在结构体的进程之外执行时,它以并发语句的形式出现。
- 过程参数可以对常数、信号和变量三类对象作出说明,并用关键词IN和OUT、INOUT定义信息的流向。
- 若过程调用中将OUT或者INOUT作为信号使用,在定义时要指明。
- 变量参数不能出现在并发过程调用语句中。
示例——计算八个整数的平均值
PACKAGE PAK IS
TYPE BUS_START_V IS ARRAY (0 TO 7) OF INTEGER;
TYPE BUS_START_T IS
RECORD
BUS_VAL:BUS_START_V;
AVERAGE_VAL:INTEGER;
END RECORD;
PROCEDURE BUS_AVERAGE( X:INOUT BUS_START_T);
END PAK;
PACKAGE BODY PAK IS
PROCEDURE BUS_AVERAGE( X:INOUT BUS_START_T) IS
VARIABLE TOTAL: INTEGER:=0;
BEGIN
FOR i 0 TO 7 LOOP
TOTAL := TOTAL + X.BUS_VAL(i);
END LOOP;
X.AVERAGE_VAL := TOTAL/8;
END BUS_AVERAGE;
END PAK;
-- 下面为调用过程的进程:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE.WORK.PAK.ALL;
ENTITY IS
……
END
ARCHITECTURE
SIGNAL AVERAGE:INTEGER;
……
PROCESS(MEM_UPDATE)
VARIABLE BUS_STATISTICS: BUS_START_T;
BEGIN
BUS_STATISTICS.BUS_VAL:=(50,50,30,35,45,55,65,85);
BUS_AVERAGE(BUS_STATISTICS);
AVERAGE<=BUS_STATISTICS.AVERAGE_VAL;
END PROCESS;
杂
- S<=S1&S2; 中 & 是连接操作
- ARCHITECTURE 代表结构体