资源描述
第九章VHDL程序基础,9.1VHDL程序结构9.2VHDL的语言元素9.3VHDL的基本描述语句9.4VHDL结构体的三种描述方法9.5有限状态机的设计,硬件描述语言VHDL,硬件描述语言VHDL的特点,1、支持自顶向下的设计方法,2、系统硬件描述能力强行为描述、数据流描述、结构描述。,3、系统仿真能力强,4、工艺无关性,初学者如何学好VHDL,1、掌握时钟的概念。,2、注意VHDL编程与软件编程的差别。,3、语法学习贵精不贵多,靠练不靠背。,4、注意VHDL语句的可综合性。,9.1.1VHDL程序基本结构,库(Library),包(Package),实体Entity,结构体Architecture,配置Configuration,存放已编译的实体、结构体、包集合和配置,存放各设计模块能共享的数据类型、常数、子程序等。,定义电路的输入/输出接口,描述电路内部的功能。,决定哪一个结构体被使用。,VHDL程序基本结构,VHDL中常用的资源库为IEEE库。,IEEE库:常用的资源库。IEEE库中的三个重要的包集合:STD_LOGIC_1164STD_LOGIC_ARITH(算术运算库)、STD_LOGIC_UNSIGNED等,库(LIBRARY),库说明语句的语法形式为:LIBRARY库名;-说明使用什么库USE库名.程序包名.项目名;-说明使用库中哪个程序包及包集合中的项目;,库和程序包的用法,LIBRARYIEEE;USEIEEE.STD_LOGIC_1164.ALL;USEIEEE.STD_LOGIC_ARITH.ALL;USEIEEE.STD_LOGIC_UNSIGNED.ALL;,WORK库:WORK库是现行作业库。设计者所描述的VHDL语句不需要任何说明,将都存放在WORK库中。WORK库对所有设计都是隐含可见的,因此在使用该库时无需进行任何说明。,一点注意:,要求:设计文件不能直接存放在根目录下,必须建立一个英文文件夹,系统自动将其视为work库。,实体的一般格式为:ENTITY实体名IS端口说明;END;,实体名必须与文件名相同。ENTITY、IS、END是VHDL的关键字(保留字)。实体名、端口名等均应为符合VHDL命名规则的标识符。端口:指实体中的每一个I/O信号,其功能对应于电路图符号的一个引脚。端口说明则是对一个实体的一组端口的定义,即对基本设计实体与外部接口的描述。端口是设计实体和外部环境动态通信的通道。,实体(ENTITY),ENTITYand2ISENDand2;,端口说明的一般格式为:PORT(端口名,端口名:端口模式数据类型;端口名,端口名:端口模式数据类型);,端口模式用来说明数据传输通过该端口的方向。端口模式有以下几类:IN(输入):仅允许数据流进入端口。主要用于时钟输入、控制输入、单向数据输入。OUT(输出):仅允许数据流由实体内部流出端口。该模式通常用于终端计数一类的输出,不能用于反馈。BUFFER(缓冲):该模式允许数据流出该实体和作为内部反馈时用,但不允许作为双向端口使用。INOUT(双向):可以允许数据流入或流出该实体。该模式也允许用于内部反馈。如果端口模式没有指定,则该端口处于缺省模式为:IN。数据类型原则上可以是任何标准的数据类型和用户自定义类型。,补充说明:,在端口说明时,可将几个同样方向、同样数据类型的端口放在同一说明语句里。最后一条端口说明语句后不加分号;,PORT(a,b:INSTD_LOGIC;y:OUTSTD_LOGIC);,ENTITYadd4ISPORT(a,b:INSTD_LOGIC_VECTOR(3downto0);Ci:INSTD_LOGIC;Sum:OUTSTD_LOGIC_VECTOR(3downto0);Co:OUTSTD_LOGIC);ENDadd4;,例3:四位加法器实体说明程序,结构体的一般格式如下:ARCHITECTURE结构体名OF实体名IS结构体说明部分;BEGIN并发处理语句;END结构体名;,实体名必须与实体声明部分所取的名字相同;而结构体名可由设计者自由选择;,ARCHITECTUREand2xOFand2ISBEGINy=aANDb;ENDand2x;,结构体(ARCHITECTURE),结构体的一般格式如下:ARCHITECTURE结构体名OF实体名IS结构体说明部分;BEGIN并发处理语句;END结构体名;,2)结构体说明是指对结构体需要使用的信号、常数、数据类型和函数进行定义和说明。声明语句所声明的内容只能用于该结构体中,若希望在其他的实体或结构体中引用这些定义,则须用包声明(PACKAGE).3)并发处理语句位于BEGIN和END之间,这些语句具体地描述了构造体的行为。并发处理语句是功能描述的核心部分,也是变化最丰富的部分。,并发处理语句,块语句(BLOCK),进程语句(PROCESS),信号赋值语句,子程序调用:调用过程(PROCEDURE)和函数(FUNCTION),元件例化语句(COMPONENT),配置的基本格式为:CONFIGURATION配置名OF实体名IS配置说明;END配置名;,配置语句描述了层与层之间的连接关系,以及实体与构造体之间的连接关系。设计者可以利用配置语句选择不同的构造体,使其与要设计的实体相对应;在仿真某一个实体时,可以利用配置选择不同的构造体进行性能对比实验,以得到性能最佳的构造体。,配置(CONFIGURATION),配置语句根据不同情况,其说明语句有简有繁。最简单的缺省配置格式为:,CONFIGURATION配置名OF实体名ISFOR选配结构体名ENDFOR;END配置名;,例4:加入了配置的4位等值比较器设计文件LIBRARYIEEE;USEIEEE.STD_LOGIC_1164.ALL;ENTITYcomp4ISPORT(a,b:INSTD_LOGIC_VECTOR(3downto0);y:OUTSTD_LOGIC);ENDcomp4;,-结构体1:ARCHITECTUREbehaviorOFcomp4ISBEGINComp:PROCESS(a,b)BEGINIFa=bTHENy=1;ELSEy=0;ENDIF;ENDPROCESScomp;ENDbehavior;,-结构体2:ARCHITECTUREdataflowOFcomp4ISBEGINy=1WHEN(a=b)ELSE0;ENDdataflow;,-结构体3:ARCHITECTUREstructuralOFcomp4ISCOMPONENTxnor2PORT(in1,in2:INSTD_LOGIC;Out:OUTSTD_LOGIC);ENDCOMPONENT;COMPONENTand4PORT(in1,in2,in3,in4:INSTD_LOGIC;Out:OUTSTD-LOGIC);ENDCOMPONENT;SIGNALs:STD_LOGIC_VECTOR(0to3);BEGINu0:xnor2PORTMAP(a(0),b(0),s(0);u1:xnor2PORTMAP(a(1),b(1),s(1);u2:xnor2PORTMAP(a(2),b(2),s(2);u3:xnor2PORTMAP(a(3),b(3),s(3);u4:and4PORTMAP(s(0),s(1),s(2),s(3),y);ENDstructural;,-配置:CONFIGURATIONcomp4_conOFcomp4ISFORbehaviorENDFOR;ENDcomp4_con;,9.2VHDL的语言元素,9.2.1标识符,标识符由英文字母、数字以及下划线字符组成,且:第一个字符必须是英文字母;最后一个字符不能是下划线;不允许连续两个下划线;在标识符中大、小写字母是等效的。VHDL中的注释文字一律为2个连续的连接线“-”,可以出现在任一语句后面,也可以出现在独立行;VHDL的保留字(关键字)不能用于标识符;,例如:如下标识符是合法的:tx_clkThree_state_Enablesel7DHIT_1124,如下标识符是非法的:_tx_clk-标识符必须起始于英文字母8B10B-标识符必须起始于英文字母large#number-只能是英文字母、数字、下划线link_bar-不能有连续两个下划线select-关键字(保留字)不能用于标识符rx_clk_-最后字符不能是下划线,9.2.2数据对象,在VHDL中,数据对象是可以赋予一个值的客体。常用的数据对象为常量、变量和信号,在使用前必须给予定义。,常量(CONSTANT)常量是指那些在设计描述中不会变化的值。,常量说明的一般格式如下:CONSTANT常量名,常量名:数据类型:=取值;,例如:CONSTANTwidth:integer:=8,变量(VARIABLE)变量是暂存数据的量。,变量说明的语法格式是:VARIABLE变量名,变量名:数据类型:=初始值;,例如:VARIABLEcount:INTEGERRANGE0TO99:=0变量只用于进程和子程序,它是一个局部量。变量必须在进程或子程序的说明性区域加以说明。变量的初始值赋值只在仿真时有用,而在综合时无用;,变量赋值语句格式为:目标变量名:=表达式;,赋值语句中的表达式必须与目标变量具有相同的数据类型。变量赋值是立即生效,不存在延时行为。变量常用在实现某种运算的赋值语句中。,信号(SIGNAL)信号是电子电路内部硬件实体相互连接的抽象表示。信号能够代表连线,也可内连元件,端口也是信号。,信号说明的语法格式为:SIGNAL信号名,信号名:数据类型:=初始值;,例如:SIGNALcount:BIT_VECTOR(3downto0);信号包括I/O引脚信号以及IC内部缓冲信号,有硬件电路与之对应,故信号之间的传递有实际的附加延时。信号通常在构造体、包集合和实体中说明;信号不能在进程中说明(但可以在进程中使用)。,信号赋值语句格式为:目标信号名=表达式;,赋值语句中的表达式必须与目标信号具有相同的数据类型。,信号和变量的主要区别:,声明形式与赋值符号不同;有效域不同。信号可在结构体、进程外定义;而变量在进程内定义。即:变量是一个局部量,只能用于进程或子程序中;信号是一个全局量,它可以用来进行进程之间的通信。信号赋值可以出现在进程中,也可以直接出现在结构体中,但它们的运行含义不同:前者属顺序信号赋值,此时的赋值操作要视进程是否已被启动;后者属并行信号赋值,其赋值操作是各自独立并行发生的。,4.在进程中变量和信号的赋值形式与操作过程不同:在变量的赋值语句中,该语句一旦被执行,其值立即被赋予变量。在执行下一条语句时,该变量的值即为上一句新赋的值。在信号的赋值语句中,该语句即使被执行,其值不会使信号立即发生代入,在下一条语句执行时,仍使用原来的信号值。直到进程结束之后,所有信号赋值的实际代入才顺序进行处理。因此,实际代入过程和赋值语句的执行是分开进行的。如例12所示。,5、可在不同的进程中读取一个信号,但不能在不同的进程中对同一个信号进行赋值。6、在同一进程中对同一信号进行多次赋值操作时,只有最后一次会生效。,当进程运行时,信号赋值将自上而下顺序执行,但第一项赋值操作并不会发生,这是因为信号赋值是在进程结束时才起作用。因为在进程结束更新时,d的最后一个赋值为c,因此执行结果为该式。,9.2.3数据类型,VHDL是一种类型型很强的语言。VHDL中只有相同数据类型的量,才能相互之间发生作用。,VHDL预定义数据类型,整数(INTEGER):取值范围为(2311)(2311)。,variablea:integerrange255to255;,布尔量(Boolean):取值为TURE、FALSE;用于逻辑(关系)运算。,位(BIT):只有两种取值,即0和1,可用于描述信号的取值.,位矢量(BIT_VECTOR):是用双引号括起来的一组数据,每位只有两种取值:0和1。在其前面可加以数制标记,如X(16进制)、B(2进制、默认)、O(8进制)等。位矢量常用于表示总线的状态。,Data=O“15”Data=B“1101”,SIGNALa:BIT_VECTOR(0TO3);SIGNALa:BIT_VECTOR(3DOWNTO0);,Real(实数)。取值范围为1.0E+38+1.0E+38。由于实数运算需要大量的资源,因此综合工具常常并不支持实数类型。,Time(时间)。时间的取值范围从(2311)到(2311)。时间由整数值、一个以上空格以及时间单位组成。常用的时间单位有:fs、ns、s、ms、s、min、hr等。时间是一个具有量纲的数据,故只能用于指定时间延时和仿真过程,而综合器并不支持。,Natural(自然数)和Positive(正整数)。是整数类型的子类型。自然数取值范围为0(2311);正整数是大于0的整数。,SeverityLevel(错误等级)。错误等级分为:NOTE(注意)、WARNING(警告)、ERROR(出错)、FAILURE(失败)四级,用于提示系统的错误等级。只用于仿真。,Character(字符)。是用单引号括起来的一个字母、数字、空格或一些特殊字符(如$、%等)。字符区分大、小写字母。,String(字符串)。是用双引号括起来的一个字符序列。字符串区分大、小写字母。常用于程序的提示和结果说明等。,IEEE预定义标准逻辑位(STD_LOGIC)和矢量(STD_LOGIC_VECTOR),TYPESTD_LOGICISU,-未初始化的X,-不定态0,-01,-1Z,-高阻态W,-弱信号不定态L,-弱信号0H,-弱信号1_,-不可能情况(可忽略值),LIBRARYIEEE;USEIEEE.STD_LOGIC_1164.ALL;,2.用户自定义数据类型VHDL允许用户自己定义数据类型。,自定义数据类型说明语句的一般格式是:TYPE数据类型名,数据类型名IS数据类型定义of基本数据类型;,常用的用户自定义数据类型主要有:(1)枚举(Enumerated)类型。通过列举某类变量所有可能的取值来加以定义。对这些取值,一般使用自然语言中有相应含义的单词或字符序列来代表,以便于阅读和理解。,枚举类型定义的格式为:TYPE数据类型名IS(元素1,元素2,);,TYPEm_stateIS(s1,s2,s3,s4,s5);SIGNALpresent_state,next_state:m_state;,在程序包STD_LOGIC_1164中对STD_LOGIC的定义为TYPESTD_LOGICIS(U,X,0,1,Z,W,L,H,_);,(2)数组(ARRAY)类型。又称为向量,是多个相同类型的数据集合。它可以是二维的和多维的。,数组类型定义的格式为:TYPE数组名ISARRAY(范围)OF元素数据类型名;,TYPEmISARRAY(7downto0)OFSTD_LOGIC;,TYPEcount1ISARRAY(STD_LOGIC_DOWNTOU)OFINTEGER;,(3)纪录(RECORD)类型:是多个不同类型的数据集合。,纪录类型定义的格式为:TYPE数据类型名ISRECORD元素名:数据类型名;元素名:数据类型名;ENDRECORD;,(4)时间(TIME)类型(物理类型)。表示时间的数据类型,在仿真时是必不可少的。,时间类型定义的一般格式为:TYPE数据类型名IS范围;UNITS基本单位;单位;ENDUNITS;,例如:在STANDARD程序包中定义的时间,如下:TYPEtimeISrange1e18TO1e18;UNITSfs;ps=1000fs;ns=1000ps;s=1000ns;ms=1000s;set=1000ms;min=60set;hr=60min;ENDUNITS;这里的基本单位是“fs”。时间是物理类型的数据,当然对容量、阻抗值也可以做定义。,(5)子类型(SUBTYPE)。是由type所定义的原数据类型的一个子集。它只是在基本数据类型的基础上作了些约束,但是没有定义新的数据类型。,子类型定义的一般格式为:SUBTYPE子类型名IS基本数据类型名约束范围;,SUBTYPEdigitISINTEGERrange0to9;,SUBTYPEdigit2ISstd_logic_vector(0to9);,Subtypedigit3isarray(0to9)ofinteger;,3.数据类型的转换在VHDL程序中,不同类型的对象不能代入,因此要进行类型转换。类型转换的方法有:,(1)类型标记法。用类型名称来实现关系密切的标量类型之间的转换。例如:VARIABLEx:INTEGER;VARIABLEy:REAL;使用类型标记(即类型名)实现类型转换时,可采用赋值语句:x:=INTEGER(y);y:=REAL(x)。,(2)类型函数法。,CONV_INTEGER():将STD_LOGIC_VECTOR类型转换成INTEGER类型。CONV_STD_LOGIC_VECTOR():将INTEGER类型、UNSIGNED类型或SIGNED类型转换成STD_LOGIC_VECTOR类型。TO_BIT():将STD_LOGIC类型转换成BIT类型。TO_BIT_VECTOR():将STD_LOGIC_VECTOR类型转换BIT_VECTOR类型。TO_STD_LOGIC():将BIT类型转换成STD_LOGIC类型。TO_STD_LOGIC_VECTOR():将BIT_VECTOR类型转换成STD_LOGIC_VECTOR类型。,其中,第1个函数由STD_LOGIC_UNSIGNED程序包定义,第2个函数由STD_LOGIC_ARITH定义,其余均由STD_LOGIC_1164定义。引用前必须先打开库和相应的程序包。,例题:用转换函数语句设计一个译码电路。,Entitydecoder1isport(input:instd_logic_vector(0to2);output:outstd_logic_vector(7downto0);Enddecoder1;,Architecturebehaveofdecoder1isbeginprocess(input)beginoutput(conv_integer(input)=1;endprocess;Endbehave;,Libraryieee;Useieee.std_logic_1164.all;Useieee.std_logic_unsigned.all;,9.2.4运算符与操作符,关于括号:表达式中如果一串运算中的算符相同,且是AND,OR,XOR中的一种,则不需使用括号;如果一串运算中的算符不同或有这三种算符之外的算符,则必须使用括号。操作数的数据类型必须是操作符所规定的数据类型。严格遵循在基本操作符间操作数是同数据类型的规则。注意运算符的优先级别;见讲义。,(1)算术运算符,Libraryieee;Useieee.std_logic_1164.all;Useieee.std_logic_unsigned.all;,(2)关系运算符:它包括:=、/=、=、=。其作用是将相同数据类型的数据对象进行数值比较或关系排序判断,并将结果以boolean类型表示。和/=的操作对象可以是任意数据类型;但其余运算符的操作对象则仅限于整数或一维数组。注意小于等于和赋值符号的区分。(3)逻辑运算符:包括一元逻辑运算符和二元逻辑运算符。一元逻辑运算符包括:NOT。二元逻辑运算符包括:AND、OR、NAND、NOR、XOR、XNOR。逻辑运算符的操作对象为boolean,bit,std_logic;也可以是bit_vector,std_logic_vector,但必须位宽要相同;且数组间的运算必须按位进行;Not的优先级别最高,但其它逻辑运算符的优先级别最低;建议使用括号。,Signala,b,c:std_logic_vector(3downto0);Signald,e,f,g:std_logic_vector(1downto0);Signalh,I,j,k:std_logic;SignalL,m,n,o,p:boolean;a=bandc;d=eorforg;h=(Inandj)nandk;L=(mxorn)and(oxorp);h=Iandjork;a=bande;h1,others=0);,2.2.5属性(Attributes),属性是指语言中某个项目的特性。预定义属性描述语句是一个预定义函数,其格式为:,属性测试项目名属性标示符,综合器支持的属性有:left,right,high,low,range,reverse_range,length,event,stable.,1、EVENT例如:CLKEVENTANDCLK=1,2、LEFT,RIGHT,HIGH,LOW例如:TYPEnumISARRAYRANGE7DOWNTO0;VARIABLEi1,i2,i3,i4:INTEGER;BEGINi1:=numLEFT;-i1取得num的左边界值7i2:=numRIGHT;-i2取得num的右边界值0i3:=numHIGH;-i3取得num的上限值7i4:=numLOW;-i4取得num的下限值0,3、LENGTH例如:TYPEnumISARRAYRANGE7DOWNTO0;VARIABLEM:INTEGER;BEGINM:=numLENGTH;,4、RANGE和REVERSE_RANGE例如:SIGNALS:STD_LOGIC_VECTOR(0TO7)FORIinsrangeloop或FORIinsreverse_rangeloop,ForIin0to7loop,ForIin7downto0loop,9.3.2VHDL结构体的基本子结构,在规模较大的电路设计中,整个电路将被分成若干个相对独立的模块来描述。这样,一个结构体可以用几个子结构,即相对独立的几个模块来构成。VHDL语言有以下3种形式的子结构描述语句:,BLOCK语句结构PROCESS语句结构SUBPROGRAMS结构,2.1.2.2进程(PROCESS),PROCESS语句是VHDL语言中最重要的语句之一,特点如下:进程本身是一种并发处理语句,在一个构造体中多个PROCESS语句可以同时并发运行,但其内部则为顺序语句;进程只有在特定的时刻才会被激活执行。,进程语句的语法格式1:进程名:PROCESS(敏感信号表)进程说明语句;BEGIN顺序描述语句;ENDPROCESS进程名;,进程语句的语法格式2:进程名:PROCESS进程说明语句;BEGINWAILUNTIL(激活进程的条件);顺序描述语句;ENDPROCESS进程名;,例9利用PROCESS语句设计与非门电路。nandx:PROCESS(a,b)BEGINy=aNANDb;ENDPROCESSnandx;,进程标号不是必需的;敏感信号表所标明的信号是用来启动进程的。若无敏感信号时,则通过WAIT语句来实现。WAITUNTIL条件表达式;PROCESS语句声明部分定义的量只适用于本进程。最常在此处定义的是变量。因为信号是全局量。PROCESS内部各语句之间是顺序关系。在系统仿真时,PROCESS语句是按书写顺序一条一条向下执行的。而不象BLOCK中的语句可以并行执行。,系统上电,进程挂起,敏感信号发生变化?,敏感信号发生变化?,顺序语句1,进程挂起,顺序语句1,顺序语句n,顺序语句n,N,N,Y,Y,进程1,进程2,进程的工作原理示意图,进程可用来描述组合逻辑,也可以用来描述时序逻辑。,时钟沿的VHDL描述:CLK:INSTD_LOGIC;上升沿描述:CLKEVENTANDCLK=1或者RISING_EDGE(CLK)下降沿描述:CLKEVENTANDCLK=0或者falling_edge(CLK),一个进程不可同时对时钟上、下沿敏感。,PROCESS(CLK)BEGINIFrising_edge(clk)THENELSIFfalling_edge(clk)THEN,PROCESS(CLK)BEGINIFrising_edge(clk)THENELSE,例题:2分频电路(fenpin2.vhd),architecturebehavoffenpin2issignalq:std_logic;beginprocess(clkin)beginifrising_edge(clkin)thenq=notq;endif;endprocess;clkout=q;endbehav;,libraryieee;useieee.std_logic_1164.all;,entityfenpin2isport(clkin:instd_logic;clkout:outstd_logic);endfenpin2;,architecturebehavoffenpin2isbeginprocess(clkin)beginifrising_edge(clkin)thenclkout=notclkin;endif;endprocess;endbehav;,例题:计数器(count10.vhd),libraryieee;useieee.std_logic_1164.all;Useieee.std_logic_unsigned.all;,entitycount10isport(clk:instd_logic;q:bufferstd_logic_vector(0to3);endcount10;,Architecturebehavofcount10isbeginprocess(clk)beginifrising_edge(clk)thenifq=1001thenq=0000;elseq=q+1;endif;endif;endprocess;endbehav;,9.3VHDL的基本描述语句,9.3.1顺序描述语句9.3.2并发描述语句,Vhdl程序设计中两大基本描述语句系列:,9.3.1顺序描述语句,信号代入语句变量赋值语句WAIT语句IF语句CASE语句,LOOP语句NEXT语句EXIT语句RETURN语句NULL语句,顺序语句的特点是:每一条顺序语句的执行顺序是与它们的书写顺序基本一致的。顺序语句只能出现在进程和子程序中。,变量赋值语句格式为:目标变量名:=表达式;,信号赋值语句格式为:目标信号名=表达式;,Libraryieee;Useieee.std_logic_1164.all;,Entitytest_signalisPort(clr,clk:instd_logic;q1,q2:outintegerrange0to9);Endtest_signal;,1、赋值语句(signal,variable)将一个值或表达式的运算结果传递给某一数据对象。,Test_signal.vhd,Architecturetestoftest_signalisSignalA,B:integerrange0to9;BeginProcess(clk,clr)Variablec:integerrange0to9;BeginIfclr=1thenA=0;B=2;C:=0;,Elsifrising_edge(clk)thenc:=c+1;A=c+1;B=A+2;ENDIF;ENDPROCESS;Q1=A;Q2=B;ENDTEST;,几种赋值形式,1、标识符赋值,Variablea:std_logic;Signalc:std_logic_vector(0to3);a:=1;C=“0001”;,2、数组元素赋值:数组名(下标),C(1)=0;C(1to2)=“00”;C(3downto2)=“10”,在进程(或过程)中,当执行到WAIT等待语句时,运行程序将被挂起,直到满足此语句的结束挂起条件后,将重新开始执行进程(或过程)中的程序。,WAIT语句有以下四种形式:WAIT-无限等待WAITON敏感信号表;-敏感信号量变化,进程启动WAITUNTIL条件表达式;-表达式成立时,进程启动WAITFOR时间表达式;-时间到,进程启动,2、WAIT语句,IF语句的语法格式一:IF条件THEN顺序处理语句;ENDIF;,例:IF(a=1)THENc=b;ENDIF;,这种描述经逻辑综合,实际上可以生成D触发器。,3、IF语句,ARCHITECTURErtlOFdffISBEGINPROCESS(clk)BEGINIF(clkeventandclk=1)THENq=d;ENDIF;ENDPROCESS;ENDrtl;,例2设计D触发器。,IF语句的语法格式为:IF条件THEN顺序处理语句l;ELSE顺序处理语句2;ENDIF;,ARCHITECTURErtlOFmux2_1ISBEGINPROCESS(a,b,sel)BEGINIF(sel=1)THENc=a;ELSEc=b;ENDIF;ENDPROCESS;ENDrtl;,例3设计2选1的数据选择器。,IF语句的语法格式3为:IF条件1THEN顺序处理语句1;ELSIF条件2THEN顺序处理语句2;ELSIF条件nTHEN顺序处理语句n;ELSE顺序处理语句n+l;ENDIF;,例4设计4选1的多路选择器,ENTITYmux4_1ISPORT(d:INSTD_LOGIC_VECTOR(3DOWNTO0);sel:INSTD_LOGIC_VECTOR(1DOWNTO0);y:OUTSTD_LOGIC);ENDmux4_1;,ARCHITECTURErtlOFmux4_1ISBEGINPROCESS(d,sel)BEGINIF(sel=00)THENy=d(0);ELSIF(sel=01)THENy=d(1);ELSIF(sel=10)THENy=d(2);ELSEy=d(3);ENDIF;ENDPROCESS;ENDrtl;,LIBRARYieee;USEieee.std_logic_1164.ALL;ENTITYpriencoderISPORT(input:INSTD_LOGIC_VECTOR(7DOWNTO0);y:OUTSTD_LOGIC_VECTOR(2DOWNTO0);ENDpriencoder;,例5设计优先编码器,ARCHITECTURErtlOFpriencoderISBEGINPROCESS(input)BEGINIF(input(7)=0)THENy=111;ELSIF(input(6)=0)THENy=110;ELSIF(input(5)=0)THENy=101;ELSIF(input(4)=0)THENy=100;ELSIF(input(3)=0)THENy=011;ELSIF(input(2)=0)THENy=010;ELSIF(input(1)=0)THENy=001;ELSEy=000;ENDIF;ENDPROCESS;ENDrtl;,几点注意:,1、if语句可以嵌套使用,但层数不宜太多;2、用if语句描述异步复位和时钟沿时,只能用ifelsifend语句。,Process(clk)BeginIfclkeventandclk=1thenS顺序处理语句;WHEN条件表达式的值|值|值=顺序处理语句;WHEN条件表达式的值to值=顺序处理语句;WHENOTHERS=顺序处理语句;,4、CASE语句:根据满足的条件直接选择多项顺序语句中的一项执行。,使用case语句必须注意:,1、case语句之间是并行处理的,没有先后顺序:2、除非所有条件句中的选择值能够涵盖case语句中表达式的所有取值,否则最末一条必须是whenothers。在使用std_logic时必须注意。3、case语句中每一条件句中的选择值只能出现一次,不能重复。,例6:4选1多路选择器(mux4_1.vhd),ARCHITECTUREarchOFmux4_1ISBEGINPROCESS(d,sel)BEGINCASEselISWHEN00=yyyyy=x;ENDCASE;ENDPROCESS;ENDarch;,8位数据的4选1如何实现?,CASE语句与IF语句的区别:在IF语句中,先处理最起始的条件,如果不满足,再处理下一个条件。在CASE语句中,没有值的顺序号,所有值是并行处理的。因此,在WHEN项中的值不能重复使用。,例7:3-8译码器(decoder3_8.vhd),LIBRARYieee;USEieee.std_logic_1164.ALL;ENTITYdecode3_8ISPORT(a,b,c:INSTD_LOGIC;g1,g2a,g2b:INSTD_LOGIC;y:OUTSTD_LOGIC_VECTOR(7DOWNTO0);ENDdecode3_8;,ARCHITECTURErtlOFdecode3_8ISSIGNALind:STD_LOGIC_VECTOR(2DOWNTO0);BEGINindyyyyyyyyy=XXXXXXXX;ENDCASE;ELSEyyyyyyyyyy=XXX;ENDCASE;ENDPROCESS;ENDrtl;,5、LOOP语句,LOOP语句的书写格式一般有两种:,FOR循环变量形成的LOOP语句,其一般格式为:循环标号:FOR循环变量IN循环范围LOOP顺序处理语句;ENDLOOP循环标号;,循环变量是一个临时变量,属于局部变量。它仅在LOOP语句中有效,因此,不需要事先定义,它由LOOP语句自动定义。循环变量是一个整数变量,不用事先说明。其中循环范围是指循环变量在循环中依次取值的范围。,todownto,例9奇偶校验电路(parity_check.vhd),ENTITYparity_checkISPORT(a:INSTD_LOGIC_VECTOR(7downto0);y:OUTSTD_LOGIC);ENDparity_check;,ARCHITECTURErtlOFparity_checkISBEGINy=a(0)xora(1)xora(2)xora(3)xora(4)xora(5)xora(6)xora(7);ENDrtl;,ARCHITECTURErtlOFparity_checkISBEGINPROCESS(a)VARIABLEtmp:STD_LOGIC;BEGINtmp:=0;FORiIN0to7LOOPtmp:=tmpXORa(i);ENDLOOP;y=tmp;ENDPROCESS;ENDrtl;,例10双向移位寄存器(shift.vhd),FORiIN7downto1LOOPa(i)=a(i-1);,FORiIN0to6LOOPa(i)=a(I+1);,ENTITYshiftISPORT(clr,clk,load,ctr,sr,sl:INSTD_LOGIC;d:INSTD_LOGIC_VECTOR(7downto0);q:OUTSTD_LOGIC_VECTOR(7downto0);ENDshift;,ARCHITECTUREarcOFshiftISSIGNALa:STD_LOGIC_VECTOR(7downto0);BEGINq=a;PROCESS(clr,clk)BEGINIF(clr=0)THENa=00000000;,ELSIF(clkEVENTANDclk=1)THENIFload=0THENa=d;ELSIF(load=1ANDctr=0)THENFORiIN7downto1LOOPa(i)=a(i-1);ENDLOOP;a(0)=sr;ELSIF(load=1ANDctr=1)THENFORiIN0to6LOOPa(i)=a(i+1);ENDLOOP;a(7)=sl;ENDIF;ENDIF;ENDPROCESS;ENDarc;,WHILE条件下的LOOP语句,其格式为:循环标号:WHILE条件LOOP顺序处理语句;ENDLOOP循环标号;,该语句中,如果条件为真,执行顺序处理语句;否则,结束循环。,例12用WHILE条件下的LOOP语句描述奇偶校验电路。ARCHITECTUREbehavOFparity_checkISBEGINPROCESS(a)VARIABLEtmp:STD_LOGIC;VARIABLEi:INTEGER;BEGINtmp:=0;i:=0;WHILE(i8)LOOPtmp:=tmpXORa(i);i:=i+1;ENDLOOP;y=tmp;ENDPROCESS;ENDbehav;,6、NEXT语句:结束本次循环。,NEXT语句的书写格式为:NEXT标号WHEN条件;,例13:L1:WHILEi10LOOPL2:WHILEj10LOOPNEXTL1WHENi=j;ENDLOOPL2;ENDLOOPL1;,7、EXIT语句,EXIT语句的书写格式为:EXIT标号WHEN条件;,当“WHEN条件”为真时,跳出LOOP至程序标号处。如果EXIT后面无“标号”和“WHEN条件”,则程序执行到该语句时即无条件从LOOP语句跳出,结束循环状态,继续执行后继语句。,例15:PROCESS(a)VARIABLEint_a:INTEGER;BEGINint_a:=a;FORiIN0tomaxlimLOOPIF(int_a=0)THENEXIT;ELSEint_a:=int_a-1;q(i)=3.1416/real(int_a*i);ENDIF;ENDLOOP;y=q;ENDPROCESS;,8、RETURN语句,返回语句的两种语法格式:RETURN;RETURN条件表达式;,PROCEDURErs(SIGNALs,r:INSTD_LOGIC;SIGNALq,nq:OUTSTD_LOGIC)ISBEGINIF(s=1ANDr=1)THENREPORTForbiddenstate:sandrareequalto1;RETURN;ELSEqtmp:=regaORregb;WHEN”110”=tmp:=NOTrega;WHENothers=NULL;ENDCASE;,对于有的EDA工具,如MAX+PLUS对NULL语句的执行会出现擅自加入锁存器的情况,对此应避免使用NULL语句,改用确定操作。如:WHENothers=tmp:=rega;,9.3.2并发描述语句,进程语句BLOCK语句并发代入语句条件代入语句,选择信号语句ASSERT语句COMPONENT语句GENERATE语句,并发描述语句的特点并发语句在结构体中的执行都是同时进行的,即它们的执行顺序和语句书写顺序无关。故语句没有先后之分。,PROCESS语句是一种并发处理语句,在一个构造体中多个PROCESS语句可以同时并发运行。因此,PROCESS语句是VHDL中描述硬件系统并发行为的最常用、最基本的语句。PROCESS语句的特点:1.可以与其它进程并发执行,并可存取结构体或实体所定义的信号。2.进程中的所有语句都是顺序执行的。3.进程中必须包含一个显式的敏感信号表或者包含一个WAIT语句。4.进程之间的通信是通过信号量传递来实现的。,PROCESS语句,简单信号赋值语句;选择信号赋值语句;条件信号赋值语句。,这3种赋值语句的赋值目标都必须是信号。,并发信号代入语句,1、简单信号赋值语句,简单信号赋值语句格式为:赋值目标=表达式;,Signale,f,g,h:std_logic;G=eorf;H=eandf;,并发信号代入语句实际上是一个进程的缩写。,例如:ARCHITECTUREbehavOFa_varISBEGINoutput=a(i);ENDbehav;,ARCHITECTUREbehavOFa_varISBEGINPROCESS(a,i)BEGINoutput=a(i);ENDPROCESS;ENDbehav;,2、条件信号代入语句,条件信号赋值语句的格式为:目标信号=表达式1WHEN条件1ELSE表达式2WHEN条件2ELSE表达式n;,执行该语句时,每一赋值条件是按书写的先后关系逐项测定的,一旦发现条件为“true”,立即将表达式的值赋予目标信号。故条件信号代入语句的赋值具有优先级别,其中第1子句优先级别最高,依次类推,例:4选1多路选择器ENTITYwmux4_1ISPORT(i0,i1,i2,i3,a,b:INSTD_LOGIC;q:OUTSTD_LOGIC);ENDwmux4_1;ARCHITECTURErtlOFwmux4_1ISSIGNALsel:STD_LOGIC_VECTOR(1downto0);BEGINsel=b,如何实现8线3线的优先编码器:要求输入高有效;输出为原码输出。,3、选择信号语句,选择信号赋值语句的格式为:WITH条件表达式SELECT目标信号=表达式1WHEN条件1,表达式2WHEN条件2,表达式nWHEN条件n;,1.选择信号语句与进程中的CASE语句相似,但不能在进程中应用。2.选择信号语句具有敏感量,即WITH后面的选择条件表达式。每当选择表达式的值发生变化,便启动该语句对各子句的选择值(条件)进行测试对比,当发现有满足条件的子句时,就将此子句表达式的值赋予目标信号。3.与CASE语句相类似,该语句对子句条件选择值具有同期性(非顺序性)。4.不允许有条件重叠现象,也不允许存在条件涵盖不全的情况。,选择信号赋值语句的格式为:WITH条件表达式SELECT目标信号=表达式1WHEN条件1,表达式2WHEN条件2,表达式nWHEN条件n;,例:4选1多路选择器ENTITYsmux4_1ISPORT(i0,i1,i2,i3,a,b:INSTD_LOGIC;q:OUTSTD_LOGIC);ENDsmux4_1;ARCHITECTUREbehavOFsmux4_1ISSIGNALsel:INTEGERrange0to3;BEGINWITHselSELECTq=i0WHEN0,i1WHEN1,i2WHEN2,i3WHEN3,XWHENOTHERS;sel=0WHENa=0ANDb=0ELSE1WHENa=1ANDb=0ELSE2WHENa=0ANDb=1ELSE3;ENDbehav;,思考:,若要实现数码管的闪烁显示该如何设计?,libraryieee;useieee.std_logic_1164.all;entityflashisport(en,clk:instd_logic;dih:instd_logic_vector(7downto4);dil:instd_logic_vector(3downto0);doh:outstd_logic_vector(7downto4);dol:outstd_logic_vector(3downto0);endflash;,architecturearflaofflashisbeginprocess(en,clk,dih,dil)beginif(en=1)thenif(clk=1)thendoh=dih;dol=dil;elsedoh=1110;dol=1110;endif;elsedoh=dih;dol=dil;endif;endprocess;endarfla;,COMPONENT语句,元件说明语句的书写格式为:COMPONENT元件名GENERIC说明;PORT说明;ENDCOMPONENT;,元件例化语句的格式为:标号:元件名PORTMAP(信号,),例1:半加器(h_adder.vhd)ENTITYh_adderISPORT(a,b:INSTD_LOGIC;s,c:OUTSTD_LOGIC);ENDh_adder;ARCHITECTURErtlOFh_adderISBEGINc=aANDb;s=aXORb;ENDrtl;,例2:全加器,ARCHITECTUREarcOFf_adderISCOMPONENTh_adderPORT(a,b:INSTD_LOGIC;s,c:OUTSTD_LOGIC);ENDCOMPONENT;SIGNALs1,c1,c2:STD_LOGIC;BEGINu1:h_adderPORTMAP(a,b,s1,c1);u2:h_adderPORTMAP(s1,ci,s,c2);co=c1ORc2;ENDarc;,b,例2:全加器(f_adder.vhd)ENTITYf_adderISPORT(a,b,ci:INSTD_LOGIC;s,co:OUTSTD_LOGIC);ENDf_adder;,GENERATE语句,GENERATE语句用来产生多个相同的结构。或者说用于创建硬件中重复部分的VHDL结构。,格式1:标号名:FOR变量IN范围GENERATE并发处理语句;ENDGENERATE标号名;,FOR-GENERATE语句在形式上与FOR-LOOP语句相象,但结构中前者是并发处理,后者是顺序处理。故FOR-GENERATE语句结构中不能使用EXIT和NEXT语句。在FOR-GENERATE语句中,变量i不需要事先定义。,例1:4位移位寄存器(用FOR-GENERATE语句shift4.vhdDff.vhd),ARCHITECTUREg_shift4OFshift4ISCOMPONENTdffPORT(d,clk:INSTD_LOGIC;q:OUTSTD_LOGIC);ENDCOMPONENT;SIGNALz:STD_LOGIC_VECTOR(0TO4);BEGINz(0)=a;g1:FORiIN0TO3GENERATEffx:dffPORTMAP(z(i),clk,z(i+1);ENDGENERATE;b=z(4);ENDg_shift4;,格式2:标号名:IF条件GENERATE并发处理语句;ENDGENERATE标号名;,例2:k位移位寄存器(用IF-GENERATE语句)ENTITYshiftISGENERIC(
展开阅读全文