fpga_feixiang 发表于 2017-12-4 10:36:45

VHDL设计初步复习总结

电路的VHDL描述由两大部分组成:
    (1)实体部分:以关键词ENTITY引导,END ENTITY mux21a结尾.VHDL的实体描述电路器件的外部情况及各信号端口的基木性质。图3-1可以认为是实体的图形表达。
    (2)结构体部分:以关键词ARCHITECTURE引导,END ARCHITECTURE one结尾.结构体描述电路器件的内部逻辑功能或电路结构。图3-2是此结构体的原理图表达。

一、实体名

具体取名由设计者自定,由于实体名实际上表达的是该设计电路的器件名,所以最好根据相应电路的功能来确定,如4位二进制计数器.实体名可取为counter4b;8位二进制加法器.实体名可取为adder8b等等.但应注意,实体名取名也应遵循一定的规则。

即遵守标识符命名规则:
(1)标识符主要由字母、数字以及下划线组成
(2)第一个字符必须是英文字母
(3)最后一个字符不能是下划线
(4)在标识符中不允许出现两个连续的下划线
(5)短标识符不区分大小写
(6)VHDL中的保留字不能作为一般的标识符使用

2.PORT语句和端口信号名

描述电路的端口及其端口信号必须用端口语句 PORT()引导,并在语句结尾处加分号“;”。端口信号名,由设计者自己确定。
      同样应遵守标识符命名规则。

3.端口模式

可综合的端口模式有四种.它们分别是“IN”、“OUT”.“INOUT”和“BUFFER”.用于定义端口上数据的流动方向和方式:
. IN:IN定义的通道为单向只读模式.规定数据只能通过此端口被读入实体中。
. OUT:OUT定义的通道为单向输出模式,规定数据只能通过此端口从实体向外流出,或者说可以将卖体中的数据向此端口赋值.
. INOUT.INOUT定义的通道确定为输入输出双向端口,即信号既可以从此端口流出,也可以向此端口输入信号.如RAM的数据端口,单片机的I/O口.
.BUFFER:BUFFER的功能与INOUT类似,区别在于当需要输入数据时.只允许内部回读输出的信号.即允许反馈.如计数器设计.可将计数器输出的计数信号回读,以作下一计数值的初值.与INOUT模式相比, BUFFER回读的信号不是由外部输入的.而是由内部产生,向外输出的信号.

4.数据类型

VHDL中任何一种数据对象(信号、变量、常量)的应用都必须严格限定其取值范围。因此,在VHDL设计中必须预先定义好要使用的数据类型。相关的数据类型有整数数据类型INTEGER、布尔数据类型BOOLEAN、标准逻辑位数据类型STD_LOGIC
BIT数据类型规定的取值范围是逻辑位’1’和’0’。
STD_LOGIC型数据较完整地概括了数字系统中所有可能的数据表现形式,在仿真和综合中,将信号或其它数据对象定义为STD_LOGIC数据类型,可以使设计者精确模拟一些未知的和具有高阻态的线路情况.对于综合器,高阻态’z’和’-’忽略态可用于三态的描述.
       STD_LOGIC数据类型在数字器件中实现的只有其中4种值,即’-’、’0’ 、’1’和’z’.其它类型通常不可综合.


5. 设计库和标准程序包

STD_LOGIC数据类型在STD_LOGIC_1164程序包中定义,而此程序包所在的程序库的库名为IEEE.由于IEEE库不属于VHDL标准库,所以在使用其库中内容前,必须事先给予声明,即调用.
使用库和程序包的一般定义表式是:
      LIBRARY<设计库名>;
      USE< 设计库名>.<程序包名>.ALL ;

VHDL语言标准定义了两个标准程序包,即STANDARD和TEXTIO程序包,它们 都被收入在VHDL标准库中.只要在VHDL应用环境中,即可随时调用这两个程序包中的所有内容,不必显式表达出来,也就是说不必象IEEE库一样进行库和程序包的调用。
   而BIT数据类型在标准程序包STANDARD中定义,所以不需要库和程序包的调用。


6.信号传输(赋值)符号

表达式y<=a表示输入端口的数据向输出端口y传输;但也可以解释为信号a向信号y赋值.
VHDL要求赋值符“<=”两边信号的数据类型必须一致.   


7.WHEN_ELSE条件信号赋值语句和数据比较符号

条件信号赋值语句,这是一种并行赋值语句.其表达方式如下:
赋值目标 <= 表达式 WHEN 赋值条件 ELSE
                     表达式 WHEN 赋值条件 ELSE
                              ...
                     表达式 ;
    在结构体中,条件信号赋值语句在执行时,每一“赋值条件”是按书写的先后关系逐项测定的,一旦发现(赋值条件=true)立即将“表达式”的值赋给“赋值目标”信号.

在VHDL综合器或仿真器中分别用’1’利’0’表达true和false。
       在VHDL中,逻辑位0和1的表达必须加单引号.否则VHDL综合器将0和1解释为整数数据类型INTEGER


二、结构体表达

ARCHITECTURE <</SPAN>结构体名> OF <</SPAN>实体名> IS
    [说明语句]
BEGIN
    <</SPAN>功能描述语句>
END <</SPAN>结构体名>;

• 对数据类型、常数、信号、子程序和元件等元素的说明部分。
•   •
               
描述实体逻辑行为的、以各种不同的描述风格表达的功能描述语句。

结构体名的命名也应遵循标识符命名规则

描述结构体的关键词(ARCHITECTURE, OF, IS, BEGIN和END ARCHITECTURE 等),在描述中必须包含它们.
   结构体中必须给出相应的电路功能描述语句.可以是并行语句,顺序语句或它们的混合.

一般地,一个可综合的完整的VHDL程序有比较固定的结构,设计实体中,一般首先出现的是各类库及其程序包的使用声明,包括未以显式表达的工作库WORK库的使用声明,然后是实体描述,最后是结构体描述.而在结构体中可以含有不同的逻辑表达语句结构。

1.逻辑操作符

VHDL共有7种基本逻辑操作符.它们是AND(与),OR(或),NAND(与非),NOR(或非)、XOR(异或),XNOR(同或)和NOT(取反).信号在这些操作符的作用下,可构成组合电路.逻辑操作符所要求的操作数(操作对象)的数据类型有5种即BOOLEAN 、BIT、BIT_VECTOR、 STD_LOGIC、STD_LOGIC_VECTOR。

2.PROCESS进程语句和顺序语句

顺序语句IF_THEN_ELSE_END IF;”是放在由“PROCESS… END PROCESS”引导的语句中的,由PROCESS引导的语句称为进程语句.在VHDL中,所有合法的顺序描述的语句都必须放在进程语句中.
    PROCESS旁的(a.b .s)称为进程的敏感信号表。通常要求将进程中所有的输入信号都放在敏感信号表中.例如.例6中的输入信号a,b和s,所以将它们全部列入敏感信号表中.由于PROCESS的执行依赖于敏感信号的变化.当某一敏感信号(如a)从原来的’1’跳变到’0’,或者从原来的’0’跳变到’1’时.就将启动此进程语句,而在执行一遍整个进程的顺序语句后.便进入等待状态,直到下一次敏感信号表中某一信号的跳变才再次进入“启动一运行”状态.
    在一个结构体中可以包含任意个进程语句,所有的进程语句都是并行语句.而由任一进程PROCESS引导的语句结构属于顺序语句.

3.元件例化

       元件例化就是引入一种连接关系,将预先设计好的设计实体定义为一个元件,然后利用特定的语句将此元件与当前的设计实体中的指定端口相连接,从而为当前设计实体引进一个新的低一级的设计层次。
       元件例化是使VHDL设计实体构成自上而下层次化设计的一种重要途径。
       元件例化是可以多层次的,一个调用了较低层次元件的顶层设计本身也可以被更高层次设计实体所调用,成为该设计实体中的一个元件。

元件例化语句由两部分组成:
第一部分是对一个现成的设计实体定义为一个元件,语句的功能是对待调用的元件作出调用声明,它的最简表达式如下所示:
    COMPONENT 元件名 IS
      PORT(端口名表) ;
         END COMPONENT 文件名 ;

元件例化语句的第二部分则是此元件与当前设计实体(顶层文件)中元件间及端口的连接说明。语句的表达式如下:
      例化名 : 元件名 PORT MAP( [端口名 =>] 连接端口名,...);

三、文件取名和存盘

         在保存文件前.每个VHD设计程序(代码)都必须赋给一个正确的文件名.一般地文件名可以由设计者任意给定,但具体取名最好与文件实体名相同;文件后缀扩展名必须是“vhd”,如adder_f.vhd、但考虑到某些EDA软件的限制和VHDL程序的特点,即在元件(例化语句中的被调用文件)调用中.其元件名与文件名是等同的,因此建议,程序的文件名应该与该程序的实体名一致.


1. CASE语句

CASE语句的一般表式是:

CASE <表达式> IS
When <选择值或标识符> => <顺序语句>; ... ; <顺序语句> ;
When <选择值或标识符> => <顺序语句>; ... ; <顺序语句> ;
...
END CASE ;

      当执行到CASE语句时,首先计算<</SPAN>表达式>的值,然后根据WHEN条件句中与之相同的<选择值或标识符> ,执行对应<顺序语句>,最后结束CASE语句.
      条件中的“=>”相当于“THEN”(或”于是”).


CASE语句使用中应该注意以下几点:
1.WHEN条件中的选择值或标识符所代表的值必须在表达式的取值范围内.
2.除非所有条件句中的选择值能完整覆盖CASE语句中的表达式的取值,否则最末一个条件句中的选择必须用关键词OTHERS表示以上已列的所有条件句中未能列出其他可能的取值,以免综合器会插入不必要的锁存器.关键词NULL表示不作任何操作.
3.CASE语句中的选择值只能出现一次,不允许有相同选择值的条件语句出现.
4.CASE语句执行中必须选中,且只能选中所列条件语句中的一条.

2. 标准逻辑矢量数据类型STD_LOGIC_VECTOR

STD_LOGIC_VECTOR在STD_LOGIC_1164程序包中定义,被定义为标准一维数组,数组中的每一个元素的数据类型都是标准STD_LOGIC, 使用 STD_LOGIC_VECTOR可以表达电路中并列的多通道端口或节点,或者总线BUS 。

在使用STD_LOGIC_VECTOR中,必须注明其数组宽度,即位宽,如:
       B : OUTSTD_LOGIC_VECTOR(7 DOWNTO 0) ;
或    SIGNAL A :STD_LOGIC_VECTOR(1 TO 4) ;

上句表明B的数据类型被定义为一个具有8位位宽的矢量或总线端口信号,它的最左位,即最高位是B(7),通过数组元素排列指示关键词”DOWNTO”向右依次递减为B(6)…B(0),
B的赋值方式如下:
B<=“01100010”;             --B(7)为’0’
       其中”01100010”表示二进制数(矢量位),必须加双引号,而单一二进制数则用单引号,如’1’.

3. 并置操作符 &

&表示将操作数或是数组合并起来形成新的数组.如“VH” &“DL”的结果为“VHDL”;

4. SIGNAL信号定义和数据对象

例中“SIGNAL abc: STD_LOGIC_VECTOR(1 DOWNTO 0) ;”
表示定义abc的数据对象为信号SIGNAL,其数据类型为STD_LOGIC_VECTOR,
在VHDL中,数据对象有3类,即信号(SIGNAL)、变量(VARIABLE)和常量(CONSTANT),
数据对象规定行为方式和功能特点,数据类型限定取值范围.

D触发器VHDL描述的语言现象说明

【例7】
LIBRARY IEEE ;
USE IEEE.STD_LOGIC_1164.ALL ;
ENTITY DFF1 IS
PORT (CLK : IN BIT ;
         D : IN STD_LOGIC ;
         Q : OUT STD_LOGIC );
END ;
ARCHITECTURE bhv OF DFF1 IS
SIGNAL Q1 : STD_LOGIC ; --类似于在芯片内部定义一个数据的暂存节点
BEGIN
   PROCESS (CLK)
    BEGIN
   IFCLK'EVENT AND CLK = '1'   
         THENQ1 <= D ;   
   END IF;
         Q <= Q1 ;            --将内部的暂存数据向端口输出
   END PROCESS ;
END bhv;

1. 上升沿检测表式和信号属性函数EVENT

例7中的“CLK’EVENT AND CLK=‘1’”是用于检测时钟信号CLK的上升沿的,即如果检测到CLK的上升沿,表达式将输出”true”.

关键词EVENT是信号属性,VHDL通过以下表式来测定某信号的跳变边沿:
    <信号名>'EVENT

“CLK’EVENT”就是对CLK的信号进行检测,当CLK的电平发生变化,则表达式输出布尔值TRUE,否则为FALSE,
而在“CLK’EVENT AND CLK=‘1’”中当CLK的电平发生变化,而CLK又为高电平’1’,两者相与(AND)后的返回值为“TRUE”.
由于当前的“CLK=‘1’”,可以推断此前的CLK必为’0’(设CLK的数据类型为BIT),
因此“CLK’EVENT AND CLK=‘1’”可以用来对信号CLK的上升沿进行检测.

2. 不完整条件语句与时序电路

分析例7可知:当时钟信号CLK发生变化时,PROCESS语句被启动,IF语句将测定条件表达式“CLK’EVENT AND CLK=‘1’”是否满足条件(即CLK上升沿是否到来),如果“TRUE”,则执行语句Q1<=D,即将D的数据向内部信号Q1赋值,并结束IF语句,最后将Q1的值向端口信号Q输出,即执行Q<=Q1.
      设想如果CLK没有出现上升沿方式的跳变,IF语句都不满足条件,即条件表达式给出“FALSE”,于是将跳过赋值表达式Q1<=D而结束IF语句的执行.由于在此,IF语句中没有利用ELSE明确指出当IF语句不满足条件时作何操作,显然这是一种不完整的条件语句(即在条件语句中,没有将所有可能发生的条件都给出对应的处理方式).
       对于这种语法现象,VHDL综合器将理解为当不满足条件时不能执行语句Q1<=D,即应保持Q1的原值不变,这就意味着必须引进时序元件来保存Q1中的值.利用这种不完整的条件语句的描述引进寄存器元件,从而构成时序电路的方式是VHDL描述时序电路最重要的途径.
       然而须注意的是,虽然在构成时序电路方面,不完整的条件语句具有独特的功能,但在利用条件语句进行纯组合电路设计时,如果没有充分考虑电路中所有可能出现的问题,即没有列全所有的条件及其对应的处理方法,将导致不完整的条件语句的描述,从而产生设计者不希望的组合与时序电路的混合体


重载函数

VHDL的IEEE库中的STD_LOGIC_UNSIGNED程序包中预定义的操作符如“+”、“-”、“*”、“=”、“<=”、“<</SPAN>”、“>”、“AND”等,对相应的数据类型的操作作了重载,赋予新的数据类型操作功能,即通过重新定义运算符的方式,准许被重载的运算符能够对新的数据类型进行操作,或者准许不同的数据类型之间用此运算符进行运算.

USE IEEE.STD_LOGIC_UNSIGNED.ALL ; 的目的就在于此,使用此程序包就是准许当遇到此例中的+号时,调用+号的算符重载函数.


变量

变量VARIABLE与信号SIGNAL一样,都属于数据对象,在此程序中的功能与信号相似.但变量的赋值符号与信号的赋值符号是不同的.信号的赋值符号是“<=”而变量的赋值符号是“:=”.例如a为变量,对其赋值可以写为: a:=‘1’,变量的功能主要用于数据的暂存.


省略赋值操作符(OTHERS=>X)

CQI:=(OTHERS=>’0’)等效于向CQI赋值”0000”,即:
                      CQI:=“0000”
为了简化表达才使用短语“(OTHERS=>’0’)”,这是一个省略赋值操作符,它可以在较多位的位矢量赋值中作省略化的赋值,如以下语句:

 SIGNAL d1: STD_LOGIC_VECTOR(4 DOWNTO 0);
VARIABLE a1 : STD_LOGIC_VECTOR(15 DOWNTO 0);
    ...
d1 <= (OTHERS=>'0');a1 := (OTHERS=>'0') ;
这条语句等同于d1<=“00000”;a1:=”000000000000000”,其优点是在给大的矢量赋值时简化了表述,明确了含义,这种表述与位矢量长度无关.

 利用“(OTHERS=>X)”还可以给位矢量的某一部分位赋值之后再使用OTHERS给剩余的位赋值,如:
  d1<=(1=>e(3),3=>e(5),OTHERS=>e(1));
此赋值语句意义是给位矢量d1的第1位赋值e(3)第3位赋值e(5),而其余位赋值为e(1).
  这个矢量赋值语句也可以改写为下面的使用连接符的语句(假设d1的长度为5位):
        d1<=e(1)&e(5)&e(1)&e(3)&e(1)

zhangyukun 发表于 2017-12-5 09:25:22

VHDL设计初步复习总结

zhiweiqiang33 发表于 2017-12-9 14:49:05

Verilog HDL语法基础

陈飞龙 发表于 2017-12-10 17:20:52

ARCHITECTURE <</SPAN>结构体名> OF <</SPAN>实体名> IS
    [说明语句]
BEGIN
    <</SPAN>功能描述语句>
END <</SPAN>结构体名>;

hellokity 发表于 2017-12-10 19:17:08

VHDL的要点,谢谢楼主分享!

zhangyukun 发表于 2018-1-30 08:59:07

VHDL设计初步复习总结

zxopenljx 发表于 2025-2-27 17:28:47

VHDL设计初步复习总结
页: [1]
查看完整版本: VHDL设计初步复习总结