VHDL讲座
VHDL (Very High Speed Integrated Circuit Hardware Description Language) ,意为超高速集成电路硬件描述语言。由美国国防部 70~80 年代组织研制开发,其目的首先是想用这种语言描述复杂电路,其次是想成为一个标准。 1985 年完成第一版, 1987 年成为 IEEE Std1076-1987 。美国国防部规定所有官方的 ASIC 设计都必须用 VHDL 为设计描述语言,此后渐渐成为工业标准为大家接受。 1993 年修改成 IEEE Std1164-1993 。 1995 年,中国国家技术监督局组织编撰并出版《CAD 通用技术规范》,推荐 VHDL 语言作为我国电子设计自动化硬件描述语言的国家标准。
VHDL 的由来
VHDL 的特点1 .支持从系统级(特大型)至门级电路的多层次描述;支持结
构描述、行为描述、数据流描述及混合描述。2 .支持自底向上( bottom-up )及自顶向下( top-down )
的设计;支持模块化、层次化设计;支持函数、过程及自定义程序包和库,可设计共享。
3 . 支持组合逻辑电路和时序电路;支持延迟功能。4 . 使用类属语句进行参数化设计。5 . 支持断言语句,报告系统信息和错误信息。6 . 数据类型丰富、安全性好,既有预定义数据类型,又可自定
义数据类型。
1.USE 定义区
2.PACKAGE 定义区
3.ENTITY 定义区
4.ARCHITECTURE 定义区
Component 定义区
信号定义
Data Flow 描述
5.CONFIGURATION 定义区
Behavior Process 描述 Structure 描述
定义元件库定义使用哪些自定义库
定义电路实体的外观: I/O 接口规格
描述电路的内部功能,说明电路执行什么动作
或功能
决定哪一个 architecture 被使
用
11 .库(.库( librarylibrary )) 库是用来存储和放置可编译的设计单元的地方,通过其目录可查询、调用。库可以分为两类:设计库和资源库。库说明一般格式如下:library library 库名;库名;use use 库名库名 .. 逻辑体名;逻辑体名;
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
初学时不太熟悉,全部写上。
22 .实体(.实体( entityentity )) 实体的电路意义相当于器件,在电路原理图上相当于
元件符号。实体的对象相当广泛,可以是完整的系统(特大型)、电路板、芯片、电路单元、小函数或是逻辑门。实体有实体名。
entity 实体名 is [generic (类属表) ; ] [port (端口表) ; ]
end [entity] [ 实体名 ] ;
( 1 )类属表( generics ) 将外部环境的静态信息传递给实体的具体元件,利用该特性可以设计参数化元件。
( 2 )端口表( ports ) 实体说明中的每一个 I/O 信号称为端口。有四种端口模式:
1 )输入( in ) 用于时钟输入及各种控制输入,如置位,复位,使能及置数等。
2 )输出( out ) 通常用作终端输出。 3)缓冲( buffer )允许数据流出端口及内部反馈允许内部引用该端口的信号。
4)双向( inout ) 允许数据流入或流出实体,也用于内部反馈。
33 . 结构体(. 结构体( architecturearchitecture )) 实体是“黑箱”,结构体在电路上相当于器件的内部
电路。结构体都必须附属于某个实体,一个实体可同时具
备多个结构体。architecture 结构体名 of 实体名 is
[ 说明部分; ]
begin
< 语句部分; >
end [ 结构体名 ] ;
44 . 配置(. 配置( configuratioconfiguratio
nn ))
配置是用于描述层与层之间的连接
关系和实体与结构体之间的连接关系。
在仿真设计中,利用配置来获得性能最
佳的设计目标。
一、 一、 VHDLVHDL 语言要素语言要素 1.1. 标识符标识符 基本标识符用来为常量、变量、信号、端口、子程序
或参数等命名,由英文字母、数字和下划线组成。基本标识符必须遵从以下规则:
1 )首字符必须是英文字母; 2 )末字符不能是下划线;并且不允许出现两个连续的下划线; 3 )大、小写英文字母等效,可混合输入; 4 ) VHDL 语言的关键字不能作标识符
几个合法的基本标识符:
a , October , MAY_1 , loop1 , new_
state
几个非法的基本标识符: signal --保留字不能用作基本标识符;
old_state_ --最后字符不能是下划线;
New#type -- 有非法字符 # ;
8home -- 不能用数字开头。
22 .数据对象.数据对象
常量常量 (constant)(constant) 常量是指固定不变的量。在实体、结构体、程序包
、块、进程和子程序中可对常量进行定义,所定义的常量的数据类型必须与表达式的类型相一致。 常量说明格式如下:
constant 常量名 [ ,常量名 ]: 数据类型 [ := 表达式] ;例如: constant width: integer := 8;
constant Us: real := 12.0;
constant bus: std_logic_vector(3 down to 0) :=”1101”;
VHDL 语言规定的常量的有效范围
变量变量 (variable)(variable) 变量常用来存储中间数据,只能用于进程和子程序中,可通过变量赋值语句改变变量的值 。 VHDL 规定对变量的赋值立即实现,无任何延迟时间。变量说明格式如下: variable 变量名 [ ,变量名 ]: 数据类型 [:= 初始值 ]
; 目标变量名 := 表达式; 例如: variable j : integer := 2;
variable a : std_logic_vector (2 downto 0);
a := “101”; -- 对变量赋值 a(1 downto 0) := “01”; a(j) := ‘1’; -- 对变量分段赋值
信号信号 (signal)(signal)信号理解成为连接线,它的作用与 ABEL 语言中的节点
NODE 相类似。信号说明格式如下: signal 信号名 : 数据类型 [:= 初始值 ] ;
可加入进程敏感表激活进程 不可写入进程敏感表中
范围实体、结构体和程序包 变 量
采用 <= 作为信号的赋值符
可用于在模块间交换数据
信 号只能在进程或子程序中使用
只用于进程或子程序局部有独立硬件对应物:连接线 无具体的硬件对应物
采用 := 作为变量的赋值符信号赋值存在延迟 变量赋值立即生效,无延迟
信号赋值语句的格式如下: 目标信号名 <= 表达式; 信号的赋值符用 <= 。信号可以在实体、结构体和程序包中说明
和使用,但不允许在进程和子程序中定义新的信号。信号的赋值并不能立即生效,即有一 δ 延迟。
信号赋值与变量赋值符号不同:信号赋值号 <=
常量、变量赋值号 :=
例 signal width : integer;
signal bus : bit_vector ( 3 to 0 ) ;
signal z : bit;
z <= ‘1’;
width <= 12;
bus <= “1010” ;
三种对象的含义和说明场合
对象类型 含义 说明语句的场合
signal 说明全局量 Architecture 、 package 、 entity
variable 说明局部量 Process 、 function 、 procedure
constant 说明全局量 以上均可
3. 3. 数据类型数据类型
标量型、复合型、寻址型、文标量型、复合型、寻址型、文
件型。件型。
标量类型标量类型 (scalar type)(scalar type)
标量类型的数据对象在某一时刻只对应一个值。 整数类型、浮点类型、物理类型和枚举类型。
复合类型复合类型 (composite type)(composite type) 复合类型的数据对象在某时刻可持多个值。是单值类型元素的集合。 复合类型包括数组类型和记录类型。
整数类型整数类型 (integer)(integer)
整数类型适用加、减、乘、除等。 VHDL 标准规定整数的最小范围为从( 2311 )至( 2311 )。整数用关键字 in
teger 说明。
标量类型标量类型
例如: signal a,b,c,d,e : integer ; a<=012; b<=0; c<=123_456; d<=2E5; e<=4e3; -- 对 c 的赋值实际是 123456 , -- 数字中的下划线只是为了提高可读性,没有任何实际意义,也不影响数值。
实数类型实数类型 (real)(real) 实数的最小范围从 1.0E+38 至 +1.0E+38 。用关键字 real 说
明。
例如: variable a,b,c,d : real ;
a:=12.0; b:=3.14_159; c:=2.0E5; d:=1.5e-6; 枚举类型枚举类型 预定义的两个枚举类型是布尔数据类型( boolean )和位
数据类型( bit )。
type boolean is ( false , true );
type bit is (‘ 0’ ,‘ 1’ );
变量或信号通常定义为枚举类型,可以将其定义成为布尔类型或位类型。如: signal z : bit ;
一种常用的多值类型 std_logic 可以描述系统,对它的定义如下:
type std_logic is ( ‘U’ ‘X’ ‘0’ ‘1’ ‘Z’ ‘W’ ‘L’ ‘H’ ‘-’ );
--未定义 --强未知--强为 0 --强为 1
-- 高阻态 --弱未知--弱为 0 --弱为 1
-- 可忽略
物理类型物理类型VHDL 中预定义的物理类型是时间,其定义如下:
type time is range 0 to 2147483647 units
fs; --飞秒,相当于 10E-15秒, VHDL 中最小的时间单位
ps=1000 fs; --皮秒,相当于 10E-12秒ns=1000 ps; --纳秒,相当于 10E-9秒us=1000 ns; --微秒,相当于 10E-6秒ms=1000 us ; --毫秒,相当于 10E-3秒sec=1000 ms; --秒min=60 sec; --分hr=60 min; -- 时end units;
虽然 VHDL 定义了八种时间类型,但 ispDesign EXPERT Syste
m 中的综合工具只支持微秒、纳秒时间类型。
复合类型复合类型
复合类型包括数组类型和记录类型。
数组类型数组类型 (array)(array) 数组类型由一个或多个相同类型的元素集合构成,构成它的元
素可以是任何一种 VHDL 单值数据类型。 VHDL允许数组的两种不同类型的定义方式,即限定性数组和非限定性数组。
限定性数组定义语句格式如下:
type 数组名 is array ( 数组范围 ) of 数据类型 ;例如: type bus is array ( 3 downto 0 ) of std_logic;
type set is array ( 0 to 7 ) of integer;
非限定性数组定义语句格式如下:type 数组名 is array (数组下标名 range <> ) of 数据类型;常用非限定性数组有:type bit_vector is array (natural range <>) of bit;
type std_logic_vector is array (natural range <>) of std_logic;
第一个定义只是说明非限定性数组 bit_vector 是由类型为 bit 的数据集合而成,第二个定义也只是说明非限定性数组 std_logic_vector 是由类型为 std_logic 的数据集合而成。非限定数组的关键字 natural指明数组范围是 0 ~ 2147483647 。非限定性数组在使用时,必须确定下标范围。
记录类型记录类型 (record)(record)记录类型是一种多值数据类型,元素可以是任一 VHDL 的数据类
型。记录类型定义语句格式如下:type 记录名 is record
元素名:元素数据类型; …
end record [记录名 ] ; 将锁存器的输入输出和使能构成一个记录,举例如下 :
type record_name is record
latch_in: bit_vector(3 downto 0);
latch_out: bit_vector(3 downto 0);
enable:bit;
end record ;
VHDLVHDL 预定义数据类型预定义数据类型 VHDL 预定义数据类型都是在 VHDL 标准程序包 STANDA
RD 以及 IEEE 库中的程序包 STD_LOGIC_1164 中预先进行定义的。 在 STANDARD 程序包中预定义的数据类型有: 1 )布尔( boolean )数据类型 2 )位( bit )数据类型 3 )位矢量( bit_vector )数据类型 4 ) 整数( integer )数据类型 5 )自然数( natural )和正整数( positive )数据类型 6 )实数( real )数据类型 7 )时间( time )数据类型
STD_LOGIC_1164 中预定义的两个非常重要的数据类型是:
1 ) 标准逻辑位( std_logic )数据类型
2) 标准逻辑矢量( std_logic_vector )数据类型
用户自定义数据类型方式用户自定义数据类型方式用户可采用类型定义语句 type 和子类型定义语句 subtype 自定
义数据类型,如枚举类型、整数类型、数组类型、记录类型、时间类型及实数类型等。
1 ) type 语句格式:type 数据类型名 is 数据类型定义 [of 基本数据类型 ] ;
例: type states is ( read , write ); signal present _ state , next _ state : states ;
再举一例自定义数据类型 week 如下:type week is ( sun , mon , tue , wed , thu , fri , sat );signal hotel , home : week ;
上述对信号 hotel 和 home 的定义表明它们是自定义数据类型week ,因此这两个信号之间可以相互作用,因为只有它们属于同一数据类型。
2 ) subtype 语句 subtype 语句用来定义数据类型的子类型。 VHDL 规定任何基本
数据类型均可定义其子类型。子类型与其父类型完全兼容。格式:subtype 子类型名 is 基本数据类型 range 约束范围;例: type integer is –2147483647 to +2147483647; --1
type i is range 0 to 50; --2
subtype natural is integer range 0 to +2147483647; --3
subtype ci is i range 0 to 30; --4
subtype di is ci range 0 to 10; --5
subtype data is bit_vector (3 downto 0); --6
subtype lower_data is data; --7 第三句定义自然数为整数数据类型的子类型;第四句定义 ci 为 i
的子类型。第五句定义 di 为 ci 的子类型, VHDL允许定义子类型的子类型;第六句,使用约束条件 (3 downto 0) 对非限定性数组 bit_vector 作具体说明;第七句, lower_data 是 data 的一个子类型
44 .属性.属性
属性是关于信号、类型等的特性。通常,对象的属性可以用一个值或一个表达式来表示。
信号类属性信号类属性 信号类属性有多种类型,其中最为常用的是’ event 属性。 例如:信号 clk ( std_logic 类型)的’ event 属性列写如下:
clk’event and clk=’1’ --1 检测时钟在上升沿有效 clk’event and clk=’0’ --2 检测时钟在下降沿有效
第一句是对信号 clk 的上升沿进行检测。第二句则是对信号 clk
的下降沿进行检测。此外, VHDL还预定义了两个函数,利用它们也可以很方便地检测信号的变化状态。
rising_edge(clk) --检测上升沿有效 falling_edge(clk) --检测下降沿有效
数值类、范围类及数组属性数值类、范围类及数组属性数值类属性主要对属性目标的相关数值特性进行测试,返回具
体值;范围类属性对属性目标的取值区间进行测试,返回一区间范围;数组属性是对数组的宽度或元素的个数进行测定,也返回一个值。
若对某数组变量的定义如下:variable byte : bit_vector (3 downto 0) ;则变量 byte 的相
关属性如表所示。属性类型 属 性 值数值类属性 Byte’left 3
Byte’right 0
Byte’low 0
Byte’high 3
数组属性 Byte’length 4
范围类属性 Byte’range 3 downto 0
Byte’reverse_range 0 to 3
5. 5. 运算符运算符 主要有算术运算符、关系运算符、逻辑运算符、赋值运算符、关联运算符和其它运算符等,各种操作符见书表 3 所示。
二、 二、 VHDLVHDL 语言中的并行语句语言中的并行语句 特点:
各种并行语句在结构体中的执行是同步进行的,其执行各种并行语句在结构体中的执行是同步进行的,其执行顺序与书写的顺序无关。顺序与书写的顺序无关。
语句之间可以有信息的交流,也可以相互独立、异步运语句之间可以有信息的交流,也可以相互独立、异步运行的。行的。
每一并行语句内部的语句运行方式有两种:并行执行方每一并行语句内部的语句运行方式有两种:并行执行方式和顺序执行方式式和顺序执行方式
基本并行语句:
进程语句( process statement )
并行信号赋值语句 ( concurrent signal assignment
) 元件例化语句( component instantiation )
块语句( block statement )
生成语句( generate statement )
并行过程调用语句( concurrent procedure calls )
在结构体中的使用形式
ARCHITECTURE 结构体名 OF 实体名 IS 说明语句
BEGIN
并行语句
END ARCHITECTURE 结构体名;
11 .进程语句.进程语句格式如下:[ 进程标号: ] process [ (敏感信号表) ] [is]
[ 说明区 ;]
begin
< 顺序语句; >
end process[ 进程标号 ]; ( 1 )进程敏感表中可包含一个或多个元素值,当这些值中的一个或多个改变时,会激活进程。含有敏感信号表的进程,不允许再出现显式 wait 语句。如果不含,必须用 wait 语句。 ( 2 )进程说明区内可以说明数据类型、子程序、变量等,限于内部,即定义局部数据环境。 ( 3 )有关进程内部顺序语句的内容将在顺序语句部分作详细介绍。( 4 ) 一个进程可以重复执行多次。
对 PROCESS 的几点说明1 、进程说明部分主要定义一些局部量,但说明部分不允许定义信号和共享变量;
2 、敏感信号参数需列出启动本进程要读入的信号名(当有 wait 语句时例外)
3 、(在敏感信号表中没有列出敏感信号)当遇到 WAIT 语句时, 执行过程将被有条件的终止,即被挂起( Suspension )
4 、进程语句有并行和顺序行为的双重性
例:结构体用进程实现两位二进制等值比较器。 .
.
.
architecture behave_process of ecomp2 is
begin
eqcome : process ( a , b ) -- 以敏感表( a , b )代替显式 wait 语句
begin
if ( a=b ) then equ<=’1’ ; else equ<= ‘0’ ; end if ; end process eqcome ;
end behave_process ; .
与其等效的使用显式 wait 语句的进程如下:architecture behave_process of ecomp2 is
begin
process --无敏感信号表 begin
if ( a=b ) then equ<=’1’ ; else equ<= ‘0’ ; end if ;
wait on a , b ; --本进程无敏感表则必须有显式 wait 语句 end process ;
end behave_process ;
22 .并行信号赋值语句.并行信号赋值语句
并行信号赋值语句对信号的赋值都经历了 δ 延迟。
三种形式:简单型、条件型和选择型。 简单信号赋值语句 格式:信号赋值语句 <= 表达式;
Eg. Architecture art of XHFZ is signal E,F,G,H: STD_LOGIC BEGIN G<=E OR F;
条件信号赋值语句格式 :
[ 标号: ] 信号名 <= 表达式 when 条件 else
[{ 表达式 when 条件 else}]
表达式;
例: z<=a when (x>5) else --注意在 else 后无任何分隔符(分号、逗号或其他) b when (x<5) else --赋值符 <=只能出现一次 c;
选择信号赋值语句格式: [ 标号: ] with 表达式 select
信号名 <= 表达式 when value[{ , 表达式 when value}] ;
when 从句中所有取值必须互相独立,可使用 when othe
rs来替代未列举的其他取值。例: with s select --同条件信号赋值语句一样,赋值符只能出现一次 z<=a when 5, --注意此处加逗号 b when 10,
c when others; --除了 s 为 5 和 10两种可能以外,其他所有可能由 others 表达。
33 .元件例化语句.元件例化语句
允许重复调用已有的设计,从而将设计分解,支持模块化设计方式。在例化元件之前,必须对元件的外貌进行元件说明。元件说明的格式如下:
component 元件名[generic (类属表) ; ]
[port (端口表) ; ]
end component ;元件例化的格式如下:元件标号: 元件名 port map (信号映射);信号映射可以使用关键字 open ;名称映射的格式如
下:形式参数 => 实际参数,其中 => 为关联运算符。
4 、生成语句 生成语句可以简化实际电路中由许多重复的基本结构构成的电路语句格式:[ 标号: ] FOR 循环变量 IN 取值范围 GENERATE
说明; BEGIN 并行语句; END GENEARTE [ 标号 ] ;
[ 标号: ] IF 条件 GENERATE 说明; BEGIN 并行语句; END GENERATE [ 标号 ] ;
几点说明:1 、 FOR 语句结构,主要用来描述设计中的一些有规律的单元结构,其生成的参数及其取值范围的含义和运行方式与 LOOP 语句相似。
2 、生成参数(循环变量)是自动产生,有两种形式: 表达式 TO 表达式; -- 递增方式 表达式 DOWNTO 表达式; -- 递减方式
5 、标号可以不要,但在嵌套生成语句结构中建议使用。
3 、并行语句中主要包括:元件、进程语句、块语句、并行过程调用语句、并行信号赋值语句以及生成语句
4 、生成语句允许嵌套
说明: …port(I1: bit; O1: out bit); … Inv: inverter port map (inputs(I),outputs(I)); …
Inputs(I)与 I1 建立联系; outputs(I)与 O1建立联系;从而形成了“位置映射”
“命名映射” 则 Inv: inverter port map(I1=>inputs(I), O1=>outputs(I));
5 、并行过程调用语句
格式: procedure 过程名(关联参量名) is
特点:可以作为一个并行语句直接出现在结构体或块语句中;功能等效于包含了同一个过程调用语句的进程。
Eg. … procedure adder(signal A,B : IN STD_LOGIC; signal SUM: OUT STD_LOGIC) is …
66 .块语句.块语句 块语句将许多并行语句包装在一起,形成一个子模块。可以改善可读性,或利用 BLOCK 中的保护表达式关闭某些信号 格式:
块标号: block [ (保护表达式) ] [is]
[generic (类属表) ; ]
[port (端口表) ; ]
[ 块说明语句; ] -- 块内说明的对象、信号只在块内有效
begin
< 并行语句; >
end block [ 块标号 ] ;
三、三、 VHDLVHDL 中的 顺序语句中的 顺序语句 特点:
1 、只能出现在进程 (process) 和子程序中2 、顺序语句的执行顺序与其书写的顺序一致;但与相应的硬件逻辑工作顺序未必一致3 、子程序本身没有顺序与并行语句之分4 、一个进程是由一系列的顺序语句构成,但其自身是并行的,即同一设计体中,所有进程都是并行的5 、进程本身与 entity 中其他部分的数据交换只能通过信号或端口进行
分类: 变量赋值语句 信号赋值语句 if 语句 case 语句 loop 语句 next 语句 exit 语句 null 语句 wait 语句 report 语句 assert 语句
11 .变量赋值语句.变量赋值语句 变量只在其说明域中有效,不许进程间传递变量值。格式 : 变量名 := 表达式; --赋值符为 :=
与信号不同,变量赋值没有 δ 延迟,而是立刻执行。
请比较下面两个进程: -- 第一个进程
signal a: integer :=5;
signal b: integer :=10;
process(a,b)
begin
a<=b;
b<=a;
end process;
-- 第二个进程 process
variable a: integer :=5;
variable b: integer :=10;
begin
a:=b;
b:=a;
end process;
a=10b=5
a=10b=10
22 .信号赋值语句.信号赋值语句 既可用作并行语句,又可用作顺序语句。
格式:信号名 <= 表达式; 例: d<=a and c ; a<=‘0’ ; s<= b“00011010” ; (s<=x“1A” ; )
r<=b“011010” ; ( r<= o“32” ; )
可允许用库指定符 b 、 o 、 x分别表示二进制、八进
制、十六进制。
--赋值可使用简单表达式-- 一位常量使用单引号括起
-- 多位常量使用双引号括起
赋值目标
1 、标识符赋值目标及数组单元赋值目标 标识符赋值目标是以简单的标识符作为被赋值的信号或新变量;
数组单元赋值目标的表达形式为: 数组类信号或新变量名(下标名) eg. Y(0)<=v3; Y(1)<=v3;
2 、段下标元素赋值目标及集合块赋值目标 段下标元素赋值目标的表达形式: 数组类信号或变量名(下标 1 to/downto 下标 2 )
33 .. if if 语句语句格式: [if 标号: ] if 条件 then
< 顺序语句; >
[{elsif 条件 then
顺序语句; }]
[else
顺序语句; ]
end if ; 若 if 的条件为真执行 then 后的顺序语句,为假执行 else ( elsif )后的语句,并以 end if 结束。
44 .. case case 语句语句 与并行语句中的 with-select-when 相似。格式如下:
[case 标号: ] case 表达式 is
when 表达式值 =>顺序语句 ;
[{when 表达式值 =>顺序语句 ;}]
[when others=>顺序语句; ]
end case[case 标号 ] ;
例 : 用 case 语句描述 4选 1 多路选择器进程 .
mux_1: process(a, b, c, d, s )
begin
case s is
when “00”=> x<=a;
when “01”=> x<=b;
when “10”=> x<=c;
when others => x<=d;
end case ; end process mux_1;
例: case 选项可 支 持一个范围,case s is
when 1 to 9=> x<=a;
when 10|15=> x<=b;
when others=> x<=c;
end case ;
55 .. LoopLoop 语句语句 Loop 语句可实现有规则的循环,次数受迭代算法的制约。格式: [loop 标号: ] [重复模式 ] loop
< 顺序语句; >
end loop [loop 标号 ] ;重复模式有两种: ( 1 ) while 循环条件 loop
--signal byte : bit_vector(3 downto 0) ;-- variable sum: integer :=0
loop1 : while ( i<=9 ) loop
i:=i+1; --允许不对 i 作变量说明 sum:=sum+1;
end loop loop1 ;
重复模式有两种 : ( 2 ) for 循环变量 in 离散范围 loop 。例:loop2 : for i in byte’range loop
-- 等价于 for i in 3 downto 0 loop
sum:=sum+2;
end loop loop2;
loop3 : for i in byte’low to byte’high loop
-- 等价于 for i in 0 to 3 loop
sum:=sum+3;
end loop ;
66 .. next next 语句语句格式: next
next loop 标号; next loop 标号 when 条件; 例如:
for i in 0 to 10 loop
if (flage(i)=’1’) then next;
end if
q(i)<=d(i);
end loop;
loop1: while j<10 loop
loop2: while k<10 loop
…
-- 如果布尔表达式为真,直接跳到 end loop 句
next when j<k;
….
next loop1 when j=k;
…
end loop2;
end loop1;
-- 此处缺省 loop 标号,条件为真跳到 end loop2
-- 当 j=k 为真跳出内循环并跳到指定循环 end loop1处
77 .. exit exit 语句语句格式: exit [loop 标号 ] [when 条件 ] ;例: for i in 0 to 10 loop
if (flage(i)=’1’) then exit;
end if
q(i)<=d(i);
end loop;
-- 如果布尔表达式为真,直接跳出并终止循环
88 .. null null 语句语句null 语句表示无任何动作。执行该语句只是使流程走到
下一句。格式: null ;例: case s is
when ‘0’=> x<=a;
when ‘1’=> x<=b;
when others =>null; --空语句 end case ;
99 .. wait wait 语句语句 wait 语句允许顺序执行的进程或子程序的执行或挂起。
格式: wait on 信号表
wait until条件表达式
wait for 时间表达式wait
-- 使进程暂停,直到信号表中的某个信号值改变时才激活进程-- 使进程暂停,直到条件表达式中的条件为真-- 使进程暂停表达式所规定的时间-- 可能会使进程陷入永远等待之中,一般不采用
例如: wait on a,b;
wait until clk’event and clk=’1’ and enable=’1’;
wait for 10ns;
1010 .. reportreport 语句语句 其语意可参照断言语句。格式 : [ 标号: ] report 报告信息 [ 错误级别 ] ;
下面两行语句是等价的:report “ok!”;
assert false report “ok!” severity note;
1111 .. assertassert 语句语句
断言语句主要用于测试平台中,用于检查并报告源程序描述(源描述)的执行结果。并行断言语句与顺序断言语句格式相同。 格式: assert 条件 [report 报告信息 ] [severity 错误级别 ] ; -- 此处条件是一个布尔表达式
( 1 ) note 级别:无错误,只报告当前发生的情况。报告信息,仿真继续;( 2 ) warning 级别:警告,如不修改,可能会出现问题。报告信息,仿真继续;( 3 ) error 级别(默认):有错误,必须现在就修改。报告信息,仿真停止,可强制继续;( 4 ) failure 级别:有严重错误,可能有破坏性的错误。报告信息,仿真停止。
例如: assert ( a=255 ) report “a at edge” severity war
ning; --警告 a 在边缘,可继续 assert ( a>255 ) report “a out of edge” severi
ty error; -- 报告 a溢出,停止仿真
12 、 return 语句
只能用子程序中,并用来结束当前子程序的运行 格式: RETURN [ 表达式 ] ;
说明: 1 、当表达式缺省时,只能用于过程,不返回任何值 2 、有表达式时,只能用于函数,并返回一个值。
四、 描述风格四、 描述风格所谓描述风格是指在结构体中,对整个设计实体的逻辑功能的描
述方式。 其包括行为描述、数据流描述、结构化描述与混合描述
11 .行为描述.行为描述
描述中采用进程语句。
22 .数据流描述.数据流描述
描述中采用除进程外的其他并发语句。
33 .结构化描述.结构化描述
用来调用低层次设计模块,支持大型设计逻辑分解。
44 .混合描述.混合描述
大型设计中,常采用行为描述与结构描述相结合的混合描述。
五、 几个重要概念五、 几个重要概念 程序包和库、类属、子程序。
11 . 程序包和库. 程序包和库 在实体说明和结构体内部定义的数据类型、元件、函数、过程等,对其它设计单元是不可见的。程序包中定义的类型、元件、函数、过程及说明可以对其它设计单元可见。它由两部分组成:程序包说明和程序包体。 需要注意的是:只有在程序包说明部分说明的标识符在程序包之外可见,在包体部分中说明的标识符对其他设计不可见;使用之前必须先用 use 语句将程序包打开再进行调用。
使用程序包实现两位二进制等值比较器。library ieee;
use ieee.std_logic_1164.all;
package myeqcom is
component xnor2
port(i1,i2: in std_logic;
o1:out std_logic);
end component;
component and2
port(i1,i2: in std_logic;
o1:out std_logic);
end component;
end myeqcom;
-- 程序包说明部分开始-- 说明元件 xnor2
-- 说明元件 and2
-- 结束程序包
-- 先将 xnor2 和 and2打包在 myeqcom 程序包中
use ieee.std_logic_1164.all;
entity xnor2 is
port(i1,i2: in std_logic;
o1:out std_logic);
end ;
architecture xnor2 of xnor2 is
begin
o1<=i1 xnor i2;
end xnor2;
-- 构造元件 xnor2
use ieee.std_logic_1164.all;
entity and2 is
port(i1,i2: in std_logic;
o1:out std_logic);
end and2;
architecture and2 of and2 is
begin
o1<=i1 and i2;
end and2;
-- 构造元件 and2
将 xnor2 和 and2打包在 myeqcom 程序包,放在 WORK 库中。
library ieee; use ieee.std_logic_1164.all;use work.myeqcom.all;
entity ecomp2 isport(a,b:in std_logic_vector(1 downto 0); equ:out std_logic);end;architecture struct of ecomp2 issignal x:std_logic_vector(1 downto 0);beginu0:xnor2 port map (a(0),b(0),x(0));
u1:xnor2 port map (a(1),b(1),x(1));u2:and2 port map (x(0),x(1),equ);end struct;
-- 构造两位二进制等值比较器
-- 使用 use 语句打开 work 库中的 myeqcom 程序包
-- 此处不需配置便可直接例化元件
22 . 类属. 类属 它可以规定端口的大小、实体中子元件的数目、实体的时延特
性等。在调用时可指明其位数 n ,若不具体指明 n 的大小,则系统认定其为默认值。
使用类属构造的 n ( n>1 )位寄存器。library ieee;
use ieee.std_logic_1164.all;
entity reg is
generic ( size: integer:=2);
port ( clk,rst,load : in std_logic;
d: in std_logic_vector(size-1 downto 0);
q: out std_logic_vector(size-1 downto 0));
end reg;
-- 位数 size 的默认值为 2
architecture behave of reg is
begin
process(rst,load,clk,d)
begin
if rst=’1’ then q<=(others=>’0’);
elsif (clk’event and clk=’1’) then
if (load=’1’) then q<=d;
end if;
end if;
end process;
end behave;
设计中若调用 n 位寄存器则需在其元件说明语句中加入类属表,如下:component reg is
generic(size :integer);
port(clk,rst,load:in std_logic;
d: in std_logic_vector(size-1 downto 0);
q: out std_logic_vector(size-1 downto 0));
end component;
设计中调用 n 位寄存器例化语句如下: u0: reg port map (clk,rst,load,d,q);
u1: reg generic map(4) port map(clk,rst,load,d,q);
u2: reg generic map(6) port map(clk,rst,load,d,q);
--加入的类属表
--缺省类属表,默认位数为 2
--调用指明寄存器位数为 4
--调用指明寄存器位数为 6
33 .子程序.子程序子程序包括函数和过程,它主要用于高层次的数值运算
或类型转换、元件描述等。在函数和过程中,所有语句必须都是顺序语句,且不能在其中说明信号。函数与过程的区别见表。
函 数 过 程
说明部分 不可说明信号,可说明变量
形式参数类型 in in , out , inout
形式参数对象类 常量,信号 常量,信号,变量
等待语句 不允许 允许
返回值 一个 多个
不可说明信号和变量
44 .类型转换与重载的概念.类型转换与重载的概念 VHDL 属于强类型语言,它规定每一个操作对象具有一个类型且只能具有该类型的值,在定义一个操作时必须指明其操作对象的类型,不同类型对象之间互不兼容,因此在 VHDL 语言中类型转换相当重要。此外,在 1076 标准中,“ +”运算符仅被定义用于数字类型(整数、浮点数和物理类型)数据的运算,并不处理如 std 或 bit
的可枚举类型。如果要使“ +”运算符能处理可枚举类型,必须对其重新定义。“ +”运算符虽然被重新定义,而它的符号不变,只是功能增加了,这就是对“ +”运算符的重载。在预定义程序包 std
_logic_arith 中,有许多对运算符的重载。子程序和运算符均可重载,函数的一大功能就是对运算符重载。 VHDL 中允许大量重载,使用重载的最终目的是使模块易读和易维护。
六、 设计举例六、 设计举例
1.1. 基本设计基本设计组合逻辑电路有编码器、七段译码显示器;时序逻辑电路有 JK触发器、移位寄存器、同步十进制
可逆计数器、同步 60 进制计数器。 4—24—2 线优先编码器线优先编码器library ieee;
use ieee.std_logic_1164.all;
entity encoder is
port(in0,in1,in2,in3:in std_logic;
out0,out1:out std_logic);
end;
architecture behave of encoder is
signal ou:std_logic_vector (1 downto 0
);
begin
ou<="11" when in3='1' el
se
"10" when in2='1' else
"01" when in1='1' else
"00" when in0='1' else
"00";
out1<=ou(1); out0<=ou(0);
end behave;
一位十进制编码器一位十进制编码器library ieee;
use ieee.std_logic_1164.all;
entity decode is
port(in0,in1,in2,in3,in4,in5,in6,in7,in8,in9 : in
std_logic;
out_decode : out std_logic_vector(3 downto 0));
end decode;
architecture behave of decode is signal s_vec : std_logic_vector(9 downto 0) ;begin s_vec<= ( in9, in8, in7, in6, in5, in4, in3, in2, in1, in0 ) ; with s_vec select out_decode<= "1001" when "1000000000", -- 数字 9
"1000" when "0100000000", -- 数字 8"0111" when "0010000000", -- 数字 7"0110" when "0001000000", -- 数字 6
"0101" when "0000100000", -- 数字 5 "0100" when "0000010000", -- 数字 4 "0011" when "0000001000", -- 数字 3
"0010" when "0000000100", -- 数字 2 "0001" when "0000000010", -- 数字 1
"0000" when others; -- 数字 0end behave;
七段译码显示器七段译码显示器library ieee;
use ieee.std_logic_1164.all;
entity decoder is
port (d:in std_logic_vector(3 downto 0);
q:out std_logic_vector(6 downto 0));
end;
architecture behave of decoder is
begin
q<="1111011" when d="1001" else --译码显示 9
"1111111" when d="1000" else --译码显示 8
"1110000" when d="0111" else --译码显示 7
"1011111" when d="0110" else --译码显示 6
"1011011" when d="0101" else --译码显示 5
"0110011" when d="0100" else --译码显示 4
"1111001" when d="0011" else --译码显示 3
"1101101" when d="0010" else --译码显示 2
"0110000" when d="0001" else --译码显示 1
“1111110”; -- 其它情况显示 0
end behave;
JKJK 触发器触发器library ieee;use ieee.std_logic_1164.all;entity jkff is
port(clk,j,k : in std_logic;q,notq : out std_logic);
end jkff;
architecture behave of jkff is signal q_temp : std_logic;signal jk:std_logic_vector(1 downto 0);begin jk<=j&k; --注意此处连接符的使用process(clk,jk)begin
if (clk'event and clk='1') then if (jk="01") then q_temp<='0'; elsif (jk="10") then q_temp<='1'; elsif(jk="11") then q_temp<=not q_temp; end if; end if;q<=q_temp; notq<=not q_temp;
end process;end behave;
四位双向移位寄存器四位双向移位寄存器 library ieee;
use ieee.std_logic_1164.all;
entity shift is
port(clk,rst,load,left_right : in std_logic;
-- 时钟、复位、置数、移位控制信号 din : in std_logic_vector(3 downto 0);
-- 预置数输入信号 dout : inout std_logic_vector(3 downto 0));
-- 输出信号 end shift;
architecture behave of shift is constant len: integer:=3; begin process (clk,rst,load,left_right,din) begin if rst=’1’ then dout<=”0000”; --异步复位 elsif rising_edge(clk) then if (load='1') then dout<=din; --同步置数 elsif (left_right='0') then --循环右移 dout<=dout(0)&dout(len downto 1); elsif(left_right='1') then --循环左移
dout<=dout(len-1 downto 0)&dout(3); end if; end if;end process;end behave;
同步十进制可逆计数器同步十进制可逆计数器library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity count is
port(clk,rst,load,plus_sub : in std_logic;
din: in std_logic_vector(3 downto 0);
dout: buffer std_logic_vector(3 downto 0));
end count;
architecture behave of count is beginprocess(clk,rst,load,plus_sub,din)begin if (clk'event and clk='1') then if (rst='1') then dout<=(others=>'0'); --同步复位
elsif (load='1') then dout<=din; --同步置数 elsif (plus_sub='1') then --加法计数 if (dout=9) then dout<="0000";
else dout<=dout+1; end if;
elsif(plus_sub='0') then --减法计数 if (dout=0) then dout<="1001"; else dout<=dout-1; end if;
end if; end if; end process;end behave;
同步同步 6060 进制计数器进制计数器library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity cnt60 is
port(clk,rst : in std_logic;
qout : out std_logic_vector(7 downto 0));
end cnt60;
architecture behave of cnt60 is
signal qh,ql : std_logic_vector(3 downto 0);
Begin
process(rst,clk)
begin
if (rst='0') then ql<="0000"; qh<="0000"; --异步复位 elsif (clk'event and clk='1') then
if (ql=9) then ql<="0000";
if (qh=5) then qh<="0000";
else qh<=qh+1;
end if;
else ql<=ql+1;
end if;
end if;
qout<=qh&ql;
end process;
end behave;
状态机的基本结构和功能
状态译码器
状态寄存器
输出译码器
输入
反馈
输出
确定状态机的激励方式
记忆状态机的内部状况
确定状态机的输出方程
由输入和寄存器中状态共同决定
状态机设计状态机设计 数字系统控制单元通常用有限状态机( FSM )建模。 Moore
型有限状态机的输出只是有限状态机当前值的函数; Mealy 型状态机的输出为有限状态机当前值和有限状态机输入值的函数,两者差别很小。模型如图所示。
下面采用状态机设计一个一位比较器,比较两个一位串行二进制数 n1 , n2 的大小,二进制数序列由低位向高位按时钟节拍逐位输入。
分析:两数比较有三种结果: n1 = n2 设为状态 s1 ;输出为 y=00 ; n1 > n2 设为状态 s2 ;输出为 y=10 ; n1 <n2 设为状态 s3 ;输出为 y=01 ;输入有四种情况 , 分别为 00 , 01 , 10 , 11 。
11 . 双进程有限状态机描述如下:. 双进程有限状态机描述如下:entity state is
port ( n1, n2, clk: in std_logic; y: out std_logic_vector(1 downto 0));
end state;
architecture stamach of state is type statype is (s1, s2, s3); -- 自定义 statype 类型
signal present_state , next_state : statype; signal n: std_logic_vector(1 downto 0); begin n<=n1&n2;
sta_com: process (present_state, n)
begin
case present_state is
when s1=> y<=”00”; --现态为 s1 时 , 输出” 00”
if (n=”10”) then next_state<=s2; -- 输入为” 10”, 次态为 s
2
elsif (n=”01”) then next_state<=s3; -- 输入为” 01”, 次态为s3
else next_state<=s1;
end if;
when s2=> y<=”10”;
if (n=”01”) then next_state<=s3;
elsif (n=”00” or n=”11”) then next_state<=s1;
else next_state<=s2;
end if;
when s3=> y<=”01”;
if (n=”10”) then next_state<=s2;
elsif (n=”00” or n=”11”) then next_state<=s1;
else next_state<=s3;
end if;
end case;
end process sta_com; state_clk: process(clk) -- 第二个进程确定转换时刻为上升沿
begin if (clk’event and clk=’1’) then
present_state<=next_state;end if;
end process state_clk;end architecture stamach;
22 .单进程状态机结构体描述如下:.单进程状态机结构体描述如下:architecture stamach of state is
type statype is (s1, s2, s3); -- 自定义 statype 类型signal state : statype;
signal n:std_logic_vector(1 downto 0);begin n<=n1&n2;
process (clk, n) begin
if rising_edge(clk) thencase state is
when s1=> if (n=”10”) then state<=s2; --根据不同的输入改变 state 的状态
elsif (n=”01”) then state<=s3;else state<=s1;
end if;
hen s2=> if (n=”01”) then state<=s3;elsif (n=”00” or n=”11”) then state<=s1;
else state<=s2;end if;
when s3=>if (n1=’1’ and n2=’0’) then state<=s2;
elsif (n=”00” or n=”11”) then state<=s1;else state<=s3;end if;
end case;end if;
end process ;with select --根据 state 的不同状态决定不同的输出
值 y<=”00” when s1, “01” when s2, “10” when s3;
end behave;
33 .状态编码描述风格.状态编码描述风格architecture stamach of state is
signal state : std_logic_vector(1 downto 0);
-- 不采用自定义类型,直接对 state 编码constant s1 : std_logic_vector(1 downto 0) :=”00”;
constant s2 : std_logic_vector(1 downto 0) :=”01”;
constant s3 : std_logic_vector(1 downto 0) :=”11”;
signal n : std_logic_vector(1 downto 0);
begin
n<=n1&n2;
process (clk, n)
begin
if rising_edge(clk) then
case state is
when s1=>
if (n=”10”) then state<=s2; --根据不同的输入改变 state 的值elsif (n=”01”) then state<=s3;
else state<=s1;
end if;
when s2=>
if (n=”01”) then state<=s3;
elsif (n=”00” or n=”11”) then state<=s1;
else state<=s2;
end if;
when s3=>
if (n1=’1’ and n2=’0’) then state<=s2;
elsif (n=”00” or n=”11”) then state<=s1;
else state<=s3;
end if;
end case;
end if;
end process ;
y<=state;
end behave;
Recommended