硬件描述语言VHDL

来源:互联网 发布:b一17轰炸机数据 编辑:程序博客网 时间:2024/05/16 19:47

 

 

数字系统设计分为硬件设计和软件设计, 但是随着计算机技术、超大规模集成电路(CPLDFPGA)的发展和硬件描述语言(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

不指定方向

 

常用的端口数据类型有两种:BITBIT_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;

构造体描述设计实体的具体行为,它包含两类语句:

l       并行语句  并行语句总是在进程语句(PROCESS)的外部,该语句的执行与书写顺序无关,总是同时被执行

l       顺序语句  顺序语句总是在进程语句(PROCESS)的内部,从仿真的角度,该语句是顺序执行的

一个构造体包含几个类型的子结构描述,这些描述是:

* BLOCK描述(块描述)

* PROCESS描述(进程描述)

* SUNPROGRAMS描述(子程序描述)

 

2) 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中有两种类型:

l       过程(Procedure

l       函数(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;

   数组常在总线、ROMRAM中使用。

* 时间(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,UNSIGNEDSIGNED转换成

STD_LOGIC_VECTOR

UNSIGNEDSIGNED转换成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_VECTORSTD_BIT_VECTOR 的语句例:

SIGNAL a: BIT_VECTOR(11 DOWNTO 8);

SIGNAL b: STD_LOGIC_VECTOR(11 DOWNTO 0);

a<=XA8; 十六进制可以赋予位矢量

b<=XA8;  十六进制不可以赋予逻辑矢量,所以此句错,逻辑量中只能赋予二进制

b<=TO_STDLOGICVECTOR(XAF7);十六进制变换

b<=TO_STDLOGICVECTOR(O5177); 八进制变换

b<=TO_STDLOGICVECTOR(B1010_1111_0111); 三位二进制变换

  

(6)         IEEE标准“STD_LOGICSTD_LOGIC_VECTOR

1993年制定的标准IEEE STD1164 STD_LOGIC的值做如下规定:

U’初始值

X’不定

00

11

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 nsa才变化。

例:与门电路

   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,PACKAGEBLOCK的说明部分.

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

   该等待有三个条件:

   第一,信号nmiinterrupt 任何一个有一次刷新动作

   第二, 信号nmiinterrupt 任何一个为真

   第三, 等待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

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;

  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

  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;

     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.    并发信号代入

代入语句在进程中使用是顺序语句,但是在进程外即在构造体中使用就是并发语句,相当于一个进程.

:

  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

         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.    并发过程调用语句

过程调用语句可以并发执行,但要注意如下问题:

l       并发过程调用是一个完整的语句,在它之前可以加标号

l       并发过程调用语句应带有IN,OUTINOUT的参数,他们应该列在过程名后的括号内

l       并发过程调用可以有多个返回值

:

  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 clkLAST_VALUE=0 AND clkEVENT

下降沿到来的条件:

    IF clk=0 AND clkLAST_VALUE=1 AND clkEVENT

关于时钟信号的总结:

 IF clock_signal=current_value AND

clock_signalLAST AND

clock_siganlEVENT

可以简单写为:

 IF clock_signal=clock_siganlEVENT AND current_value

 

1:对于上升沿D触发器,其描述为:

process(clk,d)

   begin

       if(clkevent and clk=1) then

          q<=d;

        end if;

        end process;

2:对于上升沿D触发器的另一描述为:

process

   begin

wait  until clkevent 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;

       :

     其它语句

       :

    end if;

 end if;

   end process;

2:

   process(clock)

     if (clockevent 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 clockevent and clock=1 then

        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';

      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;

 

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

      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,bh 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;

 

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

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;

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;

 

12) 各种计数器例

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;

 

13)  直接调用小规模数字电路例

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;

 

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

    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;

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;

 

16) 状态机例

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;