本文主要是介绍第一章 VHDL基本结构,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
第一章 VHDL基本结构
1.1 实体
1.2 结构体
1.3 块、子程序和进程
1.4 库和程序包
1.5 配置
一个完整的VHDL程序,或者说设计实体,通常要求最低能为VHDL综合器所支持,并能作为一个独立的设计单元,即元件的形式而存在的VHDL程序。在VHDL程序中,通常包含实体(ENTITY)、结构体(ARCHITECTURE)、配置(CONFIGURATION)、包集合(PACKAGE)和库(LIBRARY)5个部分。其中实体和结构体这两个基本结构是必需的,他们可以构成最简单的VHDL程序。
1.1 实体
设计实体是VHDL语言设计的基本单元,简单的可以是一个与门,复杂的可以是一个微处理器或一个数字系统,其结构基本是一致的,都是由实体说明和结构体两部分组成。实体说明是对这个设计实体与外部电路进行接口的描述,它规定了设计单元的输入输出接口信号或引脚,是设计实体对外的一个通信界面。结构体用于描述此设计实体的逻辑结构和逻辑功能。
实体语句结构如下:
ENTITY 实体名 IS
[GENERIC(类属表);]
[PORT(端口表);]
END ENTITY 实体名;
例:
ENTITY or2 IS
PORT(a,b:IN STD_LOGIC;
C: OUT STD_LOGIC);
END ENTITY or2;
注意:实体应以语句“ENTITY 实体名 IS”开始,语句“END ENTITY 实体名;”结束。
在层次化系统设计中,实体说明是整个模块或整个系统的输入输出(I/O)接口;在一个器件级的设计中,实体说明是一个芯片的输入输出(I/O)。
1.1.1类属参量(GENERIC)
类属参量是实体说明组织中的可选项,放在端口说明之前,其一般格式为:
GENERIC [CONSTANT] 名字表:[IN] 子类型标识 [:= 静态表达式],…]
类属参量是一种端口界面常数,常用来规定端口的大小、实体中子元件的数目及实体的定时特性等。它和常数不同,常数只能从设计实体的内部得到赋值且不能改变,而类属参量的值可由设计实体的外部提供。因此设计者可以从外面通过类属参量的重新设定而容易的改变一个设计实体或一个元件的内部电路结构和规模。
例:
GENERIC (trise,tfall:TIME:=1ns;
Addrwidth:INTEGER:=16);
PORT(a0, a1 : IN STD_LOGIC;
Add_bus:OUT STD_LOGIC_VECTOR(addrwidth-1 DOWNTO 0);
这里类属参量中参数trise为上升沿宽度,tfall为下降沿宽度,用于仿真模块的设计;定义地址总线的宽度为Addrwidth位,类属值Addrwidth的改变将使结构体中所有相关的总线定义同时改变,由此使整个设计实体的硬件结构发生变化。
1.1.2 端口说明(PORT)
端口为设计实体和其外部环境提供动态通信的通道,是对基本设计单元与外部接口的描述,其功能相当电路图符号的外部引脚。端口可以被赋值,也可以当做逻辑变量用在逻辑表达式中。
其一般书写格式为:
PORT (端口名 :端口模式 数据类型;
端口名 :端口模式 数据类型;
… …);
其中端口名是设计者为实体的每一个对外通道所取的名字,通常为英文字母加数字,名字的定义有一定的惯例,如clk 表示时钟,D开头的端口名表示数据,A开头的端口名表示地址。端口模式是指这些通道上的数据流动的方式,如输入或输出等。
端口模式有以下几种类型:
1.输入(IN)
允许信号进入实体,主要用于时钟输入、控制输入(如load、reset、enable、clk)和单向的数据输入(如地址数据信号address)等。
2.输出(OUT)
输出模式只允许信号离开实体,常用于计数输出、单向数据输出、被设计实体产生的控制其他实体的信号等。注意:输出模式不能用于被设计实体的内部反馈,因为输出端口在实体内不能看做是可读的。
3.双向模式(INOUT)
双向模式允许信号双向传输(既可以进入实体,也可以离开实体),双向模式端口允许引入内部反馈。
4.缓冲(BUFFER)
缓冲模式允许信号输出到实体外部,但同时也可以在实体内部引用该端口的信号。缓冲端口既能用于输出也能用于反馈。缓冲模式用于在实体内部建立一个可读的输出端口,例如计数器输出、计数器的现态用来决定计数器的次态。
端口模式可用图下说明,图中方框代表一个设计实体或模块。
在VHDL设计中,通常将输入信号端口指定为输入模式,输出信号端口指定为输出模式,而双向数据通信信号,如计算机PCI总线的地址/数据复用总线,DMA控制器数据总线等纯双向的信号采用双向端口模式。从端口的名称、模式就能一目了然地指导信号的用途、性质、来源和去向。
1.2 结构体
结构体也叫构造体,结构体描述了基本设计单元(实体)的结构、行为、元件及内部连接关系,也就是说它定义了设计实体的功能,规定了设计实体的数据流程,制定了实体内部元件的连接关系。结构体对其基本设计单元的输入和输出关系可用以下三种方式进行描述,即行为描述(基本设计单元的数学模型描述)、寄存器传输描述(数据流描述)和结构描述(逻辑元件连接描述)。
结构体是对实体功能的具体描述,因此它一定要跟在实体的后面 。
结构体一般由两大部分组成:
1.对数据类型、常数、信号、子程序和元件等因素进行说明的部分;
2.描述实体的逻辑行为、以各种不同的描述风格表达的功能描述语句,包括各种顺序语句和并行语句。
结构体的语句格式为:
ARCHITECTURE 结构体名 OF 实体名 IS
[定义语句]
BEGIN
[功能描述语句]
END 结构体名;
1.2.1 结构体名
结构体名由设计者自行定义,OF后面的实体名指明了该结构体所对应的是哪个实体。有些设计实体有多个结构体,这些结构体的结构体名不可相同,通常用dataflow(数据流)、behavior(行为)、structural(结构)命名。这3个名称体现了3种不同结构体的描述方式,使得阅读VHDL语言程序时,能直接了解设计者采用的描述方式。
1.2.2 结构体信号定义语句
结构体信号定义语句必须放在关键词ARCHITECTURE和BEGIN之间,用于对结构体内部将要使用的信号、常数、数据类型、元件、函数和过程加以说明。需要注意的是实体说明中定义的信号是外部信号,而结构体定义的信号为该结构体的内部信号,它只能用于这个结构体中。
结构体中的信号定义和端口说明一样,应有信号名称和数据类型定义。因为它是内部连接用的信号,因此不需要方向说明。
例:结构体的信号定义实例。
ARCHITECTURE rtl OF muj IS --rtl:结构体名,muj实体名
SIGNAL s1:BIT --结构体信号定义语句
SIGNAL s2,s3:STD_LOGIC_VECTOR (0 TO 3);
…
BEGIN
…. --功能描述语句
END rtl;
1.2.3 结构体功能描述语句
结构体功能描述语句位于BEGIN和END之间,具体地描述了构造体的行为及其连接关系。结构体的功能描述语句可以含有5种不同类型的并行语句,如图所示。每一语句结构内部可以使用并行语句,也可以是顺序语句。
结构体构造图:
图中5种功能描述语句的基本组成和功能分别是:
1块语句(BLOCK)是由一系列并行语句构成的组合体,它的功能是将结构体中的并行语句组成一个或多个子模块。
2进程语句定义顺序语句模块,用以将从外部获得的信号值或内部运算数据向其他的信号进行赋值。
3信号赋值语句将设计实体内的处理结果向定义的信号或界面端口进行赋值。
4子程序调用语句可以调用进程或参数,并将获得的结果赋值于信号。
5元件例化语句对其他的设计实体做元件调用说明,并将此元件的端口与其他元件、信号或高层实体的界面端口进行连接。
例: 2选1数据选择器
ENTTITY mux2 IS
PORT (d0,d1:IN BIT;
sel:IN BIT;
s:OUT BIT);
END mux2;
ARCHITECTURE dataflow OF mux2 IS
SIGNAL sig:BIT; --信号定义语句(内部信号,无方向)
BEGIN
Sig <= (d0 AND sel) OR (NOT sel AND d1);
S<=sig; --功能描述语句
END dataflow;
1.3 块、子程序和进程
1.3.1块语句(BLOCK)
在较大规模的电子系统设计中,传统的硬件电路设计通常包括一张系统总电路原理图和若干张子原理图。在VHDL程序设计中,结构体是由多个BLOCK块构成的,如果将结构体比做总电路原理图,那么,每个BLOCK块则相当于一张子原理图。
BLOCK块语句的结构:
块标号:BLOCK
接口说明
类属说明
BEGIN
并行块语句
END BLOCK(块标号);
例: B1: BLOCK
SIGNAL s1:BIT;
BEGIN
s1 <= a AND b;
B2: BLOCK
SIGNAL s2:BIT;
BEGIN
s2<= c AND d;
B3: BLOCK
BEGIN
Z <= s2;
END BLOCK B3;
END BLOCK B2;
y<= s1;
END BLOCK B1;
1.3.2 进程(PROCESS)
PROCESS结构是最能体现VHDL语言特色的语句。与BLOCK语句一样,利用PROCESS语句结构可以描述一个功能独立的电路。与BLOCK语句不同之处是,在系统仿真时,PROCESS结构中的语句是按顺序逐条向下执行的,而不像BLOCK语句那样并发执行。一个结构体中可以有多个并行运行的进程结构,每一个进程内部是由一系列顺序语句来构成的。
PROCESS语句的结构:
[进程标号] PROCESS [(敏感信号表)] [IS]
[进程说明语句]
BEGIN
顺序描述语句
END PROCESS [进程标号];
注意:在多个进程的结构体描述中,进程标号是区分各个进程的标志。但是进程标号并不是必需的。单进程以PROCESS开始,以END PROCESS结束。
例:两输入或非门
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY nor2_v2 IS
PORT(a,b: IN STD_LOGIC;
y: OUT STD_LOGIC);
END nor2_v2;
ARCHITECTURE behave OF nor2_v2 IS
BEGIN
PROCESS (a,b)
VARIABLE comb : STD_LOGIC_VECTOR(1 DOWNTO 0);
BEGIN
comb := a & b; --&组合符号
CASE comb IS
WHEN "00"=> y <='1';
WHEN "01"=> y <='0';
WHEN "10"=> y <='0';
WHEN "11"=> y <='0';
WHEN OTHERS => y <='X'; --‘X’不定
END CASE;
END PROCESS;
END behave;
1.3.3子程序(SUBPROGRAM)
VHDL程序与其他软件语言程序中应用子程序的目的是相似的,即能够更有效地完成重复性的工作。子程序模块是利用顺序语句定义和完成算法的,但子程序不能像进程那样可以从本结构体的其他块或进程结构中读取信号值或向信号赋值,只能通过子程序调用与子程序的界面端口进行通信。
子程序被调用时,首先要初始化,执行处理功能后,将处理结果传递给主程序。子程序内部的值不能保持,子程序返回后才能被再次调用并初始化。
子程序有两种类型:过程(PROCEDURE)和函数(FUNCTION)。
1.过程(PROCEDURE)
过程语句的书写格式为:
PROCEDURE 过程名(参数表)IS
[说明部分]
BEGIN
过程语句部分
END PROCEDURE 过程名;
例:用过程语句设计的子程序
PROCEDURE vector_to_int --矢量转换成整数
(a: IN STD_LOGIC_VECTOR;
x_flag: OUT BOOLEAN;
q: INOUT INTEGER) IS
BEGIN
q := 0;
x_flag := FALSE;
FOR i IN a’RANGE LOOP
q := q*2; --*: 乘, **:乘方
IF (a (i) =1) THEN
q := q+1;
ELSE (a (i) /=1) THEN -- /=:不等
x_flag := TRUE;
END IF;
END LOOP ;
END vector_to_int;
这个过程名为vector_to_int实现将位矢量转换成整数的功能,在过程语句执行结束后,将输入值拷贝到调用者的OUT和INOUT所定义的变量中,完成子程序和主程序之间的数据传递。
2.函数
函数的语言书写格式为:
FUNCTION 函数名 (参数表) RETURN 数据类型 IS
[说明部分];
BEGIN
顺序语句;
RETURN [返回变量名];
END RETURN 函数名;
例: 用VHDL构造的选择最大值的函数程序。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
PACKAGE bpac IS
FUNCTION max (a: STD_LOGIC_VECTOR;
b: STD_LOGIC_VECTOR)
RETURN STD_LOGIC_VECTOR;
END bpac;
PACKAGE BODY bpac IS
FUNCTION max (a: STD_LOGIC_VECTOR;
b: STD_LOGIC_VECTOR)
RETURN STD_LOGIC_VECTOR IS
VARIABLE tmp: STD_LOGIC_VECTOR (a’RANGE);
BEGIN
IF (a>b) THEN
tmp := a;
ELSE
tmp := b;
END IF;
RETURN tmp;
END;
END bpac;
1.4 库和程序包
库和程序包用来描述和保留元件、类型说明函数、子程序等,以便在其它设计中可以随时引用这些信息,提高设计效率。
1.4.1 库(LIBRARY)
库是经编译后的数据的集合,它存放包集合定义、实体定义、结构定义和配置定义。
库语句的格式为:
LIBRARY 库名;
USE语句指明库中的程序包。一旦说明了库和程序包,整个设计实体都可以进入访问或调用,但其作用范围仅限于所说明的设计实体。USE语句的使用将使所说明的程序包对本设计实体部分或全部开放。
USE语句有以下两种常用的格式:
USE 库名.程序包名.项目名;
USE 库名.程序包名.ALL;
第一种语句格式的作用是向本设计实体开放指定库中的特定程序包内的所选定的项目。
第二种语句格式的作用是向本设计实体开放指定库中的特定程序包内的所有内容。
例如:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_1164.STD_ULOGIC;
此例中,第一个USE语句表明打开IEEE库中的STD_LOGIC_1164程序包,并使程序包中的所有公共资源对本语句后面的VHDL设计实体程序全部开放,关键词ALL代表程序包中的所有资源。第二个USE语句开放了程序包STD_LOGIC_1164中的STD_ULOGIC数据类型。
STD_ULOGIC :可枚举数据类型
注意:库说明语句的作用范围从一个实体说明开始到它所属的结构体、配置为止,当一个源程序中出现两个以上实体时,两条作为使用库的说明语句应在每个设计实体说明语句前重复书写。
例:
LIBRARY IEEE; --库使用说明
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY and IS
┇
END and;
ARCHITECTURE dataflow OF and IS
┇
END dataflow;
CONFIGURATION c1 OF and IS -- CONFIGURATION(配置)
┇
AND c1;
LIBRARY IEEE; --库使用说明
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY or IS
CONFIGURATION c2 OF and IS
┇
AND c2;
1.4.2 程序包
程序包也叫包集合,主要用来存放各个设计都能共享的数据类型、子程序说明、属性说明和元件说明等部分。设计者使用时只要用USE子句进行说明即可。
程序包由两部分组成:程序包首和程序包体。
程序包的一般书写格式如下:
PACKAGE 程序包名 IS
END [PACKAGE] 程序包名; --程序包首
PACKAGE BODY 程序包名 IS
┇ --程序包体
END [PACKAGE BODY] [程序包名];
例:
USE STD.STD_LOGIC.ALL;
PACKAGE math IS
TYPE tw16 IS ARRAY(0 TO 15)OF T_WLOGIC;
FUNCTION add (a,b:IN tw16)RETURN tw16;
FUNCTION sub (a,b:IN tw16)RETURN tw16;
END math;
PACKAGE BODY math IS
FUNCTION vect_to_int(s:tw16);
RETURN INTEGER IS
VARIBLE result:INTEGER :=0;
BEGIN
FOR i IN 0 TO 7 LOOP
result := result*2;
IF s(i)=’1’THEN
result := result+1
END IF;
END LOOP ;
RETURN result;
END vect_to_int;
FUNCTION int_to_tw16(s:INTEGER);
RETURN tw16 IS
VARIBLE result: tw16;
VARIBLE digit: INTEGER:=2**15;
VARIBLE local: INTEGER;
BEGIN
local := s;
FOR i IN 15 DOWNTO 0 LOOP
IF local/ digit>=1 THEN
Local := local- digit;
ELSE
result (i) :=0;
END IF;
digit := digit/2;
END LOOP ;
RETURN result;
END int_to_tw16;
FUNCTION add(a,b:IN tw16);
RETURN tw16 IS
VARIBLE result: INTEGER;
BEGIN
result := vect_to_int (a)+ vect_to_int (b);
RETURN int_to_tw16(result);
END add;
FUNCTION sub(a,b:IN tw16);
RETURN tw16 IS
VARIBLE result: INTEGER;
BEGIN
result := vect_to_int (a)+ vect_to_int (b);
RETURN int_to_tw16(result);
END sub;
END math;
此例的程序包是由程序包首和程序包体两部分组成。程序包首定义了数据类型和函数的调用说明,程序包体中才具体描述实现该函数功能的语句和数据的赋值。这种分开描述的好处是,当函数的功能需要做某些调整或数据赋值需要变化时,只要改变程序包体的相关语句就可以了,而无需改变程序包首的说明,这样就使得需要重新编译的单元数目尽可能的减少了。
1.5 配置
在用VHDL描述硬件电路时,常常采用结构描述方式和混合描述方式。在这两种描述方式中,常常需要将其他设计实体作为元件进行引用,这时就需要将不同元件通过配置安装到不同的设计实体中。VHDL提供了配置语句用于描述各种设计实体和元件之间连接关系以及设计实体和结构体之间的连接关系。
1.5.1 默认配置
默认配置语句的基本格式为:
CONFIGURATION 配置名 OF 实体名 IS
FOR 选配结构体名
END FOR
END 配置名;
例:与、或、与非、或非、异或,5个结构体共用一个实体。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY example_v IS
PORT (a : IN STD_LOGIC;
b : IN STD_LOGIC;
y : OUT STD_LOGIC);
END example_v;
ARCHITECTURE and2_arc OF example_v IS
BEGIN
y <= a AND b;
END and2_arc;
ARCHITECTURE or2_arc OF example_v IS
BEGIN
y <= a OR b;
END or2_arc;
ARCHITECTURE nand2_arc OF example_v IS
BEGIN
y <= NOT(a AND b);
END nand2_arc;
ARCHITECTURE nor2_arc OF example_v IS
BEGIN
y <= NOT(a OR b);
END nor2_arc;
ARCHITECTURE xor2_arc OF example_v IS
BEGIN
y <= a XOR b;
END xor2_arc;
CONFIGURATION cfg1 OF example_v IS
FOR and2_arc
END FOR;
END cfg1;
CONFIGURATION cfg2 OF example_v IS
FOR or2_arc
END FOR;
END cfg2;
CONFIGURATION cfg3 OF example_v IS
FOR nand2_arc
END FOR;
END cfg3;
CONFIGURATION cfg4 OF example_v IS
FOR nor2_arc
END FOR;
END cfg4;
CONFIGURATION cfg5 OF example_v IS
FOR xor2_arc
END FOR;
END cfg5;
在上例( example_v)中,有5个不同的结构体,分别用来完成二输入的逻辑与、或、与非、或非和逻辑异或的运算操作。在程序中使用了5个默认配置语句来指明设计实体example_v和哪个结构体一起组成一个完整的设计:配置语句cfg1将与逻辑结构体配置给实体;cfg2将或逻辑结构体配置给实体;cfg3将与非逻辑结构体配置给实体;cfg4将或非逻辑结构体配置给实体;cfg5将异或逻辑结构体配置给实体。在进行模拟的时候,将根据所编译的是上面的哪个配置来决定要进行模拟的结构体,也就是说最后一个被编译的结构体(异或逻辑)将被模拟,下图就是异或逻辑的仿真波形。
异或门仿真波形
1.5.2 结构体的配置
结构体的配置主要是用来对结构体中引用的元件进行配置。
结构体的配置的书写格式:
FOR <元件例化标号>:<元件名>USE ENTITY <库名>.<实体名(结构体名)>;
以1位全加器的构成为例说明结构体的配置的用法:
将两输入与门、或门、异或门设置成通用例化元件由结构体引用。
--二输入与门源代码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY and2_v IS
PORT(a: IN STD_LOGIC;
b: IN STD_LOGIC;
y: OUT STD_LOGIC);
END and2_v;
ARCHITECTURE and2_arc OF and2_v IS
BEGIN
y <= a AND b;
END and2_arc;
CONFIGURATION and2_cfg OF and2_v IS
FOR and2_arc
END for;
END and2_cfg;
与门and2_v仿真波形
--二输入或门源代码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY or2_v IS
PORT(a: IN STD_LOGIC;
b: IN STD_LOGIC;
y: OUT STD_LOGIC);
END or2_v;
ARCHITECTURE or2_arc OF or2_v IS
BEGIN
y <= a OR b;
END or2_arc;
CONFIGURATION or2_cfg OF or2_v IS
FOR or2_arc
END for;
END or2_cfg;
或门or2_v仿真波形
--异或门源代码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY xor2_v IS
PORT(a: IN STD_LOGIC;
b: IN STD_LOGIC;
y: OUT STD_LOGIC);
END xor2_v;
ARCHITECTURE xor2_arc OF xor2_v IS
BEGIN
y <= a XOR b;
END xor2_arc;
CONFIGURATION xor2_cfg OF xor2_v IS
FOR xor2_arc
END for;
END xor2_cfg;
异或门xor2_v仿真波形
--全加器源代码:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY add1_v IS
PORT(A : IN STD_LOGIC;
B : IN STD_LOGIC;
Cin : IN STD_LOGIC;
Co : OUT STD_LOGIC;
S : OUT STD_LOGIC);
END add1_v;
ARCHITECTURE structure OF add1_v IS
COMPONENT and2_v
PORT(a : IN STD_LOGIC;
b : IN STD_LOGIC;
y : OUT STD_LOGIC);
END COMPONENT;
COMPONENT or2_v
PORT(a : IN STD_LOGIC;
b : IN STD_LOGIC;
y : OUT STD_LOGIC);
END COMPONENT;
COMPONENT xor2_v
PORT(a : IN STD_LOGIC;
b : IN STD_LOGIC;
y : OUT STD_LOGIC);
END COMPONENT;
SIGNAL tmp1,tmp2,tmp3 : STD_LOGIC;
FOR U1,U2 : xor2_v USE ENTITY work.xor2_v( xor2_arc);
FOR U3,U4 : and2_v USE ENTITY work.and2_v( and2_arc);
FOR U5 : or2_v USE ENTITY work.or2_v( or2_arc);
全加器add1_v仿真波形
实际上如果仅仅要构成1位全加器,采用行为描述方式只需几条逻辑语句即可。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
ENTITY add1_v IS
PORT(A : IN STD_LOGIC;
B : IN STD_LOGIC;
Cin : IN STD_LOGIC;
Co : OUT STD_LOGIC;
S : OUT STD_LOGIC);
END add1_v;
ARCHITECTURE structure OF add1_v IS
BEGIN
S <= A XOR B XOR Cin;
Co <= (A XOR B) AND Cin OR (A AND B);
END structure;
全加器add1_v仿真波形
这篇关于第一章 VHDL基本结构的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!