亮亮的草窝

你是继续在生活中沉沦,还是要改变世界?

硬件描述语言VHDL

 

 

数字系统设计分为硬件设计和软件设计, 但是随着计算机技术、超大规模集成电路(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;

阅读更多
个人分类: 电子设计
上一篇转载---民航学院的同学如何找工作
下一篇学好VHDL的重要性
想对作者说点什么? 我来说一句

VHDL硬件描述语言

2011年03月05日 8.3MB 下载

硬件描述语言VHDL基础

2010年08月11日 647KB 下载

VHDL硬件描述语言基础

2010年08月11日 206KB 下载

第1章 硬件描述语言VHDL

2010年05月15日 216KB 下载

VHDL硬件描述语言入门教程

2010年10月18日 3.54MB 下载

vhdl设计ppt教程

2011年03月07日 352KB 下载

没有更多推荐了,返回首页

关闭
关闭