You are on page 1of 64

太原理工大学 夏路易

第1章 硬 件描 述语言 VHD L

数字系统设计分为硬件设计和软件设计, 但是随着计算机技术、超大规模集成电路
(CPLD、FPGA)的发展和硬件描述语言(HDL, Hardware Description Language)的出现,
软、硬件设计之间的界限被打破,数字系统的硬件设计可以完全用软件来实现,只要掌握
了 HDL 语言就可以设计出各种各样的数字逻辑电路。

1.1 老的硬件设 计方法


老的硬件设计方法有如下几个特征:
(1)采用自下而 上的设计 方法
使用该方法进行硬件设计是从选择具体元器件开始,并用这些元器件进行逻辑电路设
计,从而完成系统的硬件设计,然后再将各功能模块连接起来,完成整个系统的硬件设计,
(2)采用通用逻 辑元器件
通常采用 74 系列和 CMOS4000 系列的产品进行设计
(3)在系统硬件 设计的后 期进行调 试和仿真
只有在部分或全部硬件电路连接完毕,才可以进行电路调试,一旦考虑不周到,系
统设计存在较大缺陷,则要重新设计,使设计周期延长。
(4)设计结果是 一张电路 图
当设计调试完毕后,形成电原理图,该图包括元器件型号和信号之间的互连关系等
等。
老的硬件设计方法已经使用了几十年,是广大电子工程师熟悉和掌握的一种方法,但
是现在这种方法老了,不仅方法老了,就连使用的元器件也老了。

1.2 使用 HTL 的硬件 设计方法


所谓硬件描述语言,就是利用一种人和计算机都能识别的语言来描述硬件电路的功能,
信号连接关系及定时关系,它可以比电原理图更能表示硬件电路的特性。
该方法有如下特征:
(1)支持自顶向 下的设计 方法
所谓自顶向下的设计方法就是从系统的总体要求出发,自顶向下分三个层次对系统硬
件进行设计。
第一个层次是行为描述,所谓行为描述,实际就是对整个系统的数学模型的描述,在
行为描述阶段,并不真正考虑其实际操作和算法怎么实现,而是考虑系统的结构和工作过
1
太原理工大学 夏路易

程是否能达到系统设计规格书的要求。
第二个层次是数据流描述,又称为寄存器描述或 RTL 方式描述,该描述比行为描述更
注重硬件的具体实现,通过该描述可以导出系统的逻辑表达式,为逻辑综合作准备,当然
进行逻辑综合和逻辑综合工具的能力有关,当然设计人员还必须了解逻辑综合工具的说明
和规定,
第三个层次为逻辑综合。该层次把 RTL 描述的程序转换成基本逻辑元件表示的文件,该
文件就象老的设计方法中的电原理图。
(2)采用大量的 ASIC 芯片
(3)早期仿真以 确定系统 的可行性
(4)使设计更容 易
只需写出系 统的 HDL 源程序 文件,其 它由计算 机去做
(5)全部设计文 件就是 HDL 源程序文件

1.3 V HTL 硬件设计语 言


当前 ASIC 制造商都自己开发了 HDL 语言,但是都不通用,只有美国国防部开发的
VHDL 语言成为了 IEEE. STD_1076 标准,并在全世界得到了承认。
该语言集成了各种 HDL 语言的优点,使数字系统设计更加简单和容易。VHDL 语言是一
个规模庞大的语言,在使用它之前完全学会它是很难的,本书介绍的只是 VHDL 语言的一部分。

1.4 VHD L 语言的 基本结构


VHDL 语言通常包含实体(Entity),构造体(Architecture),配置(Configuration),
包集合(Package),和库(Library)五部分.其中实体用于描述所设计的系统的外部接口信
号;构造体用于描述系统内部的结构和行为;建立输入和输出之间的关系;配置语句安装
具体元件到实体—结构体对,可以被看作是设计的零件清单;包集合存放各个设计模块共
享的数据类型、常数和子程序等;库是专门存放预编译程序包的地方。如下详细介绍。

1.4 .1 基本设计单 元
VHDL 的基本设计单元就是实体,无论数字电路复杂还是简单,都是由实体和构造体
组成。
(1) 实体说 明
实体说明有如下结构:
ENTITY 实体名 IS
[端口说明]
END 实体名;
(VHDL 语言中不分大小写字母)
2
太原理工大学 夏路易

其中:
端口说明是对设计实体中输入和输出借口进行描述,格式如下:
PORT(端口名(,端口名):方向 数据类型名;


端口名(,端口名):方向 数据类型名);
端口名是赋予每个系统引脚的名称,一般用几个英文字母组成。
端口方向是定义引脚是输入还是输出,见下表:
方向 说明
IN 输入到实体
OUT 从实体输出输出
INOUT 双向
BUFFER 输出(但可以反馈到实体内部)
LINKAGE 不指定方向

常用的端口数据类型有两种:BIT 和 BIT_VECTOR,当端口被说明为 BIT 时,只能取值


“1”或“0”,
当端口被说明为 BIT_VECTOR 时,它可能是一组二进制数。
例:
PORT(n0, n1, select: IN BIT;
q: OUT BIT;
bus: OUT BIT_VECTOR(7 DOWNTO 0));
本例中,n0, n1, select 是输入引脚,属于 BIT 型,q 是输出引脚,BIT 型,bus 是
一组 8 位二进制总线,属于 BIT_VECTOR,
例:
LIBRARY IEEE;
USE IEEE.STD_LOGIC.1164.ALL;
ENTITY mm IS
PORT(n0,n1,select: IN STD_LOGIC;
Q : OUT STD_LOGIC;
Bus : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END mm;
在此例中端口数据类型取自 IEEE 标准库(该库中有数据类型和函数的说明),其中
STD_LOGIC 取值为“0”,“1”,“X”和“Z”。
因为使用了库所以在实体说明前要增加库说明语句。

3
太原理工大学 夏路易

(2) 构造体
构造体是实体的一个重要部分,每一个实体都有一个或一个以上的构造体。
1) 一般说明
构造体格式如下:
ARCHITECTURE 构造体名 OF 实体名 IS
[定义语句] 内部信号,常数,数据类型,函数等的定义
BEGIN
[并行处理语句]
END 构造体名;
例:
ENTITY nax IS
PORT(a0,a1 : IN BIT;
Sel : IN BIT;
Sh : OUT BIT);
END nax;
ARCHITECTURE dataflow OF nax IS
BEGIN
sh<=(a0 AND sel) OR (NOT sel AND a1);
END dataflow;
构造体描述设计实体的具体行为,它包含两类语句:
 并行语句 并行语句总是在进程语句(PROCESS)的外部,该语句的执行与书写顺
序无关,总是同时被执行
 顺序语句 顺序语句总是在进程语句(PROCESS)的内部,从仿真的角度,该语句
是顺序执行的
一个构造体包含几个类型的子结构描述,这些描述是:
* BLOCK 描述(块描述)
* PROCESS 描述(进程描述)
* SUNPROGRAMS 描述(子程序描述)

2) BLOCK 语句描述
使用 BLOCK 语句描述的格式如下:
块标号:BLOCK
BEGIN


4
太原理工大学 夏路易

END BLOCK 块标号:

例: 二选一电路
ENTITY mux IS
PORT (d0,d1,sel: IN BIT;
q: OUT BIT);
END mux;
ARCHITECTURE connect OF mux IS
SIGNAL tmp1,tmp2,tmp3: BIT;
BEGIN
cale:
BLOCK
BEGIN
tmp1<=d0 AND sel;
tmp2<=d1 AND (NOT sel);
tmp3<=tmp1 OR tmp2;
q<=tmp3;
END BLOCK cale;
END connect;
在对程序进行仿真时,BLOCK 中的语句是并行执行的,与书写顺序无关,这一点和构
造体中直接写的语句是一样的。

3) 进程(PROCESS)描述
进程描述的格式如下:
[进程名]:PROCESS(信号 1,信号 2,。。。 )
BEGIN


END PROCESS 进程名;
* 一般用于组合电路进程模式:
__进程标记:
PROCESS (__信号名, __信号名, __信号名)
VARIABLE __变量名 : STD_LOGIC;
VARIABLE __变量名 : STD_LOGIC;
BEGIN
5
太原理工大学 夏路易

-- 指定信号
-- 指定变量
-- 过程调用
-- 如果语句
-- CASE 语句
-- 循环语句
END PROCESS __进程标记;
* 用于时序电路进程模式:
__进程标记:
PROCESS (__信号名, __信号名, __信号名)
VARIABLE __变量名 : STD_LOGIC;
VARIABLE __变量名 : STD_LOGIC;
BEGIN
WAIT UNTIL __时钟信号 = '1';
-- 指定信号
-- 指定变量
-- 过程调用
-- 如果语句
-- CASE 语句
-- 循环语句
END PROCESS __进程标记;
例:
ENTITY mux1 IS
PORT (d0,d1,sel: IN BIT;
q : OUT BIT);
END mux1;
ARCHITECTURE connect OF mux1 IS
BEGIN
cale:
PROCESS(d0,d1,sel)
VARIABLE tmp1,tmp2,tmp3 : BIT;--在进程中定义的变量
BEGIN
tmp1:=d0 AND sel; --输入端口向变量赋值
tmp2:=d1 AND (NOT sel);
tmp3:=tmp1 OR tmp2;
6
太原理工大学 夏路易

q<=tmp3;
END PROCESS cale;
END connect;
在 PROCESS 中的语句是顺序执行的,这一点和 BLOCK 中的语句是不一样的。
当 PROCESS 所带的信号量发生变化时,PROCESS 中的语句就会执行一遍。

4)子程序描述
子程序的概念和其它高级程序中子程序的概念相同,在 VHDL 中有两种类型:
 过程(Procedure)
 函数(Function)
1. 过程的格式:
PROCEDURE 过程名(参数 1,参数 2。。。。) IS
[定义变量语句]
BEGIN
[顺序处理语句]
END 过程名;
例:
PROCEDURE vector_to_int
(z : IN STD_LOGIC_VECTOR;
x_flag : OUT BOOLEAN;
q : IN INTEGER) IS
BEGIN
q:=0;
x_flag:=FALSE;
FOR i IN z RANGE LOOP
q:=q*2;
IF(z(i)=1) THEN
q:=q+1;
ELSEIF (z(i)/=10) THEN
x_flag:=TRUE;
END IF;
END LOOP;
END vector_to_int;
在过程中,语句是顺序执行的。

7
太原理工大学 夏路易

2.函数
函数的格式:
FUNCTION 函数名(参数 1,参数 2。。。。) RETURN 数据类型名 IS
[定义变量语句]
BEGIN
[顺序处理语句]
RETURN [返回变量名];
END 函数名;
在 VHDL 语言中函数的参数都是输入信号,
例:
FUNCTION min(x,y:INTEGER ) RETURN INTEGER IS
BEGIN
IF X<Y THEN
RETURN(x);
ELSE
RETURN(y);
END IF;
END min;

1.4.2 2 包、库和配 置

(1) 库
库是经编译后的数据的集合,它存放包定义、实体定义、构造定义和配置定义。
在设计单元内的语句可以使用库中的结果,所以,库的好处就是设计者可以共享已经
编译的设计结果,在 VHDL 中有很多库,但他们相互独立。
IEEE 库:在 IEEE 库中有一个 STD_LOGIC 的包,它是 IEEE 正式认可的包。
STD 库:STD 库是 VHDL 的标准库,在库中有名为 STANDARD 的包,还有 TEXTIO 包。若使用
STANDARD 包中的数据可以不按标准格式说明,但是若使用 TEXTIO 包,则需要按照如下格
式说明:
LIBRARY STD;
USE STD.TEXTIO.ALL
另外还有 ASIC 库、WORK 库和用户自定义库等。
库的使用:
在使用库之前,一定要进行库说明和包说明,库和包的说明总是放在设计单元的前面:
LIBRARY 库名;
8
太原理工大学 夏路易

USE LIBRARY name.package.name.ITEM.name


例:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL
该例说明要使用 IEEE 库中的 1164 包中所有项目
库的作用范围:
库的作用范围从一个实体说明开始到它所属的结构体、配置为止,当有两个实体时,
第二个实体前要另加库和包的说明。

(2) 包
通常在一个实体中对数据类型、常量等进行的说明只可以在一个实体中使用,为使这
些说明可以在其它实体中使用,VHDL 提供了程序包结构,包中罗列 VHDL 中用到的信号定
义、常数定义、数据类型、元件语句、函数定义和过程定义,它是一个可编译的设计单元,也
是库结构中的一个层次,使用包时可以用 USE 语句说明,例如:
USE IEEE.STD_LOGIC_1164.ALL
程序包分为包头和包体,包结构的格式如下:
1) 包头格式:
PACKAGE 包名 IS
[说明语句]
END 包名
包头中列出所有项的名称。
2) 包体格式:
PACKAGE BODY 包名 IS
[说明语句]
END 包名;
包体给出各项的具体细节。
例:包头
USE STD.STD.LOGIC.ALL
PACKAGE logic IS
TYPE three_level_logic IS (‘0’,’1’,’z’); //数据类型项目
CONSTANT unknown_value : three_level_logic :=’0’;//常数项目
FUNCTION invert (input: three_level_logic)//函数项目
RETURN three_level_logic;
END logic;
例:包体
9
太原理工大学 夏路易

PACKAGE BODY logic IS


FUNCTION invert (input: three_level_logic)//函数项目描述
BEGIN
CASE input IS
WHEN ‘0’ => RETURN ‘1’;
WHEN ‘1’ => RETURN ‘0’;
WHEN ‘Z’ => RETURN ‘Z’;
END CASE;
END invert;
END logic
该包使用例:
USE logic.three_level_logic, logic.invert; //使用数据类型和函数两个项目
ENTITY inverter IS
PORT(x: IN three_level_logic ;
y: OUT three_level_logic);
END inverter;
ARCHITECTURE inverter_body OF inverter IS
BEGIN
kk:
PROCESS
BEGIN
Y<=invert(x) AFTER 10ns;
WAIT ON x;
END PROCESS;
END inverter_body;

(2) 配置
用于在多构造体中的实体中选择构造体,例如,在做 RS 触发器的实体中使用了两个构
造体,目的是研究各个构造体描述的 RS 触发器的行为性能如何,但是究竟在仿真中使用哪
一个构造体的问题就是配置问题。
配置语句格式:
CONFIGURATION 配置名 OF 实体名 IS
[说明语句]
END 配置名;
例:最简单的配置
10
太原理工大学 夏路易

CONFIGURATION 配置名 OF 实体名 IS


 FOR 被选构造体名
END FOR;
END 配置名;  
例:
ENTITY rs IS
PORT(set,reset:IN BIT;
q,qb: BUFFER BIT);
END rs;
ARCHITECTURE rsff1 OF rs IS
COMPONENT nand2
PORT(a,b: IN BIT;
c: OUT BIT);
END COMPONENT;
BEGIN
U1:nand2 PORT MAP(a=>set, b=>qb, c=>q)
U2:nand2 PORT MAP(a=>reset, b=>q, c=>qb)
END rsff1;

ARCHITECTURE rsff2 OF rs IS
BEGIN
q<=NOT(qb AND set);
qb<=NOT(q AND reset);
END rsff2
两个构造体,可以用配置语句进行设置:
CONFIGRATION rscon OF rs IS //选择构造体 rsff1
FOR rsff1
END FOR;
END rscon;

1.4.3 VHDL 中使用 的数据类 型和运算 操作


VHDL 可以象其它高级语言一样定义数据类型,但还可以用户自己定义数据类型。

(1) 信号、 常量和变 量


信号:通常认为信号是电路中的一根线
11
太原理工大学 夏路易

常数:可以在数字电路中代表电源、地线等等
变量:可以代表某些数值
1.常数
常数的描述格式:
CONSTANT 常数名:数据类型:=表达式
例:
CONSTANT Vcc: REAL:=5.0;
CONSTANT DALY: TIME:=100ns;
CONSTANT FBUS: BIT_VECTOR:=”0101”;
2.变量
变量只能在进程、函数和过程中使用,一旦赋值立即生效。
变量的描述格式:
VARIABLE 变量名:数据类型 约束条件:=表达式
例:
VARIABLE x, y: INTEGER;
VARIABLE count: INTEGER RANGE 0 TO 255:=10;
3.信号
信号除了没有方向的概念以外几乎和端口概念一致。
信号的描述格式:
SIGNAL 信号名:数据类型 约束条件:=表达式
例:
SIGNAL sys_clk: BIT:=’0’;
SIGNAL ground: BIT:=’0’
在程序中,信号值输入信号时采用代入符”<=”,而不是赋值符“:=”,同时信号可以
附加延时。
信号传送语句:
s1<=s2 AFTER 10ns
信号是一个全局量,可以用来进行进程之间的通信
4.信号与变量的区别
信号赋值可以有延迟时间,变量赋值无时间延迟
信号除当前值外还有许多相关值,如历史信息等,变量只有当前值
进程对信号敏感,对变量不敏感
信号可以是多个进程的全局信号,但变量只在定义它之后的顺序域可见
信号可以看作硬件的一根连线,但变量无此对应关系

12
太原理工大学 夏路易

1.4.4 VHDL 中的数据类 型


(1)标准数据类 型
1.整数(INTEGER)
范围:-2147483547---2147483646
2.实数(REAL)
范围:-1.0E38---1.0E38
书写时一定要有小数。
3.位(BIT)
在数字系统中,信号经常用位的值表示,位的值用带单引号的‘1’和‘0’来表示
明确说明位数值时:BIT‘(‘1’)
4.位矢量(BIT_VECTOR)
位矢量是用双引号括起来的一组位数据
“010101”
5.布尔量(BOOLEAN)
只有“真”和“假”两个状态,可以进行关系运算
6.字符(CHARACTER)
字符量通常用单引号括起来,对大小写敏感
明确说明 1 是字符时:
CHARACTER‘(‘1’)
7.字符串(STRING)
字符串是双引号括起来的一串字符:
“laksdklakld”
8.时间(TIME)
时间的单位:fs,ps,ns,ms,sec,min,hr
例: 10 ns
整数数值和单位之间应有空格
9.错误等级(SEVERITY LEVEL)
用来表示系统的状态,它共有 4 种:
NOTE(注意)
WARNING(警告)
ERROR(错误)
FAILURE(失败)
10. 大于等于零的整数(NATURAL)、正整数(POSITIVE)
只能是正整数
数据除定义类型外,有时还需要定义约束范围。
13
太原理工大学 夏路易

例:
INTEGER RANGE 100 DOWNTO 0
BIT_ VECTOR (3 DOWNTO 0)
REAL RANGE 2.0 TO 30.0

(2) 用户定 义的数据 类型


用户定义的数据类型的一般格式:
TYPE 数据类型名 {,数据类型名} 数据类型定义
不完整的数据类型格式:
TYPE 数据类型名 {,数据类型名};
可由用户定义的数据类型为:
* 枚举(ENUMERATED)
格式:TYPE 数据类型名 IS(元素、元素、…);
例 1: TYPE week IS(Sun,Mon,Tue,wed,Thu,Fri,Sat);
例 2: TYPE STD_LOGIC IS
(‘U’,’X’,’0’,’1’,’Z’,’W’,’L’,’H’,’-‘);
* 整数(INTEGER)
格式:TYPE 数据类型名 IS 数据类型定义 约束范围
例:TYPE digit IS INTEGER RANGE 0 TO 9
* 实数(REAL)
格式:TYPE 数据类型名 IS 数据类型定义 约束范围
例:TYPE current IS REAL RANGE -1E4 TO 1E4
* 数组(ARRAY)
格式:TYPE 数据类型名 IS ARRAY 范围 OF 原数据类型名;
例:TYPE word IS ARRAY (1 TO 8) OF STD_LOGIC;
TYPE word IS ARRAY (INTEGER 1 TO 8) OF STD_LOGIC;
TYPE instruction IS (ADD,SUB,INC,SRL,SRF,LDA,LDB);
SUBTYPE digit IS INTEGER 0 TO 9;
TYPE indflag IS ARRAY (instruction ADD TO SRF) OF digit;
数组常在总线、ROM 和 RAM 中使用。
* 时间(TIME)
格式: TYPE 数据模型名不副实 IS 范围
UNITS 基本单位
单位;
END UNITS;
14
太原理工大学 夏路易

TYPE time RANGE –1E18 TO 1E18


UNITS
fs;
ps=1000 fs;
ns=1000 ps;
us=1000 ns;
ms=1000 us;
sec=1000 ms;
min=60 sec;
hr=60 min;
END UNITS;
* 记录(RECODE)
将不同的数据类型放在一块,就是记录类型数据
格式:TYPE 数组类型名 IS RECORD
元素名:数据类型名;
元素名:数据类型名;


END RECORD;
例:TYPE bank IS RECORD
addr0: STD_LOGIC_VECTOR(7 DOWNTO 0);
addr1: STD_LOGIC_VECTOR(7 DOWNTO 0);
r0: INTEGER;
END RECORD;
存取(ACCESS)
文件(FILE)

(3) 数据类 型的转换


数据类型转换函数有 VHDL 语言的包提供,例如:STD_LOGIC_1164,STD_LOGIC_ARITH 等

转换函数见表:
函数 说明
STD _LOG IC_1 164 包

TO_STDLOGICVECTOR(A) 由 BIT_VECTOR 转换成 STD_LOGIC_VECTOR

15
太原理工大学 夏路易

TO_BITVECTOR(A) 由 STD_LOGIC_VECTOR 转换成 BIT_VECTOR


TO_LOGIC(A) 由 BIT 转换成 STD_LOGIC
TO_BIT(A) 由 STD_LOGIC 转换成 BIT
STD _LOG IC_A RITH 包

CONV_STD_LOGIC_VECTOR(A,位长) 由 INTEGER,UNSIGNED 和 SIGNED 转换成


CONV_INTEGER(A) STD_LOGIC_VECTOR
由 UNSIGNED 和 SIGNED 转换成 INTEGER
STD _LO GIC_ UNSI GNED 包

CONV_INTEGER STD_LOGIC_VECTOR 转换成 INTEGER

例:由 STD_BIT_VECTOR 转换成 INTEGER


LIBRARY IEEE
USE IEEE.STD_LOGIC_1164.ALL
USE IEEE.STD_LOGIC_UNSIGNED.ALL
ENTITY add5 IS
PORT(num: IN STD_LOGIC_VECTOR(2 DOWNTO 0);


);
END add5;
ARCHITECTURE rtl OF add5 IS
SIGNAL in_num: INTEGER RANGE 0 TO 5;


BEGIN
  In_num<=CONV_INTEGER(num);
END rtl;

(5)有关 BIT _VEC TOR 和 STD_B IT_V ECTO R 的语句例:


SIGNAL a: BIT_VECTOR(11 DOWNTO 8);
SIGNAL b: STD_LOGIC_VECTOR(11 DOWNTO 0);
a<=X”A8”; 十六进制可以赋予位矢量
b<=X”A8”; 十六进制不可以赋予逻辑矢量,所以此句错,逻辑量中只能赋予二进
16
太原理工大学 夏路易


b<=TO_STDLOGICVECTOR(X”AF7”);十六进制变换
b<=TO_STDLOGICVECTOR(O”5177”); 八进制变换
b<=TO_STDLOGICVECTOR(B”1010_1111_0111”); 三位二进制变换

(6)IEEE 标准“ STD _LOG IC” 和” STD_L OGIC _VEC TOR”


1993 年制定的标准 IEEE STD1164 对 STD_LOGIC 的值做如下规定:
‘U’初始值
‘X’不定
‘0’0
‘1’1
‘Z’高阻
‘W’弱信号不定
‘L’ 弱信号 0
‘H’ 弱信号 1
‘-’不可能情况

1.4 .5 VHDL 语言的运算 操作符

优先级别 类型 操作符 说明

17
太原理工大学 夏路易

高 逻辑运算符 AND 逻辑与


OR 逻辑或
NAND 逻辑与非
NOR 逻辑或非
XOR 逻辑异或
关系运算符 = 等号
/= 不等号
< 小于
> 大于
<= 小于等于
>= 大于等于
加、减、并置运 + 加
算符 - 减
& 并置
正负运算符 + 正
- 负
乘除法运算符 * 乘
/ 除
MOD 取模
REM 取余
** 指数
ABS 取绝对值
NOT 取反

(1) 逻辑运 算符
要求运算符左右的数据类型必须相同,
例:x<=(a AND b) OR (NOT c AND d);
x<=b AND a AND d AND e;
x<=b OR c OR d OR e;
x<=a XOR d XOR e;
a<=(x1 AND x2) OR (y1 AND y2);

(2) 算数运 算符
18
太原理工大学 夏路易

在使用乘法运算符时,应该特别慎重,因为它可以使逻辑门数大大增加。

(3) 关系运 算符
应该注意小于等于<=和代入运算符的不同(从上下文区别)

(4) 并置运 算符
并置运算符 ”&” 用于位连接,
例如: y(0)=b(0)&en
y(1)=b(1)&en
y(2)=b(2)&en
y(3)=b(3)&en
y(4)=a(0)
y(5)=a(1)
y(6)=a(2)
y(7)=a(3)
从上可以看出 a,b 是四位长度的矢量,而 y 的位长是 7 位,上述情况可以表示成:
tmp_b<=b AND (en&en&en&en);
y<= a&tmp_b;
若是位连接,可以简单写为:
tmp_b<=b AND (en,en,en,en);

1.4.5 VHDL 语言构造体 的描述方 式


有三种描述方式:行为描述,RTL 描述和 ASIC 描述,采用后两种描述方式可以进行逻
辑综合。

(1)行为描述
描述数字系统的行为,主要用于仿真和系统工作原理的研究。下面介绍一些专用语句。
1) 代入语句
格式: 信号量<=敏感信号量表达式;
例如: z<=a NOR(b NAND c);
该例中有三个敏感量,无论哪一个发生变化都可以使 z 变化。
具有时间延迟的代入语句:
a<=b AFTER 10 ns
表示当 b 发生变化 10 ns 后 a 才变化。
19
太原理工大学 夏路易

例:与门电路
ENTITY and2 IS
PORT(a,b : IN BIT;
c : OUT BIT);
END and2;
ARCHITECTURE and2_behave OF and2 IS
BEGIN
c<=a AND b;
END and2_behave;
2)延时语句
VHDL 中有两种延时语句:惯性延时和传输延时。
*惯性延时
VHDL 中惯性延时是缺省的,因为逻辑硬件电路总是有时间延迟的,若延迟时间是
20ns,那末输入信号时间若小于 20ns,则输出信号将不跟随输入信号的变化。
有时为使延迟时间更逼真实际电路,就专门设置惯性时间:
b<=a AFTER 10 ns;
* 传输延时
传输延时常代表总线、连接线的延迟时间,该时间必须专门说明。该传输延时只对信号
起纯延时作用。
例: b<=TRANSPORT a AFTER 20 ns;

(2) 数据流 描述方式


数据流描述方式是一种可以进行逻辑综合的描述方式,由于要进行逻辑综合所以对使
用的语句有一定的限制,VHDL 中的每一个命令和语句都对逻辑综合能力进行了定义,要进
行逻辑综合的设计实体就要使用有逻辑综合能力的命令和语句。
例:四选一电路
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY mux42 IS
PORT(input : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
Sel : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
Y : OUT STD_LOGIC);
END mux42;
ARCHITECTURE app OF mux42 IS
20
太原理工大学 夏路易

BEGIN
y<=input(0) WHEN sel=0 ELSE
input(1) WHEN sel=1 ELSE
input(2) WHEN sel=2 ELSE
input(3);
END app;
使用数据流描述方式应该注意的问题:
1.‘X’状态的传递问题
有时‘X’状态会逐级传递,造成系统的输出为不确定或者错误,所以要在设计中考虑
‘X’状态对输出的影响。
2. 一些限制
*禁止在一个进程中使用两个寄存器
*在 IF 语句描述寄存器时,禁止 ELSE 项
*在寄存器描述中,禁止将变量代入信号
*关连性强的信号应该放在一个进程中

(3) 结构描 述方式


注重调用已有的元件、元件或门级电路之间的连线是结构描述的特点,结构描述可以提
高设计效率.
1) 元件声明语句:
元件声明语句用于调用已生成的元件,这些元件可能在库中,也可能是预先编写的元件
实体描述.
元件语句的格式:
COMPONENT 元件名
PORT 说明; 端口说明
END COMPONENT;
元件语句可以在 ARCHITECTURE,PACKAGE 和 BLOCK 的说明部分.
2) 元件调用:
格式: 标号名:元件名 PORT MAP(信号,…);
两层信号之间的关系为映射关系,该映射有两种:
位置映射例:
有一元件的端口说明为:
port (a,b: in bit;
c: out bit);
调用该元件时:
21
太原理工大学 夏路易

u2: 元件名 port map(n1,n2,m);


这里 n1 对应 a,n2 对应 b,m 对应 c.
名称映射例:
该映射就是将库中已有模块的端口名称,赋予设计中的信号名.
U2: 元件名 port map(a=>n1.b=>n2,c=>m);

1.4.6 VHDL 语言的主要 描述语句

(1) 顺序描 述语句


顺序描述语句只能用在进程和子程序中,它和其他高级语言一样,其语句是按照语句的
出现的顺序加以执行的.如下分别介绍有关的顺序描述语句.
1. WAIT 语句
进程在执行过程中总是处于两种状态:执行或挂起,进程的状态变化受等待语句的控制,
当进程执行到等待语句,就被挂起,并等待再次执行进程.
等待语句的格式:
*WAIT 无限等待
*WAIT ON 敏感信号变化
格式:WAIT ON 信号[,信号]
例: PROCESS(a,b)
BEGIN
y<=a AND b;
END PROCESS;
该例中的进程与下例中进程相同:
例: PROCESS
BEGIN
y<=a AND b;
WAIT ON a,b;
END PROCESS;
*WAIT UNTIL 直到条件满足
格式: WAIT UNTIL 布尔表达式
当进程执行到该语句时,被挂起;若布尔表达式为真时,进程将被启动.
例: WAIT UNTIL ((x*10)<100)
*WAIT FOR 等到时间到
格式: WAIT FOR 时间表达式
当进程执行到该语句时,被挂起;等待一定的时间后,进程将被启动.
22
太原理工大学 夏路易

例: WAIT FOR 20 ns
*多条件 WAIT 语句
例: WAIT ON nmi,interrupt UNTIL ((nmi=TRUE) OR (interrupt=TRUE)) FOR 5 us
该等待有三个条件:
第一,信号 nmi 和 interrupt 任何一个有一次刷新动作
第二, 信号 nmi 和 interrupt 任何一个为真
第三, 等待 5 us
只要一个以上的条件被满足,进程就被启动.
*超时等待
若在程序中所设置的等待条件永远不会满足,则进程就永远不能启动,为防止进入无限等待
情况,应做一些处理.
2. 断言语句(ASSERT)
格式: ASSERT 条件 [REPORT 输出信息][SEVERITY 级别]
执行到断言语句时,判断条件,若条件满足就继续执行,否则输出文字串和错误级别信息.
例: ASSERT (tiaojian=’1’)
REPORT “some thing wrong”
SEVERITY ERROR;
3. 信号代入语句
格式: 目的信号量<=信号量表达式
例: a<=b;
4. 变量赋值语句
格式: 目的变量:=表达式
例: c:=a+d
5. IF 语句
1) IF 的门闩控制
格式:IF 条件 THEN
顺序执行语句
END IF;
例:IF (a=’1’) THEN
c<=b;
END IF;
2) IF 语句的选择控制
格式一:IF 条件 THEN
顺序执行语句
ELSE
23
太原理工大学 夏路易

顺序执行语句
END IF;
格式二:IF 条件 THEN
顺序执行语句
ELSIF 条件 THEN
顺序执行语句


ELSIF 条件 THEN
顺序执行语句
ELSIF 条件 THEN
顺序执行语句
END IF;
6. CASE 语句
常用来描述总线、编码和译码的行为。
格式:
CASE 表达式 IS
WHEN 条件表达式=>顺序处理语句
END CASE;
其中 WHEN 的条件表达式可以有 4 种形式:
WHEN 值=>顺序处理语句
WHEN 值|值|值|…|值=>顺序处理语句
WHEN 值 TO 值=>顺序处理语句
WHEN OTHERS=>顺序处理语句

例:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY mux43 IS
PORT(a,b,i0,i1,i2,i3 :IN STD_LOGIC;
q : OUT STD_LOGIC);
END mux43;

ARCHITECTURE mux4_behave OF mux43 IS


SIGNAL sel: INTEGER RANGE 0 TO 3;
24
太原理工大学 夏路易

BEGIN
nn: PROCESS(a,b,i0,i1,i2,i3)
BEGIN
sel<=0;
IF (a='1') THEN
sel<=sel+1;
END IF;
IF (b='1') THEN
sel<=sel+2;
END IF;
CASE sel IS
WHEN 0 =>q<=i0;
WHEN 1 =>q<=i1;
WHEN 2 =>q<=i2;
WHEN 3 =>q<=i3;
END CASE;
END PROCESS nn;
END mux4_behave;

7. LOOP 语句
格式一:
[标号]: FOR 循环变量 IN 离散范围 LOOP
顺序处理语句
END LOOP [标号];
例: ASUM: FORi IN 1 TO 9 LOOP
sum=1+sum;
END LOOP ASUM;
例:8位奇偶校验电路
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY pc IS
PORT(a : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
y : OUT STD_LOGIC);
END pc;
ARCHITECTURE behave OF pc IS
25
太原理工大学 夏路易

BEGIN
cbc: PROCESS(a)
VARIABLE tmp: STD_LOGIC;
BEGIN
tmp:='0';
FOR i IN 0 TO 7 LOOP
tmp:=tmp XOR a(i);
END LOOP;
y<=tmp;
END PROCESS cbc;
END behave;
格式二:
[标号]: WHILE 条件 LOOP
顺序处理语句
END LOOP [标号];
在该语句中,如果条件为真,则进行循环,否则结束循环.
例:
sum:=0
abcd: WHILE (I<10) LOOP
sum:=I+sum;
I:=I+1;
END LOOP abcd;

8. NEXT 语句
在 LOOP 语句中用 NEXT 语句跳出循环.
格式: NEXT [标号][WHEN 条件];
NEXT 语句用于控制内循环的结束.
例:
PROCESS (a,b)
CONSTANT max_limit: INTEGER:=255
BEGIN
FOR I IN 0 TO max_limit LOOP
IF (done(I)=TRUE) THEN
NEXT;
ELSE done(I):=TRUE;
26
太原理工大学 夏路易

END IF;
q(I)<=a(I) AND b(I);
END LOOP;
END PROCESS;

9. EXIT 语句
EXIT 语句用于结束 LOOP 循环状态.
格式: EXIT [标号] [WHEN 条件]
例:
PROCESS(a)
VARIABLE int_a :INTEGER;
BEGIN
int_a:=a
FOR I=0 IN 0 TO max_limit LOOP
IF (int_a<=0) THEN
EXIT;
ELSE
int_a:=int_a-1;
q(I)<=3.1416/REAL(a*I);
END IF
END LOOP;
y<=q;
END PROCESS;

(2) 并发描 述语句


1. 进程语句
在一个构造体中多个 PROCESS 语句可以同时并行的执行,该语句有如下特点:
1)可以和其它进程语句同时执行,并可以存取构造体和实体中所定义的信号
2)进程中的所有语句都按照顺序执行
3)为启动进程,在进程中必须包含一个敏感信号表或 WAIT 语句
4)进程之间的通信是通过信号量来实现的
2. 并发信号代入
代入语句在进程中使用是顺序语句,但是在进程外即在构造体中使用就是并发语句,相当于
一个进程.
例:
27
太原理工大学 夏路易

ARCHITECTURE behave OF a_var IS


BEGIN
Output<=a(I);
END behave;
可以等效于:
ARCHITECTURE behave OF a_var IS
BEGIN
ss PROCESS(a,I)
BEGIN
Output<=a(I);
END PROCESS ss;
END behave;
信号代入语句的右边可以是算数表达式,也可以是逻辑表达式,还可以是关系表达式,
所以可以仿真加法器、乘法器、除法器、比较器和各种逻辑电路。
3. 条件信号代入
条件代入语句也是并发语句,它可以将符合条件的表达式代入信号量。
格式:目的信号量<=表达式 1 WHEN 条件 1
ELSE 表达式 2 WHEN 条件 2
ELSE 表达式 3 WHEN 条件 3
:
ELSE 表达式 n;

例:四选一电路
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY mux44 IS
PORT(i0,i1,i2,i3,a,b:IN STD_LOGIC;
q : OUT STD_LOGIC);
END mux44;
ARCHITECTURE aa OF mux44 IS
SIGNAL sel: STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
sel<=b & a;
q<= i0 WHEN sel="00" ELSE
i1 WHEN sel="01" ELSE
28
太原理工大学 夏路易

i2 WHEN sel="10" ELSE


i3 WHEN sel="11" ;
END aa;

4. 选择信号代入
格式: WITH 表达式样 SELECT
目的信号量<=表达式 1 WHEN 条件 1
表达式 2 WHEN 条件 2
:
表达式 n WHEN 条件 n;
该语句很象 CASE 语句.
例:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY mux45 IS
PORT(i0,i1,i2,i3,a,b :IN STD_LOGIC;
q : OUT STD_LOGIC);
END mux45;
ARCHITECTURE bb OF mux45 IS
SIGNAL sel: INTEGER range 0 to 3;
BEGIN
WITH sel SELECT
q<=i0 WHEN 0,
i1 WHEN 1,
i2 WHEN 2,
i3 WHEN 3;
sel<=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' ;
END bb;

5. 并发过程调用语句
过程调用语句可以并发执行,但要注意如下问题:
 并发过程调用是一个完整的语句,在它之前可以加标号
29
太原理工大学 夏路易

 并发过程调用语句应带有 IN,OUT 或 INOUT 的参数,他们应该列在过程名后的括号



 并发过程调用可以有多个返回值
例:
ARCHITECTURE….
BEGIN
vector_to_int(z,x_flag,q);
:
END;
等同于:
ARCHITECTURE….
BEGIN
PROCESS(z,q)
BEGIN
vector_to_int(z,x_flag,q);
:
END PROCESS;
END;

1.4.7 基本逻辑电 路设计

(1) 组合逻 辑电路


例1 2 输入与非门电路
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity xx1 is
port(a,b: in std_logic;
y: out std_logic);
end xx1;
architecture nand2pp OF xx1 is
begin
y<=a nand b;
end nand2pp;

例 2: 2 输入或非门
30
太原理工大学 夏路易

LIBRARY ieee;
use ieee.std_logic_1164.all;
entity nor2 is
port(a,b: in std_logic;
y: out std_logic);
end nor2;
architecture nor_behave of nor2 is
begin
y<=a nor b;
end nor_behave;

例3 2 输入异或门电路
library ieee;
use ieee.std_logic_1164.all;
entity xor2 is
port(a,b: in std_logic;
y: out std_logic);
end xor2;
architecture xor_behave of xor2 is
begin
y<=a xor b;
end xor_behave;

例 4 3-8 译码器
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity decoder38 is
port(a,b,c,g1,g2a,g2b: in std_logic;
y: out std_logic_vector(7 downto 0));
end decoder38;
architecture behave38 OF decoder38 is
signal indata: std_logic_vector(2 downto 0);
begin
indata<=c&b&a;
process(indata,g1,g2a,g2b)
31
太原理工大学 夏路易

begin
if(g1='1' and g2a='0' and g2b='0') then
case indata is
when "000"=>y<="11111110";
when "001"=>y<="11111101";
when "010"=>y<="11111011";
when "011"=>y<="11110111";
when "100"=>y<="11101111";
when "101"=>y<="11011111";
when "110"=>y<="10111111";
when "111"=>y<="01111111";
when others=>y<="XXXXXXXX";
end case;
else
y<="11111111";
end if;
end process;
end behave38;

例 5 优先编码器
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity prior is
port( input: in std_logic_vector(7 downto 0);
y: out std_logic_vector(2 downto 0));
end prior;
architecture be_prior OF prior is
begin
process(input)
begin
if(input(0)='0') then
y<="111";
elsif (input(1)='0') then
y<="110";
elsif (input(2)='0') then
32
太原理工大学 夏路易

y<="101";
elsif (input(3)='0') then
y<="100";
elsif (input(4)='0') then
y<="011";
elsif (input(5)='0') then
y<="010";
elsif (input(6)='0') then
y<="001";
elsif (input(7)='0') then
y<="000";
end if;
end process;
end be_prior;

例7 四选一选择器
LIBRARY ieee;
USE ieee.std_logic_1164.all;
entity mux4 is
port( input: in std_logic_vector(3 downto 0);
a,b: in std_logic;
y: out std_logic);
end mux4;
architecture be_mux4 OF mux4 is
signal sel: std_logic_vector(1 downto 0);
begin
sel<=b&a;
process(input,sel)
begin
if(sel="00") then
y<=input(0);
elsif (sel="01") then
y<=input(1);
elsif (sel="10") then
y<=input(2);
33
太原理工大学 夏路易

else
y<=input(3);
end if;
end process;
end be_mux4;

例8 :加法器
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
ENTITY adder IS
PORT (op1, op2 : IN UNSIGNED(7 downto 0);
result : OUT INTEGER);
END adder;
ARCHITECTURE maxpld OF adder IS
BEGIN
result <= CONV_INTEGER(op1 + op2);
END maxpld;

例9 半加器
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY half IS
PORT (a, b : IN std_LOGIC;
s,co : OUT std_LOGIC);
END half;
ARCHITECTURE half1 OF half IS
signal c,d :std_logic;
BEGIN
c<=a or b;
d<=a nand b;
co<=not d;
s<=c and d;
end half1;

34
太原理工大学 夏路易

例 10 全加器,由半加器组成,以元件方式调用.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY half IS
PORT (a, b : IN std_LOGIC;
s,co : OUT std_LOGIC);
END half;
ARCHITECTURE half1 OF half IS
signal c,d:std_logic;
BEGIN
c<=a or b;
d<=a nand b;
co<=not d;
s<=c and d;
end half1;

LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY full IS
PORT (a, b,cin : IN std_LOGIC;
s,co : OUT std_LOGIC);
END full;
ARCHITECTURE full1 OF full IS
component half
PORT (a, b : IN std_LOGIC;
s,co : OUT std_LOGIC);
end component;
signal u0_co,u0_s,u1_co:std_logic;
begin
u0:half port map(a,b,u0_s,u0_co);
u1:half port map(u0_s,cin,s,u1_co);
co<=u0_co or u1_co;
end full1;

例 10: 三态门
35
太原理工大学 夏路易

LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY tri IS
PORT (din, en : IN std_LOGIC;
dout : OUT std_LOGIC);
END tri;
ARCHITECTURE tri1 OF tri IS
BEGIN
tri_gate: process(din,en)
begin
if (en='1') then
dout<=din;
else
dout<='Z';
end if;
end process;
end tri1;

例 11 三态单向总线
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY bufs IS
PORT (din : IN std_LOGIC_vector(7 downto 0);
dout : OUT std_LOGIC_vector(7 downto 0) bus;
en : IN std_LOGIC);
END bufs;
ARCHITECTURE bufs1 OF bufs IS
BEGIN
process(en,din)
begin
if (en='1') then
dout<=din;
else
dout<="ZZZZZZZZ";
end if;
36
太原理工大学 夏路易

end process;
end bufs1;

(2) 时序电 路设计


1.时钟信号和复位信号
1) 时钟信号的描述
* 若进程的敏感信号是时钟信号,这时时钟信号出现在 PROCESS 后的括号中.
例: process (clock_signal)
begin
if (clock_edge_condition) then
signal_out<=signal_in
:
其它语句
:
end if;
end process;
* 在进程中用 WAIT ON 语句等待时钟
这样的电路没有敏感信号,进程通常停留在 WAIT ON 语句上,只有时钟信号到来且满足
一定条件时,其余语句才能执行.
例:
process
begin
wait on (clock_signal) until (clock_edge_condition)
signal_out<=signal_in;
:
其它语句
:
end process;
* 敏感表中只能有一个时钟信号
* wait on 语句只能放在进程的最前面或者最后面
* 时钟的边沿描述
描述时钟一定要指明是上升沿还是下降沿
上升沿到来的条件:
IF clk=’1’ AND clk’LAST_VALUE=’0’ AND clk’EVENT
下降沿到来的条件:
37
太原理工大学 夏路易

IF clk=’0’ AND clk’LAST_VALUE=’1’ AND clk’EVENT


关于时钟信号的总结:
IF clock_signal=current_value AND
clock_signal’LAST AND
clock_siganl’EVENT
可以简单写为:
IF clock_signal=clock_siganl’EVENT AND current_value

例 1:对于上升沿 D 触发器,其描述为:
process(clk,d)
begin
if(clk’event and clk=’1’) then
q<=d;
end if;
end process;
例 2:对于上升沿 D 触发器的另一描述为:
process
begin
wait until clk’event and clk=’1’;
q<=d;
end process;

2.复位信号
*同步复位
当复位信号有效且在给定的时钟边沿到来时,触发器才被复位.
例 1:
process (clock)
begin
if (clock_edge_condition) then
if (reset_condition) then
signal_out<=reset_value;
else
signal_out=signal_in;
:
其它语句
38
太原理工大学 夏路易

:
end if;
end if;
end process;
例 2:
process(clock)
if (clock’event and clock=’1’) then
if reset=’1’ then
count<=’0’;
else
count<=count+1;
end if;
end if;
end process;
此例中,敏感表中只有时钟信号,因为只有时钟到来时才能复位.
* 异步复位
只要复位信号有效,触发器就被复位,所以敏感表中除时钟信号外,还需要复位信号
例 1:
process(reset_signal,clock_signal)
begin
if (reset_signal) then
signal_out<=reset_value;
elsif (clock_event and clock_edge_condition) then
signal_out<=signal_in;
:
其它语句
:
end if;
end process;
例 2:
process(clock,reset)
begin
if reset=’1’ then
count<=’0’;
elsif clock’event and clock=’1’ then
39
太原理工大学 夏路易

count<=count+1;
end if;
end process;

3.触发器
1) D 锁存器
LIBRARY ieee;
use ieee.std_logic_1164.all;
entity dff1 is
port(clk,d: in std_logic;
q: out std_logic);
end dff1;
architecture dff1_behave of dff1 is
begin
process(clk)
begin
if (clk'event and clk='1') then
q<=d;
end if;
end process;
end dff1_behave;

2)异步复位 D 锁存器
LIBRARY ieee;
use ieee.std_logic_1164.all;
entity dff2 is
port(clk,d,reset: in std_logic;
q: out std_logic);
end dff2;
architecture dff2_behave of dff2 is
begin
process(clk,reset)
begin
if (reset='0') then
q<='0';
40
太原理工大学 夏路易

elsif (clk'event and clk='1') then


q<=d;
end if;
end process;
end dff2_behave;

3) 异步复位/置位 D 锁存器
LIBRARY ieee;
use ieee.std_logic_1164.all;
entity dff3 is
port(clk,d,reset,set: in std_logic;
q: out std_logic);
end dff3;
architecture dff3_behave of dff3 is
begin
process(clk,reset,set)
begin
if (set='0') then
q<='1';
elsif (reset='0') then
q<='0';
elsif (clk'event and clk='1') then
q<=d;
end if;
end process;
end dff3_behave;
在该例中,置位优先级最高,复位次之,时钟最低.

4) 同步复位/置位 D 触发器
LIBRARY ieee;
use ieee.std_logic_1164.all;
entity dff4 is
port(clk,d,reset,set: in std_logic;
q: out std_logic);
end dff4;
41
太原理工大学 夏路易

architecture dff4_behave of dff4 is


begin
process(clk)
begin
if (clk'event and clk='1') then
if (set='0') then
q<='1';
elsif (reset='0') then
q<='0';
else
q<=d;
end if;
end if;
end process;
end dff4_behave;

5) 异步复/置位 D 触发器
LIBRARY ieee;
use ieee.std_logic_1164.all;
entity jk is
port(clk,j,k,reset,set: in std_logic;
q,qb: out std_logic);
end jk;
architecture jk_behave of jk is
signal q_s,qb_s: std_logic;
begin
process(clk,reset,set,j,k)
begin
if (set='0')and (reset='1') then
q_s<='1';
qb_s<='0';
elsif (set='1')and (reset='0') then
q_s<='0';
qb_s<='1';
elsif (clk'event and clk='1') then
42
太原理工大学 夏路易

if (j='0') and (k='1') then


q_s<='0';
qb_s<='1';
elsif (j='1') and (k='0') then
q_s<='1';
qb_s<='0';
elsif (j='1') and (k='1') then
q_s<=not q_s;
qb_s<=not qb_s;
end if;
end if;
q<=q_s;
qb<=qb_s;
end process;
end jk_behave;

6)寄存器例
ENTITY reginf IS
PORT
(
d, clk, clr, pre, load, data : IN BIT;
q1, q2, q3, q4, q5, q6, q7 : OUT BIT
);
END reginf;

ARCHITECTURE maxpld OF reginf IS


BEGIN
--高电平时钟触发
PROCESS
BEGIN
WAIT UNTIL clk = '1';
q1 <= d;
END PROCESS;

--低电平时钟触发
43
太原理工大学 夏路易

PROCESS
BEGIN
WAIT UNTIL clk = '0';
q2 <= d;
END PROCESS;
--上升沿触发/同步清除
PROCESS (clk, clr)
BEGIN
IF clr = '1' THEN
q3 <= '0';
ELSIF clk'EVENT AND clk = '1' THEN
q3 <= d;
END IF;
END PROCESS;

--下降沿触发/同步清除
PROCESS (clk, clr)
BEGIN
IF clr = '0' THEN
q4 <= '0';
ELSIF clk'EVENT AND clk = '0' THEN
q4 <= d;
END IF;
END PROCESS;
--上升沿触发/同步预置”1”
PROCESS (clk, pre)
BEGIN
IF pre = '1' THEN
q5 <= '1';
ELSIF clk'EVENT AND clk = '1' THEN
q5 <= d;
END IF;
END PROCESS;

--上升沿触发/同步预置数据
44
太原理工大学 夏路易

-- Register with active-high Clock & asynchronous load


PROCESS (clk, load, data)
BEGIN
IF load = '1' THEN
q6 <= data;
ELSIF clk'EVENT AND clk = '1' THEN
q6 <= d;
END IF;
END PROCESS;

--上升沿触发/同步置”1”和清除
PROCESS (clk, clr, pre)
BEGIN
IF clr = '1' THEN
q7 <= '0';
ELSIF pre = '1' THEN
q7 <= '1';
ELSIF clk'EVENT AND clk = '1' THEN
q7 <= d;
END IF;
END PROCESS;
END maxpld;

7) D 触发器组成的 8 位移位寄存器.
LIBRARY ieee;
use ieee.std_logic_1164.all;
entity shift8 is
port(a,clk: in std_logic;
b: out std_logic);
end shift8;
architecture shift_behave of shift8 is
signal df1,df2,df3,df4,df5,df6,df7: std_logic;
begin
process(clk)
begin
45
太原理工大学 夏路易

if(clk'event and clk='1') then


df1<=a;
df2<=df1;
df3<=df2;
df4<=df3;
df5<=df4;
df6<=df5;
df7<=df6;
b<=df7;
end if;
end process;
end shift_behave;
8) 带请零端的 8 位并行输入串行输出移位寄存器(74166)
管脚定义:
a,b—h 8 位并行输入信号
se 串行输入信号
q 串行输出信号
clk 时钟信号
fe 时钟信号禁止端
s1 移位装载控制端
reset 复位信号

LIBRARY ieee;
use ieee.std_logic_1164.all;
entity ttl74166 is
port(reset,s1,fe,clk,se,a,b,c,d,e,f,g,h: in std_logic;
q: out std_logic);
end ttl74166;
architecture behave of ttl74166 is
signal tmpreg8: std_logic_vector(7 downto 0);
begin
process(clk,reset,s1,fe)
begin
if (reset='0') then --
tmpreg8<="00000000";
46
太原理工大学 夏路易

q<=tmpreg8(7);
elsif (clk'event) and (clk='1') then
if (fe='0') then
if (s1='0') then
tmpreg8(0)<=a;
tmpreg8(1)<=b;
tmpreg8(2)<=c;
tmpreg8(3)<=d;
tmpreg8(4)<=e;
tmpreg8(5)<=f;
tmpreg8(6)<=g;
tmpreg8(7)<=h;
elsif (s1='1') then
for i in tmpreg8'high downto tmpreg8'low+1 loop
tmpreg8(i)<=tmpreg8(i-1);
end loop;
tmpreg8(tmpreg8'low)<=se;
q<=tmpreg8(7);
end if;
end if;
end if;
end process;
end behave;

9) 十二进制同步计数器
引脚定义:
reset 复位
en 计数控制
clk 时钟
qa,qb,qc,qd 计数器输出

LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity count12 is
47
太原理工大学 夏路易

port(clk,reset,en: in std_logic;
qa,qb,qc,qd: out std_logic);
end count12;

architecture behave of count12 is


signal count_4: std_logic_vector(3 downto 0);
begin
qa<=count_4(0);
qb<=count_4(1);
qc<=count_4(2);
qd<=count_4(3);
process(clk,reset)
begin
if (reset='0') then
count_4<="0000";
elsif(clk'event and clk='1') then
if(en='1') then
if(count_4="1011") then
count_4<="0000";
else
count_4<=count_4+'1';
end if;
end if;
end if;
end process;
end behave;

10) 4 位二进制可逆计数器
管脚定义: reset 复位
clk 时钟
updn 加减计数控制
qa,qb,qc,qd 输出
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
48
太原理工大学 夏路易

entity updown is
port(clk,reset,updn: in std_logic;
qa,qb,qc,qd: out std_logic);
end updown;
architecture behave of updown is
signal count_6: std_logic_vector(3 downto 0);
begin
qa<=count_6(0);
qb<=count_6(1);
qc<=count_6(2);
qd<=count_6(3);
process(clk,reset)
begin
if (reset='1') then
count_6<="000000";
elsif(clk'event and clk='1') then
if(updn='1') then
count_6<=count_6+'1';
else
count_6<=count_6-'1';
end if;
end if;
end process;
end behave;

11)可预置数的六十进制计数器
管脚定义:
clk 时钟
bcd1wr 个位预置数控制
bcd10wr 十位预置数控制
datain 预置数据
cin 进位输入(计数脉冲)
co 进位输出
bcd1p 个位数据输出
bcd10p 十位数据输出
49
太原理工大学 夏路易

LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity count60 is
port(clk,bcd1wr,bcd10wr,cin: in std_logic;
co: out std_logic;
datain: in std_logic_vector(3 downto 0);
bcd1p: out std_logic_vector(3 downto 0);
bcd10p: out std_logic_vector(2 downto 0));
end count60;

architecture behave of count60 is


signal bcd1n: std_logic_vector(3 downto 0);
signal bcd10n: std_logic_vector(2 downto 0);
begin
bcd1p<=bcd1n;
bcd10p<=bcd10n;
kk1: process(clk,bcd1wr)
begin
if (bcd1wr='1') then
bcd1n<=datain;
elsif(clk'event and clk='1') then
if (cin='1') then
if(bcd1n="1001" ) then
bcd1n<="0000";
else
bcd1n<=bcd1n+'1';
end if;
end if;
end if;
end process kk1;

kk2: process(clk,bcd10wr)
begin
if (bcd10wr='1') then
50
太原理工大学 夏路易

bcd10n<=datain(2 downto 0);


elsif(clk'event and clk='1') then
if(cin='1') and (bcd1n="1001") then
if(bcd10n="101") then
bcd10n<="000";
else
bcd10n<=bcd10n+'1';
end if;
end if;
end if;
end process kk2;

kk3: process(bcd10n,bcd1n,cin)
begin
if(cin='1' and bcd1n="1001" and bcd10n="101") then
co<='1';
else
co<='0';
end if;
end process kk3;
end behave;

12) 各种计数器例
ENTITY counter IS
PORT
(
d : IN INTEGER RANGE 0 TO 255; --预置数据
clk : INBIT;--时钟信号
clear : INBIT;--计数器清零
ld : INBIT;--计数器预置数
enable : INBIT;--计数使能
up_down : INBIT;--计数器加减控制
qa : OUT INTEGER RANGE 0 TO 255;--输出端
qb : OUT INTEGER RANGE 0 TO 255; :
qc : OUT INTEGER RANGE 0 TO 255; :
51
太原理工大学 夏路易

qd : OUT INTEGER RANGE 0 TO 255;


qe : OUT INTEGER RANGE 0 TO 255;
qf : OUT INTEGER RANGE 0 TO 255;
qg : OUT INTEGER RANGE 0 TO 255;
qh : OUT INTEGER RANGE 0 TO 255;
qi : OUT INTEGER RANGE 0 TO 255;
qj : OUT INTEGER RANGE 0 TO 255;
qk : OUT INTEGER RANGE 0 TO 255;
ql : OUT INTEGER RANGE 0 TO 255;
qm : OUT INTEGER RANGE 0 TO 255;
qn : OUT INTEGER RANGE 0 TO 255 –输出端
);

END counter;

ARCHITECTURE a OF counter IS
BEGIN
-- 有使能端的计数器
PROCESS (clk)
VARIABLEcnt : INTEGER RANGE 0 TO 255;
BEGIN
IF (clk'EVENT AND clk = '1') THEN
IF enable = '1' THEN
cnt := cnt + 1;
END IF;
END IF;

qa <= cnt;
END PROCESS;

--同步预置数计数器
PROCESS (clk)
VARIABLEcnt : INTEGER RANGE 0 TO 255;
BEGIN
IF (clk'EVENT AND clk = '1') THEN
52
太原理工大学 夏路易

IF ld = '0' THEN
cnt := d;
ELSE
cnt := cnt + 1;
END IF;
END IF;
qb <= cnt;
END PROCESS;

--同步清除计数器
PROCESS (clk)
VARIABLEcnt : INTEGER RANGE 0 TO 255;
BEGIN
IF (clk'EVENT AND clk = '1') THEN
IF clear = '0' THEN
cnt := 0;
ELSE
cnt := cnt + 1;
END IF;
END IF;
qc <= cnt;
END PROCESS;

--加减计数器
PROCESS (clk)
VARIABLE cnt : INTEGER RANGE 0 TO 255;
VARIABLE direction : INTEGER;
BEGIN
IF (up_down = '1') THEN
direction := 1;
ELSE
direction := -1;
END IF;

IF (clk'EVENT AND clk = '1') THEN


53
太原理工大学 夏路易

cnt := cnt + direction;


END IF;
qd <= cnt;
END PROCESS;

--同步预置/计数控制计数器
PROCESS (clk)
VARIABLE cnt : INTEGER RANGE 0 TO 255;
BEGIN
IF (clk'EVENT AND clk = '1') THEN
IF ld = '0' THEN
cnt := d;
ELSE
IF enable = '1' THEN
cnt := cnt + 1;
END IF;
END IF;
END IF;
qe <= cnt;
END PROCESS;

--计数控制的加减计数器
PROCESS (clk)
VARIABLE cnt : INTEGER RANGE 0 TO 255;
VARIABLE direction : INTEGER;
BEGIN
IF (up_down = '1') THEN
direction := 1;
ELSE
direction := -1;
END IF;

IF (clk'EVENT AND clk = '1') THEN


IF enable = '1' THEN
cnt := cnt + direction;
54
太原理工大学 夏路易

END IF;
END IF;
qf <= cnt;
END PROCESS;

--同步清除/计数控制计数器
PROCESS (clk)
VARIABLE cnt : INTEGER RANGE 0 TO 255;
BEGIN
IF (clk'EVENT AND clk = '1') THEN
IF clear = '0' THEN
cnt := 0;
ELSE
IF enable = '1' THEN
cnt := cnt + 1;
END IF;
END IF;
END IF;
qg <= cnt;
END PROCESS;

--同步预置/清除计数器
PROCESS (clk)
VARIABLE cnt : INTEGER RANGE 0 TO 255;
BEGIN
IF (clk'EVENT AND clk = '1') THEN
IF clear = '0' THEN
cnt := 0;
ELSE
IF ld = '0' THEN
cnt := d;
ELSE
cnt := cnt + 1;
END IF;
END IF;
55
太原理工大学 夏路易

END IF;
qh <= cnt;
END PROCESS;

--同步预置/加减计数器
PROCESS (clk)
VARIABLE cnt : INTEGER RANGE 0 TO 255;
VARIABLE direction : INTEGER;
BEGIN
IF (up_down = '1') THEN
direction := 1;
ELSE
direction := -1;
END IF;

IF (clk'EVENT AND clk = '1') THEN


IF ld = '0' THEN
cnt := d;
ELSE
cnt := cnt + direction;
END IF;
END IF;
qi <= cnt;
END PROCESS;

--同步预置/计数控制/加减计数器
PROCESS (clk)
VARIABLEcnt : INTEGER RANGE 0 TO 255;
VARIABLEdirection : INTEGER;
BEGIN
IF (up_down = '1') THEN
direction := 1;
ELSE
direction := -1;
END IF;
56
太原理工大学 夏路易

IF (clk'EVENT AND clk = '1') THEN


IF ld = '0' THEN
cnt := d;
ELSE
IF enable = '1' THEN
cnt := cnt + direction;
END IF;
END IF;
END IF;
qj <= cnt;
END PROCESS;

--同步清除/预置/计数控制计数器
PROCESS (clk)
VARIABLEcnt : INTEGER RANGE 0 TO 255;
BEGIN
IF (clk'EVENT AND clk = '1') THEN
IF clear = '0' THEN
cnt := 0;
ELSE
IF ld = '0' THEN
cnt := d;
ELSE
IF enable = '1' THEN
cnt := cnt + 1;
END IF;
END IF;
END IF;
END IF;
qk <= cnt;
END PROCESS;

--同步清除/加减计数器
PROCESS (clk)
57
太原理工大学 夏路易

VARIABLEcnt : INTEGER RANGE 0 TO 255;


VARIABLEdirection : INTEGER;
BEGIN
IF (up_down = '1') THEN
direction := 1;
ELSE
direction := -1;
END IF;

IF (clk'EVENT AND clk = '1') THEN


IF clear = '0' THEN
cnt := 0;
ELSE
cnt := cnt + direction;
END IF;
END IF;
ql <= cnt;
END PROCESS;

--同步清除/计数控制/加减计数器
PROCESS (clk)
VARIABLEcnt : INTEGER RANGE 0 TO 255;
VARIABLEdirection : INTEGER;
BEGIN
IF (up_down = '1') THEN
direction := 1;
ELSE
direction := -1;
END IF;

IF (clk'EVENT AND clk = '1') THEN


IF clear = '0' THEN
cnt := 0;
ELSE
IF enable = '1' THEN
58
太原理工大学 夏路易

cnt := cnt + direction;


END IF;
END IF;
END IF;
qm <= cnt;
END PROCESS;

A modulus 200 up counter


--模为 200 的计数器
PROCESS (clk)
VARIABLE cnt : INTEGER RANGE 0 TO 255;
CONSTANT modulus : INTEGER := 200;
BEGIN
IF (clk'EVENT AND clk = '1') THEN
IF cnt = modulus THEN
cnt := 0;
ELSE
cnt := cnt + 1;
END IF;
END IF;
qn <= cnt;
END PROCESS;
END a;

13) 直接调用小规模数字电路例
LIBRARY altera;
USE altera.maxplus2.ALL;--使用 Altera 的元件库
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY compinst IS
PORT
(
data, clock, clearn, presetn : INSTD_LOGIC;
q_out : OUT STD_LOGIC;

59
太原理工大学 夏路易

a, b, c, gn : INSTD_LOGIC;
d : INSTD_LOGIC_VECTOR(7 DOWNTO 0);
y, wn : OUT STD_LOGIC
);
END compinst;

ARCHITECTURE a OF compinst IS

BEGIN
--D 触发器
dff1 : dff PORT MAP (d =>data, q => q_out, clk => clock, clrn => clearn,
prn => presetn);
--TTL74151
mux : a_74151b PORT MAP (c, b, a, d, gn, y, wn);
END a;

14) 选择信号
如果 sel 信号为”1”时,选择信号 input1,否则选择信号 input0.
ENTITY condsig IS
PORT
(
input0, input1, sel : IN BIT;
output : OUT BIT
);
END condsig;
ARCHITECTURE maxpld OF condsig IS
BEGIN
output <= input0 WHEN sel = '0' ELSE input1;
END maxpld;

15) 三信号分别控制输出数值
输入信号 high =1 输出 q=3
mid=1 输出 q=2
low=1 输出 q=1
ENTITY condsigm IS
60
太原理工大学 夏路易

PORT
(
high, mid, low : IN BIT;
q : OUT INTEGER
);
END condsigm;

ARCHITECTURE maxpld OF condsigm IS


BEGIN
q <=3 WHEN high = '1' ELSE -- when high
2 WHEN mid = '1' ELSE -- when mid but not high
1 WHEN low = '1' ELSE -- when low but not mid or high
0; -- when not low, mid, or high
END maxpld;

16) 由状态机方法描述的模 4 加减计数器


如果 updown=0 状态变化为: zeroonetwothree
如果 updown=1 状态变化为: zerothreetwoone
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY enumsmch IS
PORT
(
updown : IN STD_LOGIC;
clock : IN STD_LOGIC;
lsb : OUT STD_LOGIC;
msb : OUT STD_LOGIC
);
END enumsmch;

ARCHITECTURE firstenumsmch OF enumsmch IS


TYPE count_state is (zero, one, two, three);
ATTRIBUTE ENUM_ENCODING : STRING;
ATTRIBUTE ENUM_ENCODING OF count_state : TYPE IS "11 01 10 00";
SIGNAL present_state, next_state : count_state;
61
太原理工大学 夏路易

BEGIN

PROCESS (present_state, updown)


BEGIN
CASE present_state IS
WHEN zero =>
IF (updown = '0') THEN
next_state <= one;
lsb <= '0';
msb <= '0';
ELSE
next_state <= three;
lsb <= '1';
msb <= '1';
END IF;
WHEN one =>
IF (updown = '0') THEN
next_state <= two;
lsb <= '1';
msb <= '0';
ELSE
next_state <= zero;
lsb <= '0';
msb <= '0';
END IF;
WHEN two =>
IF (updown = '0') THEN
next_state <= three;
lsb <= '0';
msb <= '1';
ELSE
next_state <= one;
lsb <= '1';
msb <= '0';
END IF;
62
太原理工大学 夏路易

WHEN three =>


IF (updown = '0') THEN
next_state <= zero;
lsb <= '1';
msb <= '1';
ELSE
next_state <= two;
lsb <= '0';
msb <= '1';
END IF;
END CASE;
END PROCESS;

PROCESS
BEGIN
WAIT UNTIL clock'EVENT and clock = '1';
present_state <= next_state;
END PROCESS;
END firstenumsmch;

16) 状态机例
ENTITY statmach IS
PORT(
clk : INBIT;
input : INBIT;
reset : INBIT;
output : OUT BIT);
END statmach;

ARCHITECTURE a OF statmach IS
TYPE STATE_TYPE IS (s0, s1);
SIGNAL state: STATE_TYPE;
BEGIN
PROCESS (clk)
BEGIN
63
太原理工大学 夏路易

IF reset = '1' THEN


state <= s0;
ELSIF (clk'EVENT AND clk = '1') THEN
CASE state IS
WHEN s0=>
state <= s1;
WHEN s1=>
IF input = '1' THEN
state <= s0;
ELSE
state <= s1;
END IF;
END CASE;
END IF;
END PROCESS;
output <= '1' WHEN state = s1 ELSE '0';
END a;

64