MAXPLUS教程 - 第1章 硬件描述语言VHDL

本文详细介绍了VHDL硬件描述语言,包括传统的硬件设计方法与使用HDL的现代方法的区别,重点讲解了VHDL的基本结构,如实体、构造体、配置、库和包,并给出了实例解析。此外,还提到了VHDL中的数据类型和运算操作,以及各种计数器的实现。VHDL使得数字系统设计更加灵活和高效。

第1章 硬件描述语言VHDL

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

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

1.2 使用HTL的硬件设计方法
所谓硬件描述语言,就是利用一种人和计算机都能识别的语言来描述硬件电路的功能,信号连接关系及定时关系,它可以比电原理图更能表示硬件电路的特性。
该方法有如下特征:
(1) 支持自顶向下的设计方法
所谓自顶向下的设计方法就是从系统的总体要求出发,自顶向下分三个层次对系统硬件进行设计。
第一个层次是行为描述,所谓行为描述,实际就是对整个系统的数学模型的描述,在行为描述阶段,并不真正考虑其实际操作和算法怎么实现,而是考虑系统的结构和工作过程是否能达到系统设计规格书的要求。
第二个层次是数据流描述,又称为寄存器描述或RTL方式描述,该描述比行为描述更注重硬件的具体实现,通过该描述可以导出系统的逻辑表达式,为逻辑综合作准备,当然进行逻辑综合和逻辑综合工具的能力有关,当然设计人员还必须了解逻辑综合工具的说明和规定,
第三个层次为逻辑综合。该层次把RTL描述的程序转换成基本逻辑元件表示的文件,该文件就象老的设计方法中的电原理图。
(2) 采用大量的ASIC芯片
(3) 早期仿真以确定系统的可行性
(4) 使设计更容易
只需写出系统的HDL源程序文件,其它由计算机去做
(5) 全部设计文件就是HDL源程序文件

1.3 VHTL硬件设计语言
当前ASIC制造商都自己开发了HDL语言,但是都不通用,只有美国国防部开发的VHDL语言成为了IEEE. STD_1076标准,并在全世界得到了承认。
该语言集成了各种HDL语言的优点,使数字系统设计更加简单和容易。VHDL语言是一个规模庞大的语言,在使用它之前完全学会它是很难的,本书介绍的只是VHDL语言的一部分。
1.4 VHDL语言的基本结构
VHDL语言通常包含实体(Entity),构造体(Architecture),配置(Configuration),包集合(Package),和库(Library)五部分.其中实体用于描述所设计的系统的外部接口信号;构造体用于描述系统内部的结构和行为;建立输入和输出之间的关系;配置语句安装具体元件到实体—结构体对,可以被看作是设计的零件清单;包集合存放各个设计模块共享的数据类型、常数和子程序等;库是专门存放预编译程序包的地方。如下详细介绍。

1.4.1基本设计单元
VHDL的基本设计单元就是实体,无论数字电路复杂还是简单,都是由实体和构造体组成。
(1) 实体说明
实体说明有如下结构:
ENTITY 实体名 IS
[端口说明]
END 实体名;
(VHDL语言中不分大小写字母)
其中:
端口说明是对设计实体中输入和输出借口进行描述,格式如下:
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”。
因为使用了库所以在实体说明前要增加库说明语句。

(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描述(子程序描述)
  1. BLOCK语句描述
    使用BLOCK语句描述的格式如下:
    块标号:BLOCK
    BEGIN


    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
    – 指定信号
    – 指定变量
    – 过程调用
    – 如果语句
    – 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;
    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;
    在过程中,语句是顺序执行的。

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 库名;
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;
    例:包体
    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 配置名;
例:最简单的配置
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) 信号、常量和变量
信号:通常认为信号是电路中的一根线
常数:可以在数字电路中代表电源、地线等等
变量:可以代表某些数值
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. 信号与变量的区别
信号赋值可以有延迟时间,变量赋值无时间延迟
信号除当前值外还有许多相关值,如历史信息等,变量只有当前值
进程对信号敏感,对变量不敏感
信号可以是多个进程的全局信号,但变量只在定义它之后的顺序域可见
信号可以看作硬件的一根连线,但变量无此对应关系

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)
只能是正整数
数据除定义类型外,有时还需要定义约束范围。
例:
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;
    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_LOGIC_1164包
TO_STDLOGICVECTOR(A)
TO_BITVECTOR(A)
TO_LOGIC(A)
TO_BIT(A)
由BIT_VECTOR转换成STD_LOGIC_VECTOR
由STD_LOGIC_VECTOR转换成BIT_VECTOR
由BIT转换成STD_LOGIC
由STD_LOGIC转换成BIT
STD_LOGIC_ARITH包
CONV_STD_LOGIC_VECTOR(A,位长)
CONV_INTEGER(A)
由INTEGER,UNSIGNED和SIGNED转换成
STD_LOGIC_VECTOR
由UNSIGNED和SIGNED转换成INTEGER
STD_LOGIC_UNSIGNED包
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_VECTOR和STD_BIT_VECTOR 的语句例:
SIGNAL a: BIT_VECTOR(11 DOWNTO 8);
SIGNAL b: STD_LOGIC_VECTOR(11 DOWNTO 0);
a<=X”A8”; 十六进制可以赋予位矢量
b<=X”A8”; 十六进制不可以赋予逻辑矢量,所以此句错,逻辑量中只能赋予二进制
b<=TO_STDLOGICVECTOR(X”AF7”);十六进制变换
b<=TO_STDLOGICVECTOR(O”5177”); 八进制变换
b<=TO_STDLOGICVECTOR(B”1010_1111_0111”); 三位二进制变换

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

1.4.5 VHDL语言的运算操作符

优先级别 类型 操作符 说明

低 逻辑运算符 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) 算数运算符
在使用乘法运算符时,应该特别慎重,因为它可以使逻辑门数大大增加。

(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才变化。
例:与门电路
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
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);
    调用该元件时:
    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 时间表达式
    当进程执行到该语句时,被挂起;等待一定的时间后,进程将被启动.
    例: 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
    顺序执行语句
    END IF;
    格式二:IF 条件 THEN
    顺序执行语句
    ELSIF 条件 THEN
    顺序执行语句


    ELSIF 条件 THEN
    顺序执行语句
    ELSIF 条件 THEN
    顺序执行语句
    END IF;
  1. 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;
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;

  1. 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
    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;

  2. 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;
    END IF;
    q(I)<=a(I) AND b(I);
    END LOOP;
    END PROCESS;

  3. 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. 进程之间的通信是通过信号量来实现的
  1. 并发信号代入
    代入语句在进程中使用是顺序语句,但是在进程外即在构造体中使用就是并发语句,相当于一个进程.
    例:
    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;
    信号代入语句的右边可以是算数表达式,也可以是逻辑表达式,还可以是关系表达式,所以可以仿真加法器、乘法器、除法器、比较器和各种逻辑电路。
  2. 条件信号代入
    条件代入语句也是并发语句,它可以将符合条件的表达式代入信号量。
    格式:目的信号量<=表达式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
i2 WHEN sel=“10” ELSE
i3 WHEN sel=“11” ;
END aa;

  1. 选择信号代入
    格式: 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;

  2. 并发过程调用语句
    过程调用语句可以并发执行,但要注意如下问题:
     并发过程调用是一个完整的语句,在它之前可以加标号
     并发过程调用语句应带有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输入或非门
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)
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
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);
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;

例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: 三态门
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;
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
    下降沿到来的条件:
    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;

  1. 复位信号
    *同步复位
    当复位信号有效且在给定的时钟边沿到来时,触发器才被复位.
    例1:
    process (clock)
    begin
    if (clock_edge_condition) then
    if (reset_condition) then
    signal_out<=reset_value;
    else
    signal_out=signal_in;
    :
    其它语句
    :
    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
    count<=count+1;
    end if;
    end process;
  1. 触发器
  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’;
    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;
    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
    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;

--低电平时钟触发
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;

--上升沿触发/同步预置数据
-- 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;

  1. 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
    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;
  2. 带请零端的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”;
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;

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

LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity count12 is
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;

  1. 4位二进制可逆计数器
    管脚定义: reset 复位
    clk 时钟
    updn 加减计数控制
    qa,qb,qc,qd 输出
    LIBRARY ieee;
    use ieee.std_logic_1164.all;
    use ieee.std_logic_unsigned.all;
    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 十位数据输出
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
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;

  1. 各种计数器例
    ENTITY counter IS
    PORT
    (
    d : IN INTEGER RANGE 0 TO 255; --预置数据
    clk : IN BIT;–时钟信号
    clear : IN BIT;–计数器清零
    ld : IN BIT;–计数器预置数
    enable : IN BIT;–计数使能
    up_down : IN BIT;–计数器加减控制
    qa : OUT INTEGER RANGE 0 TO 255;–输出端
    qb : OUT INTEGER RANGE 0 TO 255; :
    qc : OUT INTEGER RANGE 0 TO 255; :
    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)
VARIABLE cnt : 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)
	VARIABLE	cnt			: INTEGER RANGE 0 TO 255;
BEGIN
	IF (clk'EVENT AND clk = '1') THEN
		IF ld = '0' THEN
			cnt := d;
		ELSE
			cnt := cnt + 1;
		END IF;
	END IF;
	qb	<=	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
			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
		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;
		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;
	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)
	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
			IF enable = '1' THEN
				cnt := cnt + direction;
			END IF;
		END IF;
	END IF;
	qj	<=	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
				IF enable = '1' THEN
					cnt := cnt + 1;
				END IF;
			END IF;
		END IF;
	END IF;	
	qk	<=	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 clear = '0' THEN
			cnt := 0;
		ELSE
			cnt := cnt + direction;
		END IF;
	END IF;
	ql	<=	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 clear = '0' THEN
			cnt := 0;
		ELSE
			IF enable = '1' THEN
				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;

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

    a, b, c, gn						: IN	STD_LOGIC;
    d								: IN	STD_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;

  1. 选择信号
    如果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;

  2. 三信号分别控制输出数值
    输入信号high =1 输出q=3
    mid=1 输出q=2
    low=1 输出q=1
    ENTITY condsigm IS
    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;

  1. 由状态机方法描述的模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;
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;
		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;

  1. 状态机例
    ENTITY statmach IS
    PORT(
    clk : IN BIT;
    input : IN BIT;
    reset : IN BIT;
    output : OUT BIT);
    END statmach;

ARCHITECTURE a OF statmach IS
TYPE STATE_TYPE IS (s0, s1);
SIGNAL state : STATE_TYPE;
BEGIN
PROCESS (clk)
BEGIN
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;

1 绪 论 ....................................................................................................................1 § 1.1 关于EDA...............................................................................................................1 § 1.2 关于 VHDL............................................................................................................3 § 1.3 关于自顶向下的系统设计方法 ............................................................................5 § 1.4 关于应用 VHDL 的EDA 过程.............................................................................6 § 1.5 关于在系统编程技术 ............................................................................................9 § 1.6 关于 FPGA/CPLD 的优势...................................................................................10 § 1.7 关于 VHDL 的学习.............................................................................................10 第2 VHDL 入门..............................................................................................................12 § 2.1VHDL 设计多路选择器和锁存器.................................................................12 § 2.2 用 VHDL 设计全加器.........................................................................................15 第3 VHDL 程序结构......................................................................................................19 § 3.1 实 体 ENTITY ..............................................................................................19 § 3.2 结构体 ARCHITECTURE ............................................................................26 § 3.3 块语句结构 BLOCK .....................................................................................29 § 3.4 进程 PROCESS .............................................................................................32 § 3.5 子程序(SUBPROGRAM)....................................................................................35 3.5.1 函数FUNCTION ..................................................................................36 3.5.2
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值