实体和结构体是最基本的构成部分,实体可以是一个简单的门电路,例如三态缓冲器、与门、或门等基本门电路;也可以是一个复杂的数字系统,例如微处理器。实体由实体说明和结构体说明两部分组成。实体说明定义了系统硬件的输入输出端口,以及与外部的接口信号。在实体说明中并不包括输入输出之间的逻辑关系,故实体说明所定义的只是一个具有接口信息的黑盒子。黑盒子内的系统功能由结构体定义。
Entity()实体
Entity 实体名 is
PORT(端口名1,端口名N:方向:类型)
[端口说明]
End Entity;
Port的方向有: IN , OUT, INOUT, BUFFER, LINKAGE
**In** 信号只能被引用,不能被赋值;不可以出现在<= 或 : = 的左边
**out** 信号只能被赋值,不能被引用;不可以出现在<= 或 : = 的右边
**buffer** 信号可以被引用,也可以被赋值;可以出现在<= 或 : = 的两边
Tips: OUT 和BUFFER的区别:
Arcthitecture()构造体
Arcthitecture 构造体名 **of** 实体名 **is**
[定义语句] 内部信号、常数、元件、数据类型、函数等的定义
**begin**
[并行处理语句和block、process、function、procedure],内部互连关系,并发执行,结果与先后顺序无关。
**end** 构造体名;
例如:
下面让我们来看一看如何将一个实体(FULLADD)构造为一个内部能实现功能的构造体(STRUCT):
其他设计单元
除了entity(实体)和architecture(构造体)外还有另外三个可以独立进行编译的设计单元
Package(包集合)属于库结构的一个层次,存放信号定义、常数定义、数据类型、元件语句、函数定义和过程定义。
Package Body: 具有独立对端口(port)的package
**configuration(**配置)描述层与层之间的连接关系以及实体与构造体之间关系
Library(库)
库: 数据的集合。内含各类包定义、实体、构造体等
STD库 --VHDL的标准库
IEEE库 – VHDL的标准库的扩展
面向ASIC的库 --不同的工艺
不同公司自定义的库
普通用户自己的库 --当VHDL文件被编译后,编译的结果储存在特定的目录下,这个目录的逻辑名称即Library,此目录下的内容亦即是这个Library的内容。
Package(包)
程序包是一个可编译的VHDL源设计单元,用户和厂商都可以编写。程序包是库的一个层次,将常用的相关说明(例如类型说明、常量说明、子程序说明、元件说明、属性说明等)搜集在一起,一旦编译后存入库中,就可以通过USE语句调用。对STD库中集合包STANDARD的调用不需要USE语句。USE语句中的ALL表示该集合包中的所有项目;USE语句也可以指定具体的项目。程序包由两部分组成:程序包说明和程序包体。
程序包体的主要任务是定义常量的值。
**程序包说明包括:** **程序包体说明部分包括:**
USE语句 USE语句
属性说明 子程序说明
子程序说明 子程序体说明
类型、子类型说明 类型、子类型说明
常量、时间常量说明 常量说明
信号说明,建立一个全局信号 元件说明
元件说明
文件说明
(对客观实体的抽象和概括,可以被赋予值。)有:
Constant(常量)在程序中不可以被赋值,只能在被说明时被赋值,器件工作期间不变化。
CONSTANT常量名:数据类型∶= 标达式;
CONSTANT Vcc:REAL∶=5.0;
Variable(变量)在程序中可以被赋值(用": ="),赋值后立即变化为新值。
VARIABLE变量名:数据类型 约束条件∶= 表达式;
VARIABLE x:STD_LOGIC ∶=‘0';
VARIABLE a, b :INTEGER;
VARIABLE count:INTEGER RANGE 0 TO 255∶=10; --变量值的范围为0~255,初值为10。
Signal(信号)在程序可以被赋值(用"<=") ,但不立即更新,进程挂起后,才开始更新。
SIGNAL信号名:数据类型 约束条件∶= 表达式;
SIGNAL clk:BIT∶=‘0';
SIGNAL bus_a:STD_LOGIC_VECTOR(7 DOWNTO 0);
SIGNAL bus_b :STD_LOGIC_VECTOR(0 DOWNTO 7);
在VHDL语言中,信号是全局量。信号在一个设计之内提供全局通信,在结构设计中用来连结元件,实现元件间的通信;信号也在进程间传递信息,完成进程间的通信。
FILE(文件),文件类型是VHDL-93标准中增加的。
注意:
1、variable只能定义在process和subprogram(包括function和procedure)中,不可定以在其外部。
2、signal不能定义在process和subprogram(包括function和procedure)中,只可定以在其外部。
对象的属性(类似于其它面向对象的编程语言如VB、VC、DELPHI):
用法格式:对象 ’ 属性
例子:clk’event --表明信号clk的event属性
常用的属性:
Signal 对象的常用属性有:
event : 返回boolean值,信号发生变化时返回true
last_value:返回信号发生此次变化前的值
last_event:返回上一次信号发生变化到现在变化的间隔时间
delayed[(时延值)]: 使信号产生固定时间的延时并返回
stable[(时延值)]: 返回boolean, 信号在规定时间内没有变化返回true
transaction: 返回bit类型,信号每发生一次变化,返回值翻转一次
例子:A<=B’delayed(10 ns); --B延时10ns后赋给A;
if(B’Stable(10 ns)); --判断B在10ns中是否发生变化
应用:
信号的event和last_value属性经常用来确定信号的边沿
例子:
判断clk的上升沿
if ( (clk’event)and (clk=‘1’) and(clk’last_value=‘0’)) then
判断clk的下降沿
if ( (clk’event)and (clk=‘0’) and(clk’last_value=‘1’)) then
bit(位): 0
和1
bit-Vector(位矢量): 例如:00110
,位矢量是用双引号括起来的一组数据,位矢量可以是二进制(B)数、八制进(O)数和十六进制数(X)。如“001100”,X“00BE”等。位矢量可以对其某一位进行操作。
Boolean " ture"和"false"
time 例如:1 us、100 ms,3 s
character 例如:‘a’、‘n’、‘1’、 ‘0’
string 例如:“sdfsd”、“my design”
integer 32位例如:1、234、-2134234
real 范围-1.0E38~+1.0E38 例如:1.0、2.834、3.14、0.0
natural 自然数 和 positive 正整数
senverity level (错误等级,常和assert语句配合使用)包含有:note、warning、error、failure
以上十种类型是VHDL中的标准类型,在编程中可以直接使用。使用这十种以外的类型,需要自行定义或指明所引用的Library(库)和Package(包)集合。
通用格式
*TYPE* 类型名 IS 数据类型定义
用户可以定义的数据类型:
枚举类型enumberated、整数型integer、实数型real、数组类型array、纪录类型record、时间类型time、文件类型file、存取类型access
(1)枚举类型enumberated
格式 :*type* 数据类型名 *is* (元素,元素……);
例子 :type week is (sun,mon,tue,thu,fri,sat);
type std_logic is (‘1’,‘0’,‘x’,‘z’);
(2) 整数类integer和实数类real
格式 :type 数据类型名 is 数据类型定义 约束范围;
例子 type week is integer range 1 to 7;
type current is real range -1E4 to 1E4
(3) 数组类型array
格式 :*type* 数据类型名 *is array* 范围 *of* 元数据类型名
例子 type week is array (1 to 7) of integer;
type deweek is array (1 to 7) of week;
(4) 时间类型time
格式 *type* 数据类型名 *is* 范围 *units* 基本单位; 单位; *end units*
例子 type time is range -1E18 to 1E18 units us;
ms=1000 us; sec=1000 ms; min=60 sec; end units
注意*:引用时间时,有的编译器要求量* 与单位 之间应有一个空格如:1 ns;不能写为1ns
(5) 纪录类型record
元素名:数据类型名;
元素名:数据类型名;
*end record;*
id:integer;
date:string;
security:boolean;
end record;
引用:signal flag:boolean;
signal order1:order;
order1<=(3423,“1999/07/07”,true);
flag<=order1.security;
非法使用例子:
(1)
(2)
(3)
信号Z有两个驱动A和B;Z必须定义为一种新的数据类型,否则Z将无法决定取值,语句视为非法。
(4)
(5)
要点:赋值语句中的方向应和声明中的方向一样
连接操作符—&
集合操作—()
集合操作—序号
集合操作–采用others
(1)逻辑操作符有:
(2)逻辑操作符的应用例子
(3)关系运算符有
(4)关系运算符的应用
(5)数学运算符
***注意:***上述运算符应用于 integer,real,time 类型,不能用于vector(如果希望用于vector,可以使用库IEEE的std_logic_unsigned包,它对算术运算符进行了扩展)
(6)VHDL中的操作符应用要点
VHDL属于强类型,不同类型之间不能进行运算和赋值,可以进行数据类型转换
vector不表示number, array 不表示number
基本概念
并行处理(concurrent):语句的执行与书写顺序无关,并行块内的语句时同时执行的
顺序处理(sequential): 语句的执行按书写的先后次序,从前到后顺序执行。这种方式和其他普通编程语言(如c,pascal)是一样的。
2、并行和顺序处理在vhdl中的应用
(1)Architecture 中的语句及子模块之间是并行处理的
(2)子模块block中的语句是并行处理的
(3)子模块process中的语句是顺序处理的
分析:
当A、B、C、D中任一信号发生变化时,进程将开始执行,当执行 Z <= A and B 后, Z 的值不会立即变化 ;同理执行 Z <= C and D 后Z 的值也不会立即变化。当执行end process后, Z 的值才开始更新,同时系统挂起开始等待敏感信号。
在process中,其值被引用的信号应当出现在敏感信号列表中
反例:
可见不符和设计要求
(4)子模块subprogram中的function和procedure是顺序处理的
顺序执行语句(sequential statement)
Wait语句 assert语句 If 语句
case语句 for loop语句 while 语句
并行处理语句(concurrent statement)
并行操作中的信号赋值
*用在并行处理语句中时,符号<=右边的值是此条语句的敏感信号,*即符号<=右边的值发生变化就会重新激发此条赋值语句,也即符号<=右边的值不变化时,此条赋值语句就不会执行。如果符号<=右边是常数则赋值语句一直执行。*
*用在顺序执行语句中时,没有以上说法。
with 表达式 select
目的信号量 <= 表达式1 when 条件1,
表达式2 when 条件2,
……
表达式n when 条件n;
1、顺序执行语句 wait、assert、if -else 、case、for-loop、while语句只能用在process、function 和 procedure 中;
2、并行处理语句(条件信号带入和选择信号带入)只能用在architecture、block中;
其它语句
参数传递语句(GENERIC)用于不同层次设计模块之间信息的传递和参数的传递,例如矢量和数组的长度、器件的延迟时间参数等的传递。
元件调用(COMPONENT)和端口映射(PORT MAP)语句
元件调用语句指定了本结构体中所调用的是哪一个模块,这些被调用的模块应已编译在库中,在本结构体中无需再对该模块的功能进行描述。COMPONENT语句的书写格式如下:
COMPONENT元件名
GENERIC 说明;--参数说明
PORT 说明; --端口说明
END COMPONENT;
COMPONENT语句可用于ARCHITECTURE、PACKGE以及BLOCK中的说明部分,但不能用于进程和子程序过程。
COMPONENT语句所定义的元件,用端口映射语句实现连接。端口映射语句的书写格式为:
标号名:元件名PORT MAP(信号,…,信号);
U2:and2 PORT MAP(a=>d0, b=>d1, c=>q0);
通过映射语句,将被调用的元件信号按映射语句中的规定连接到系统上。信号映射的方法有两种:位置映射和名称映射。所谓位置映射,就是在PORT MAP语句中所指定的实际信号位置顺序应和库元件说明中的信号书写顺序一一对应。
【1】VHDL重点语法全解
【2】系统芯片(SOC)设计方法与实践 万国春,苏立峰,罗胜钦,陈怡著