赵工的个人空间


专业技术部分转网页计算转业余爱好部分


 基础资料

首页 > 专业技术 > 基础资料 > 硬件描述语言VHDL
硬件描述语言VHDL
  1. 概述
  2. VHDL程序结构
  3. VHDL语言的描述风格
  4. VHDL语言的设计资源共享
  5. VHDL语言的文字规则
  6. VHDL语言的数据对象、类型和属性
  7. VHDL语言的操作符
  8. VHDL语言的顺序描述语句
  9. VHDL语言的并发描述语句
  10. VHDL的元件声明及例化语句
  11. VHDL的文件操作

1. 概述:

硬件描述语言HDL(Hardware Description Language)是硬件设计人员和EDA工具之间的界面,主要用来编写设计文件,建立电子系统形为级的仿真模型,即利用计算机的强大能力对VHDL或Verilog HDL建模的复杂逻辑进行仿真,然后再自动综合,生成符合要求且在电路结构上可以实现的数字逻辑网表Netlist,根据网表和某种工艺的器件自动生成具体电路,最后生成该工艺条件下这种具体电路的时延模型。仿真验证无误后,该模型即可用于制造ASIC芯片或写入CPLD和FPGA器件中。
美国国防部电子系统项目有众多的承包公司,由于各公司的技术路线不一致,许多产品不兼容,各家公司使用各自的HDL语言,造成信息交换和维护困难。为了降低开发费用,避免重复设计,美国国防部为他们的超高速集成电路提供了一种硬件描述语言,即VHDL,其功能强大、严格、可读性好,政府要求各公司的合同都用它来描述,以避免产生歧义。
EDA技术领域,把用HDL语言建立的数字模型称为软核(Soft Core),把用HDL语言建模和综合后生成的网表称为固核(Hard Core),对这些模块的重复利用可以缩短开发时间,提高产品开发率,提高设计效率。
到20世纪90年代末,芯片的集成密度已达到一千万个晶体管以上,为使如此复杂的芯片易于被人理解,用一种高级语言来表达其功能性而隐藏具体实现的细节很有必要,工程人员不得不使用HDL语言进行设计,而把具体实现留给逻辑综合工具去完成。面对激烈的市场竞争,芯片及电子产品设计需要提高逻辑设计的效率,降低设计成本,缩短设计周期。多方位的仿真可以在设计完成之前检测到错误,这样能够减少重复设计的次数,有效的HDL语言和计算机仿真系统起到了将设计错误的数目减少到最低限的作用,并使第一次设计便能成功实现芯片功能成为可能。
HDL语言既包含一些高层程序设计的结构形式,同时也兼顾描述硬件线路连接的具体构件。HDL语言是并发的,即具有在同一时刻执行多任务的能力,并有时序概念。通过使用结构级或形为级描述,可以在不同的抽象层次进行描述设计自顶向下主要包括3个领域的5个抽象层次:

行为领域 结构领域 物理领域
系统级 性能描述 部件及它们之间的逻辑连接方式 芯片、模块、电路板和物理划分的子系统
算法级 I/O应答算法级 硬件模块数据结构 部件之间的物理连接、电路板、底盘等
寄存器传输级 并行操作寄存器传输、状态表 算术运算部件、多路选择器、寄存器总线、微定序器之间的物理连接方式 芯片、宏单元
逻辑级 用布尔方程描述 门电路、触发器、锁存器 标准单元布图
电路级 微分方程表述 晶体管、电阻、电容、电感元件 晶体管布图
VHDL和Verilog HDL是目前最常用的HDL语言,也都是IEEE标准化的HDL语言,VHDL偏重于标准化考虑,而Verilog HDL则和EDA工具结合得更为紧密,VHDL更适合特大型系统级设计,而Verilog HDL在系统抽象方面更强一些,适合算法级、寄存器传输级、逻辑级以及门级的设计。

2. VHDL程序结构:

一个完整的VHDL程序包括实体entity、结构体architecture、配置configuration、包package、库library等5个部分。实体只要用于描述外部设备的接口信号;结构体用于描述系统的具体逻辑行为功能;包集合包含要使用到的公共的数据类型、常数和子程序等;配置用来从库中选择所需单元来组成系统设计的不同版本;库用于存放已经编译的实体、结构体、包集合和配置等。
VHDL的基本结构是由实体和结构体两部分组成,设计实体是VHDL程序的基本单元,是电子系统的抽象。根据所设计的数字系统复杂度不同,其程序规模也大不相同。

1) VHDL实体:

实体说明由类属性和端口说明两部分组成。根据IEEE标准,实体的一般格式为:
  entity <entity_name> is
  generic( --
     <generic_name>:<type>:=<value>;
     <other generics> ...
  );
  port(
     <port_name>:<mode> <type>;
     <other ports> ...
  );
  end <entity_name>;

实体描述在VHDL程序设计中描述一个元件或一个模块与设计系统的其余部分之间的连接关系,可以看作一个电路图符号。
①类属说明:
类属说明是实体说明中的可选项,放在端口说明之前,用于指定参数,其一般书写格式为:
  generic( --
    <generic_name>:<type>:=<value>;
    <other generics> ...
  );

类属说明常用来定义实体端口的大小、设计实体的物理特性、总线宽度、元件例化的数量等。
②端口说明:
实体的一组端口定义称作端口说明。端口说明是对设计实体与外部接口的描述,是设计实体和外部环境动态通信的通道,其功能对应于电路图符号的引脚。实体说明中的每一个I/O信号被称为端口,一个端口就是一个数据对象。端口可以被赋值,也可以当作变量用在逻辑表达式中。
端口说明结构必须有端口名、端口方向和数据类型,一般格式为:
  port(
    <port_name>:<mode> <type>;
    <other ports> ...
  );

端口名:
端口名是赋予每个外部引脚的名称,名称的含义要明确,如D开头的端口名表示数据,A开头的端口名表示地址等。端口名通常用几个英文字母或一个英文字母加数字表示,如CLK、RESET、A0、D3等。
模式:
模式用来说明数据、信号通过该端口的传输方向。端口模式有in(输入)、out(输出)、buffer(缓冲)、inout(双向)。
输入模式下,输入仅允许数据流入端口。输入信号的驱动源由外部向该设计实体内进行。输入模式主要用于时钟输入、控制输入(如Load、Reset、Enable、CLK)和单向的数据输入(如地址信号address)。
输出模式下,输出仅允许数据流从实体内部输出,端口的驱动源是由被设计的实体内部进行的。输出模式不能用于设计实体的内部反馈,因为输出端口在实体内部不能看作可读的。输出模式常用于计数输出、单向数据输出、设计实体产生的控制其他实体的信号输出等。
缓冲模式下,端口与输出模式的端口类似,只是缓冲模式允许内部引用该端口的信号。缓冲端口既能用于输出,也能用于反馈。缓冲端口的驱动源可以是设计实体的内部信号源或其他实体的缓冲端口。缓冲不允许多重驱动,不与其他实体的双向端口和输出端口相连。
vhdl模式
内部反馈的实现方法由建立缓冲模式端口和建立设计实体的内部节点,如上图所示。缓冲模式用于在实体内部建立一个可读的输出端口,例如计数器输出,计数器的现态被用来决定计数器的次态。实体既需要输出,又需要反馈,这时设计端口模式应为缓冲模式。
双向模式可以代替输入模式、输出模式和缓冲模式。在设计实体的数据流中,有些数据是双向的,数据可以流入该设计实体,也有数据从设计实体流出,这时需要将端口模式设计为双向端口。
双向模式的端口允许引入内部反馈,所以双向模式还可以作为缓冲模式用,可见双向端口是一个完备的端口模式。常见的SRAM和SDRAM芯片的数据端口就是双向端口。
数据类型:
端口说明除了要定义端口标识名称、端口模式外,还要说明出入端口的数据类型。VHDL语言标准规定,EDA综合工具支持的数据类型为布尔型boolean、位型bit、位矢量型bit-vector和整数型integer。为了使EDA工具的仿真、综合软件能够处理这些逻辑类型,这些标准库必须在实体中声明或在USE语句中调用。
8位计数器实体示例:
  entity counter is
  generic( byte: integer:=8); --
  port(
     clk : in std_logic;
     rst : in std_logic;
     counter : out std_logic_vector(byte-1 downto 0);
  );
  end counter;

上面的8位计数器实体中声明了一个byte的类属名,该类属表示8比特位。在counter端口的类型说明中,直接使用在该实体中所定义的byte类属名,很多情况下使用类属名是为了方便修改程序。在实体端口说明中,说明了clk、rst、counter三个端口,其中clk、rst均为输入端口,而counter为输出端口。

2) VHDL程序结构体:

结构体具体指明了该设计的行为,定义了该设计实体的逻辑功能和行为,规定了该设计实体的内部模块及其内部模块连接关系。VHDL对结构体的描述通常有行为描述、寄存器传输描述和结构描述3种。
由于结构体是对具体功能的描述,所以结构体一定在实体后面。一个VHDL程序结构体的描述为:
  architecture <arch_name> of <entity_name> is
     -- declarative_items(signal declarations,component declarations,etc.)
  begin
     -- architecture body
  end <arch_name>;

其中,arch_name为结构体名字;entity_name为实体的名字。
结构体中begin开始的前面部分为声明项declarative_items,通常是对设计内部的信号或者元件进行声明;而begin后面一直到结构体的结束部分是对实体行为和功能的具体描述,该部分的描述是由顺序语句和并发语句完成的。
①结构体命名:
结构体的名称由设计者自由命名,是结构体的唯一名称。有些设计实体中可能含有多个结构体,OF后面的实体名称部分声明该结构体属于哪个设计实体。这些结构体的命名可以反映结构体的特色,从名字就能让人一目了然。示例:
  ARCHITECTURE rtl OF mux IS      用结构体的寄存器传输结构命名
  ARCHITECTURE dataflow OF mux IS      用结构体的数据流命名
  ARCHITECTURE structural OF mux IS      用结构体的组织结构命名
  ARCHITECTURE behave OF mux IS      用结构体的行为描述方式命名
上述几个结构体都属于设计实体mux,每个结构体有着不同的名称,使得阅读VHDL程序的人能直接从结构体描述方式了解功能,方便定义电路行为。
②结构体内信号定义:
由结构体的书写格式可以知道,关键字ARCHITECTURE和BEGIN之间的部分用于对结构体内部使用的信号、常数、数据类型、函数进行定义。这些声明用于结构体内部,而不是用于实体内部,因为实体中可能有几个结构体相对应。另外,实体说明中定义I/O信号为外部信号,而结构体定义的信号为内部信号。
结构体的信号定义和实体端口说明一样,应有信号名称和数据类型定义,但不需要定义信号模式,不需要说明信号方向,因为这些结构体的内部信号是用来描述结构体内部连接关系。示例:
  ARCHITECTURE structural OF mux IS
     signal a,b: std_logic;
     signal x: std_logic_vector(0 to 7);
     signal y: integer 0 to 255;
  BEGIN
     ......
  END structural;

③结构体并行处理语句:
并行处理语句是结构体描述的主要语句,在begin和end之间。并行处理语句表明,若一个结构体的描述用的是结构描述方式,则并行语句表达了结构体的内部元件之间的互连关系。这些语句是并行的,各个语句之间没有顺序关系。
若一个结构体是用进程语句来描述,并且这个结构体含有多个进程,则各进程之间是并行的。但每个进程内部的语句是有顺序的,不是并行的。
若一个结构体使用模块化结构描述,则各模块之间是并行的,而模块内部视描述方式而定。示例:
  LIBRARY IEEE;
  USE IEEE.STD_LOGIC_1164.ALL;
  ENTITY mux4 IS
     PORT(a: in std_logic_vector(3 downto 0);
       sel: in std_logic_vector(1 downto 0);
       q: out std_logic);
  END mux4;
  ARCHITECTURE rtl OF mux4 IS
  BEGIN
     q<=a(0) when sel="00" else
     a(1) when sel="01" else
     a(2) when sel="10" else
     a(3) when sel="11" else
     'X'
  END rtl;

其中使用了条件代入语句,描述了一个4选1的逻辑单元,该条件信号代入语句是并发描述语句。

3. VHDL语言的描述风格:

VHDL语言主要有行为描述、数据流(RTL寄存器传输)描述和结构描述3种描述风格,从不同角度对硬件系统进行描述。一般情况下,行为描述用于模型仿真和功能仿真阶段,而RTL描述和结构描述可以进行逻辑综合阶段。

1) 行为描述:

行为描述是以算法形式对系统模块、功能的描述,与硬件结构无关,抽象程度最高。行为描述中常用的语句主要有进程、过程和函数。示例:
  ENTITY and2 IS
     PORT(a,b: in std_logic;
       c: out std_logic);
  END and2;
  ARCHITECTURE behav of or2 is
  BEGIN
     c<=a or b AFTER 5 ns;
  END behav

2) 数据流描述:

数据流描述又称为寄存器传输级RTL描述。RTL描述以寄存器为特征,在寄存器之间插入组合逻辑电路,即以描述数据流的流向为特征。如下图。
vhdl数据流描述
示例:4选1选择器的数据流描述
  LIBRARY IEEE;
  USE IEEE.STD_LOGIC_1164.ALL;
  USE IEEE.STD_LOGIC_UNSIGNED.ALL;
  ENTITY mux4 IS
     PORT(x: in std_logic_vector(3 downto 0);
       sel: in std_logic_vector(1 downto 0);
       y: out std_logic);
  END mux4;
  ARCHITECTURE rtl OF mux4 IS
  BEGIN
     y<=x(0) when sel="00" else
     x(1) when sel="01" else
     x(2) when sel="10" else
     x(3);
  END rtl;

这种基于RTL级的描述,虽然具体了一些,但仍没有反映出实体内部的具体结构。

3) 结构描述:

在多层次的设计中,高层次的设计模块调用低层次的设计模块,构成模块化的设计。例如,全加器即由两个半加器和一个或门构成,元件之间、元件与实体端口之间通过信号连接,如下图。
vhdl结构描述
  Architecture structure_view of Full_adder is
     Component half_adder
       port(a,b: in std_logic; s,c: out std_logic);
     end compent;
     Component or_gate
       port(a,b: in std_logic; s,c: out std_logic);
     end compent;
     signal a,b,c: std_logic;
  begin
     Inst_half_adder1: port map(x,y,a,b);
     Inst_half_adder2: port map(a,cin,sum,c);
     Inst_or_gate: port map(b,c,cout);
  end structure_view;

结构层次化编码是模块化设计思想的一种体现。目前大型设计中必须采用结构层次化编码风格,以提高代码可读性,易于分工协作,易于设计仿真测试激励。最基本的结构层次由一个顶层模块和若干个子模块构成,每个子模块根据需要还可以包含自己的子模块。
在进行层次化设计过程中,要遵循如下原则:
  ·  结构层次不易太深,一般3~5层即可。
  ·  顶层模块最好仅仅包含对所有模块的组织和调用,而不应完成比较复杂的逻辑功能。
  ·  所有I/O信号的描述在顶层模块完成。
  ·  子模块之间也可以有接口,但最好不用建立子模块间跨层次的接口。
  ·  子模块的合理划分非常重要。

4. VHDL语言的设计资源共享:

除实体和结构外,包集合、库及配置是VHDL语言的另外3个可以各自独立进行编译的源设计单元。通过库、包和配置,可以实现设计资源的共享。

1) 库:

一个库中,可以存放集合定义、实体定义、结构体定义和配置定义。当需要引用一个库时,首先需要对库名进行说明,格式为:
  LIBRARY <library_name>
其中, <library_name>为库的名字,这时就可以使用库中已经编译好的设计。
对库中包集合的访问必须再经USE语句才能打开,格式为:
  USE <package_name>
其中, <package_name>为包集合的名字。
①库的种类:
当前VHDL语言中的库大致可以分为IEEE库、STD库(默认库)、ASIC矢量库、用户定义库和WORK库5种。
IEEE库:
定义了如下4个常用的程序包:
  std_logic_1164(std_logic types & related functions)
  std_logic_arith(arithmetic functions)
  std_logic_sighed(signed arithmetic functions)
  std_logic_unsighed(unsighed arithmetic functions)

STD库:
STD库是VHDL语言的标准库,存放了STANDARD包集合,如果调用STANDARD包集合内的数据,可以不进行标准格式的说明。STANDARD包集合中定义的最基本数据类型包括bit、bit_vector、boolean、integer、real、time等。
STD库中还包含TEXTIO包集合,在使用这部分包集合时,必须说明库和包集合名,然后才能使用该包集合中的数据,格式为:
  LIBRARY STD
  USE STD.TEXTIO.ALL

ASIC矢量库:
在VHDL程序中,为了门级仿真的要求,各公司提供了面向ASIC的逻辑门库,该库中存放着与逻辑门一一对应的实体。若要使用它,必须对库说明。
WORK库:
WORK库是存放设计数据的库,设计所描述的VHDL语句并不需要说明,将其存放到WORK库中。在使用WORK库时不需要说明。
用户定义库:
用户定义库是设计人员根据设计的需要所开发的包集合和实体等,可以汇集在一起定义成一个库。在使用该类库时,必须说明库名称,然后才能调用包集合内的数据等。
②库的使用:
库的说明:
除了WORK库和STD标准库外,其他库在使用前都需要进行说明,格式为:
  library <LIB_NAME>
其中, LIB_NAME为所需要调用的库的名字。
库的调用:
设计人员还需要指明使用库中哪个包集合以及要使用包集合中的项目名(过程名、函数名等),格式为:
  USE <LIB_NAME>.<PACKAGE_NAME>.ALL
其中,LIB_NAME为所需要调用的库的名字,PACKAGE_NAME为所需要调用的包集合的名字。
库说明语句的作用范围:
库说明语句的作用范围从一个实体说明开始,到所属的结构体、配置为止,当一个文件中出现两个以上的实体时,两条作为使用库的说明语句应在每个实体说明语句前重复书写。

2) 包集合:

包集合说明像C语言中的include语句一样,用来单纯地罗列VHDL语言中所要用到的信号定义、常数定义、数据类型、元件语句、函数定义和过程定义等。使用包集合时,要用USE语句说明,如"USE IEEE.STD_logic_1164.ALL;"。包集合的说明包括常量说明、VHDL数据类型说明、元件说明及子程序说明,程序包的结构包括包集合说明(包首)和包集合主体(包体)。
①包集合说明:
包集合的说明语句格式为:
  package <Package_Name> is
     <package declaration>
  end <Package_Name>;

其中,Package_Name为包集合的名字,package declaration为包集合的具体声明部分。示例:
  package example is
     type <new_type> is
       record
         <type_name>: std_logic_vector(7 downto 0);
         <type_name>: std_logic;
       end record;
  --Declare constants
     constant <constant_name> : time:=<time_unit> ns;
     constant <constant_name> : integer:=<value>;
  --Declare function and procedure
     function <function_name> (signal <signal_name> : in<type_declaration>) return;
  <type_declaration>;
     precedure <precedure_name> (<type_declaration> <constant_name> : in <type_declaration>);
  end example;

可以看出,包集合的说明部分包括记录record类型、常数constant类型、函数function和子程序procedure几个部分。
②包集合主体:
包集合的内容包括子程序的实现算法。包集合主体的语句格式为:
  package body <Package_Name> is
     <package_body declaration>
  end <Package_Name>;

其中,Package_Name为包的名字,package_body declaration为主体的具体说明部分。
包集合主体说明项可含use语句、子程序说明、子程序主体、类型说明、子类型说明以及常量说明。
包集合主体并非必须,只有在程序包中要说明子程序时才是必须的。包集合说明可以独立定义和使用。
包集合示例:
  package body example is
     function <function_name> (signal <signal_name> :in <type_declaration>) return
   is
     variable <variable_name> : <type_declaration>;
     begin
       <variable_name> := <signal_name> xor <signal_name>;
       return <variable_name>;
     end <function_name>;
     function <function_name> (signal <signal_name> :in <type_declaration>;
           signal <signal_name> :in <type_declaration>) return
  <type_declaration> is
     begin
       if(<signal_name>='1') then
         return <signal_name>;
       else
         return 'Z';
       end if;
     end <function_name>;
  --Procedure Example
     procedure <procedure_name> (<type_declaration> <constant_name> : in
       <type_declaration>) is
     begin
     end <procedure_name>;
  end example;

该包集合主体是对包集合说明部分中的函数和子程序的具体说明。

3) 子程序和函数:

子程序和函数是VHDL语言中一种重要的代码共享方式,通过使用子程序和函数可以大大减少代码的书写量。
①函数:
函数说明:
  function <FUNC_NAME> (<comma_separated_inputs>:<type>;
     <comma_separated_inputs>:<type>) return <type>

其中,FUNC_NAME为函数名称;括号里为输入变量的声明,包括对变量类型type的说明,在声明部分还要声明return后面变量的返回类型。
函数的实现:
  function <FUNC_NAME> (<comma_separated_inputs>:<type>;
         <comma_separated_inputs>:<type>) return <type> is
     --subprogram_declarative_items(constant declarations,
         variable declarations,etc)
  begin
     --function body
  end <FUNC_NAME>;

其中,在return <type> is之后和begin之前的部分,是对函数内部使用的一些常数和变量等的声明;在begin后到end之间是函数体部分,是函数具体逻辑行为 方式的表示。
return用于函数时,并且必须返回一个值,该值的类型必须和声明的返回类型一致。示例:
  function lut1 (a: std_logic_vector) return std_logic_vector;
  function lut1 (a: std_logic_vector) return std_logic_vector is
     variable length1: std_logic_vector(2 downto 0)
  begin
     if(a="11111110") then length1:="000";
     elsif(a="11111101") then length1:="001";
     elsif(a="11111011") then length1:="010";
     elsif(a="11110111") then length1:="011";
     elsif(a="11101111") then length1:="100";
     elsif(a="11011111") then length1:="101";
     elsif(a="10111111") then length1:="110";
     elsif(a="01111111") then length1:="111";
     endif;
    return length1;
  end lut1;

②子程序:
子程序说明部分:
  procedure <PROC_NAME> (<comma_separated_inputs>:<type>;
       <comma_separated_inputs>:out <type>);

其中,PROC_NAME为子程序名;括号里为对输入变量和输出变量的声明,包括对变量输入in/输出out和变量类型的说明。
子程序的实现部分:
  procedure <PROC_NAME> (<comma_separated_inputs>:<type>;
         <comma_separated_inputs>:out <type>) is
     --subprogram_declarative_items(constant declarations,
         variable declarations,etc.)
  begin
     --procedure body
  end <PROC_NAME>;

其中,在() is之后和begin之前的部分是子程序内部使用的一些常数和变量的声明;在begin后到end之间的部分是子程序体部分,是子程序具体逻辑行为方式的表示。
return用于子程序时,只是结束子程序,不返回任何值。示例:
  package PKG is
     procedure ADD (A,B,CIN: in BIT;
           C: out BIT_VECTOR(1 downto 0));
  end PKG;
  package body PKG is
     procedure ADD (A,B,CIN: in BIT;
           C: out BIT_VECTOR(1 downto 0)) is
       variable S,COUT: BIT
     begin
       S:=A xor B xor CIN;
       COUT:= (A and B) or (A and CIN) or (B and CIN);
       C:= COUT & S;
     end ADD;
  end PKG;

4) 元件配置:

元件配置就是从某个实体的多种结构体描述中选择特定的一个。配置语句描述层与层之间以及实体与结构之间的连接关系。设计者可以利用这种配置语句来选择不同的结构体,使其与要设计的实体相对应。在进行高级仿真时经常会使用元件配置语句。配置语句格式:
  configuration <configuration_identifier> of <entity_name> is
     for <architecture_name>
     <component_configuration>
  end <configuration_identifier>;

其中,configuration_identifier为配置名,entity_name为配置所使用的实体名;architecture _name为配置所使用的结构体名,component_configuration为元件的配置。示例:
  library ieee;
     use ieee.std_logic_1164.all;
     entity nand is
       port(a: in std_logic;
         b: in std_logic;
         c: out std_logic);
     end entity nand;
     architecture art1 of nand is
     begin
       c<=not (a and b);
     end architecture art1;
     architecture art2 of nand is
     begin
       c<='1' when (a ='0') and (b ='0') else
         '1' when (a ='0') and (b ='1') else
         '1' when (a ='1') and (b ='0') else
         '0' when (a ='1') and (b ='1') else
         '0';
     end architecture art2;
  configuration first of nand is
       for art1;
       end for;
  end first;
  configuration second of nand is
       for art2;
       end for;
  end second;

5. VHDL语言的文字规则:

1) 数字型文字:

①整数Integer:
整数类型的数代表正整数、负整数和零,表示的范围为-(231-1)~(231-1),它与算术整数相似,可进行+、-、*、/等算术运算,但不能用于逻辑运算。
  示例:5, 768, 156E2(=15600), 45_234_287(=45234287)
②实数Real:
实数类型也类似于数学上的实数,或称浮点数,表示范围为-1.0E38~1.0E38。
  示例:23.34, 2.0, 44.96E-2(0.4496), 8_867_551.23_909(=8867551.23909)
③以数制基数表示的文字格式:
  示例:10#170#(=170), 2#1111_1110#(=254), 16#E0#(=2#1110_0000#=224)
④位矢量Bit_Vector:
位矢量是用引号括起来的一组位数据,使用位矢量必须注明位宽。
  示例:B"1_1101_1110" ----二进制数数组,长度为9
      O"34" ----八进制数数组,长度为6
      X"1AB" ----十六进制数数组,长度为12
⑤IEEE预定义标准逻辑位与矢量:
在IEEE库的STD_LOGIC1164包集合中定义了两个重要的数据类型,即标准逻辑位STD_LOGIC和标准逻辑矢量STD_LOGIC_VECTOR,使得STD_LOGIC数据可以具有如下所述9种不同的值。
  ·  "U"----初始值
  ·  "0"----0
  ·  "Z"----高阻
  ·  "L"----弱信号0
  ·  "X"----不定
  ·  "1"----1
  ·  "W"----弱信号不定
  ·  "H"----弱信号1
  ·  "_"----不可能情况
在使用该类型数据时,程序中必须写出库说明语句和使用包集合的说明语句。

2) 字符型文字:

①字符character:
字符也是一种数据类型,字符类型通常用单引号引起来,如"A"。字符类型区分大小写。
②字符串string:
字符串是由引号括起来的一个字符序列,也称字符矢量或字符串数组。字符串常用于程序的提示和说明,如"STRING"等。
③时间time:
时间是一个物理数据。完整的时间类型包括整数和单位两部分,整数与单位之间至少留一个空格,如55 ms、2 ns。在包集合STANDARD中给出了时间的预定义,其单位为fs、ps、ns、us、ms、sec、min、hr。
在系统仿真时,时间数据很有用,可用它表示信号延时,从而使模型系统能更逼近实际系统的运行环境。
④错误等级severity level:
在VHDL仿真器中,错误等级用来指示设计系统的工作状态,有NOTE(注意)、WARNING(警告)、ERROR(出错)和FAILURE(失败)4种。在仿真过程中,可输出这4种状态,以提示系统当前的工作状态。

3) 标识符:

①使用规则:
VHDL语言中,标识符可以是常数、变量、信号、端口、子程序或参数的名字。使用标识符要遵守如下规则:
  ·  标识符由字母、数字和下划线字符组成
  ·  任何标识符必须以英文字母开头
  ·  末字符不能为下划线
  ·  不允许出现两个连续的下划线
  ·  标识符中字母不区分大小写
  ·  VHDL定义的保留字不能用作标识符
  ·  VHDL中的注释由两个连续的短线开始,直到行尾
②扩展标识符:
扩展标识符是以反斜线来界定,93标准为:
  ·  可以以数字打头
  ·  允许包含图形符号
  ·  允许使用VHDL保留字
  ·  区分字母大小写
  示例:\74LS163\、\Sig_#N\、\entity\、\ENTITY\
在AHDL中,标识符要区分大小写,但在VHDL语言中不区分大小写。一般写程序时,关键字用大写,自己定义的标识符用小写。

4) 下标名及下标段名:

下标名为用于指示数组型变量或信号的某一个元素;下标段名为用于指示数组型变量或信号的某一段元素。示例:
  a: std_logic_vector(7 downto 0);
  a(7),a(6)...a(0);
  a(7 downto 4),a(5 downto 3)...

6. VHDL语言的数据对象、类型和属性:

1) 数据对象:

VHDL语言中,标识符表示的几种数据对象包括以下几种。
①常量constant:
常量是一个固定的值,主要是为了使设计实体中的常量更容易阅读和修改而设置。常量一经赋值就不能再改变,常量所赋的值应与定义的数据类型一致。常量声明一般格式:
  CONSTANT 常数名 : 数据类型 := 表达式;
例如设计实体的电源电压指定常量:
  CONSTANT Vcc : REAL := 5.0;
常量的使用范围取决于它被定义的位置。包集合中定义的常量具有最大的全局化特性,可以用在调用此包集合的所有设计实体中;设计实体中某一结构体定义的常量只能用于此结构体结构体中某一单元定义的常量,如在一个进程中定义的常量,就只能用在这一进程中。
②变量variable:
变量是一个局部变量,它只能在进程语句、函数语句和进程语句结构中使用,用作局部数据存储。在仿真过程中,它不像信号那样到了规定的仿真时间才进行赋值,变量的赋值是立即生效的,变量常用在实现某种算法的赋值语句中。变量声明的一般格式为:
  VARIABLE 变量名 : 数据类型 约束条件 := 表达式;
示例:
  VARIABLE x,y : integer; --定义整型变量
  VARIABLE count : integer range0 to255 := 10; --定义计数变量范围

变量的适用范围仅限于定义了变量的进程或子程序中。若将变量用于进程之外,必须将该值赋给一个相同类型的信号,即进程之间传递数据靠的是信号,变量不能用于硬件连线和存储元件。变量赋值语法格式为:
  目标变量 := 表达式;
变量赋值符号是“:=”,赋值语句右方必须是一个与目标变量有相同数据类型的数值。
③信号signal:
信号是描述硬件系统的基本数据对象,它类似于连接线,除了没有数据流动方向说明之外,其他性质与实体端口Port概念一致。变量的值可以传递给信号,而信号的值不能传递给变量。信号通常在结构体、包集合和实体中说明。信号说明的格式:
  SIGNAL 信号名 : 数据类型;
信号的初始值设置不是必须的,而且初始值进在VHDL的行为仿真中有效。信号是电子系统内部硬件连接和硬件特性的抽象表示,用来描述硬件系统的基本特性。信号赋值语法格式为:
  目标信号 <= 表达式;
信号除了没有方向的概念以外,几乎与端口概念一致。端口是一种有方向的信号,即输出端口不能读出数据,只能写入数据;输入端口不能写入数据,只能读出数据。信号本身无方向,可读可写。
信号是一个全局量,可以用来进行进程之间的通信。信号赋值可以有时间延迟,除了当前信息外还要历史信息等相关值,进程对信号敏感。可以是多个进程的全局变量,可以看作硬件的一根连线。

2) 数据类型:

VHDL是一种强数据类型语言,要求设计实体中的每一个常数、信号、变量、函数以及设定的各种参量都必须具有确定的数据类型,并且只有相同数据类型的量才能相互传递和作用。
VHDL数据类型分为变量类型SCALAR、复合类型COMPOSITE、存取类型ACCESS、文件类型FILES。
①VHDL中的预定义数据类型:
布尔量Boolean:
布尔量具有false和true两种状态,常用于逻辑函数,如相等、比较等中作为逻辑比较。如,bit值转化成boolean值的格式为:
  boolean_var:=(bit_var='1');
位bit:
Bit表示一位的信号值,放在单引号中,如'0'或'1'。
位矢量bit_vector:
bit_vector是双引号括起来的一组位数据,如"001100"、X"00B10B"。
STD_LOGIC:
如,'U','X','0','1','Z','W','L','H','-'。
STD_LOGIC_VECTOR:
即Natuaral Range of STD_LOGIC。
字符character:
即用单引号将字符括起来,
  variable character_var : character;
  ......
  character_var := 'A';

整数integer:
表示所有正的和负的整数。硬件实现时,需利用32位的位矢量来表示。可实现的整数范围:-(231-1)~(231-1)
VHDL综合器要求对具体的整数作出范围限定,否则无法综合成硬件电路。如:
  signal s : integer 0 to 15;
表示信号s的取值范围是0~15,可用4位二进制数表示,因此s将被综合成由4条信号线构成的信号。
自然数natural和正整数positive:
natural是integer的子集,表示非负整数;positive是integer的子类型,表示正整数。定义如下:
  subtype natural is integer range 0 to integer'high;
  subtype positive is integer range 1 to integer'high;

实数或称浮点数real:
取值范围为-1.0E38~1.0E38。实数类型仅能用于VHDL仿真,一般综合器不支持。
字符串string:
string是character类型的一个非限定数组,需用双引号将一串字符括起来。如:
  variable string_var : string(1 to 7);
  ......
  string_var := "Rosebud";

时间time:
由整数和物理单位组成,如:55 ns,20 ms。
错误等级severity level:
仿真中用来指示系统的工作状态,共有NOTE(注意)、WARNING(警告)、ERROR(出错)、FAILURE(失败)4种。
②标准逻辑位与矢量:
STD_LOGIC:
由IEEE库中的STD_LOGIC_1164包集合定义,为9个值( 'U','X','0','1','Z','W','L','H','-')逻辑系统,'U'表示未初始化,'X'表示强未知的,'0'表示强0,'1'表示强1,'Z'表示高阻,'W'表示弱未知的,'L'表示弱0,'H'表示弱1,'-'表示忽略。
由STD_LOGIC类型代替bit类型,可以完成电子系统的精确模拟,并可实现常见的三态总线电路。
STD_LOGIC_VECTOR:
即由STD_LOGIC构成的数组,定义为:
  type std_logic_vector is array(natural range <>) of std_logic;
赋值的原则为相同宽度、相同数据类型。
③用户自定义类型:
可由用户定义的数据类型包括枚举类型、整数和实数类型、数组类型、记录类型以及子类型。
类型type定义语句:
  ·  整数类型描述:
  type <type_name> is array integer range <lower_limit> to <upper_limit>;
其中,type_name为类型名,lower_limit为整数下限,upper_limit为整数上限。示例:
  type my_integer is integer range 0 to 9;
  ·  枚举类型描述:
  type <type_name> is ( <string1>, <string2>, ...);
其中,string为字符串的名字。示例:
  type std_logic is ( 'U','X','0','1','Z','W','L','H','-');
  type color is ( blue,green,yellow,red);

枚举类型的编码方法:综合器自动实现枚举类型元素的编码,一般将第一个枚举量编码为0,以后依次加1。编码用位矢量表示,位矢量的长度将取所需表达的所有枚举元素的最小值,其中一种编码为“blue="00";green="01";yellow="10";red="11";”。
  ·  通用类型描述:
  type <type_name> is type <type_definition>;
其中,type_definition为类型定义。示例:
  type byte is array(7 downto 0) of bit;
  variable addend: byte
  type week is (sun,mon,tue,wed,thu,fri,sat);
  type byte is array(7 downto 0) of bit;
  type vector is array(3 downto 0) of byte;
  type bit_vector is array(integer range < >) of bit;
  variable my_vector: bit_vector(5 downto -5);

subtype子类型定义语句:
subtype是可以实现用户自定义的数据子类型,主要有3种描述格式。
  ·  整数子类型描述:
  subtype <subtype_name> is integer range <lower_limit> to <upper_limit>;
示例:
  subtype digits is integer range 0 to 9;
  ·  数组子类型描述:
  subtype <subtype_name> is array range <lower_limit> to <upper_limit>;
  ·  通用子类型描述:
subtype <subtype_name> is subtype <<subtype_definition>>;
示例:
  type bit_vector is array(integer range < >) of bit;
  subtype my_vector is ibit_vector(0 downto 15);

记录类型:
记录是不同类型的名称域的集合,格式为:
  type 记录类型名 is record
     元素名 : 数据类型名;
     元素名 : 数据类型名;
     ......
  end record;

访问记录元素的方式: 记录体名.元素名
示例:
  constant len: integer :=8;
  subtype byte_vec is bit_vector(len-1 downto 0);
  type byte_and_ix is record
     byte: byte_vec;
     ix: integer range 0 to len;
  end record;
  signal x,y,z: byte_and_ix;
  signal data: byte_vec;
  signal num: integer;
  ......
  x.byte<="11110000";
  x.ix<=2;
  data<=y.byte;
  num<=y.ix;
  z<=x;

④数据类型转换:
VHDL中,不同类型的数据对象必须经过类型转换,才能相互操作。
IEEE库numeric_std.all包集合中常用的几种转换函数:
  ·  整数转有符号数的函数:
  <signed_sig>=TO_SIGNED(<int_sig>,<integer_size>);
  ·  整数转无符号数的函数:
  <unsigned_sig>=TO_UNSIGNED(<int_sig>,<integer_size>);
  ·  有符号数转整数的函数:
  <int_sig>=TO_INTEGER(<signed_sig>);
  ·  无符号数转整数的函数:
  <int_sig>=TO_INTEGER(<unsigned_sig>);
IEEE库std_logic_1164.all包集合中常用的几种转换函数:
  ·  bit转StdUlogic的函数:
  <sul_sig>=TO_StdUlogic(<bit_sig>);
  ·  bit_vector转std_logic_vector的函数:
  <slv_sig>=TO_StdLogicVector(<bv_sig>);
  ·  bit_vector转std_ulogic_vector的函数:
  <sulv_sig>=TO_StdULogicVector(<bv_sig>);
  ·  std_logic_vector转bit_vector的函数:
  <bv_sig>=TO_bitvector(<slv_sig>);
  ·  std_logic_vector转std_ulogic_vector的函数:
  <sulv_sig>=TO_StdULogicVector(<slv_sig>);
  ·  std_ulogic转bit的函数:
  <bit_sig>=TO_bit(<sul_sig>);
  ·  std_logic_vector转bit_vecto的函数:
  <bv_sig>=TO_bitvector(<sulv_sig>);
  ·  std_ulogic_vector转std_logic_vector的函数:
  <slv_sig>=TO_StdLogicVector(<sulv_sig>);
IEEE库sta_logic_arith.all包集合中常用的几种转换函数:
  ·  integer转signed的函数:
  <signed_sig>=CONV_SIGNED(<int_sig>,<integer_size>);
  ·  integer转std_logic_vector的函数:
  <slv_sig>=CONV_STD_LOGIC_VECTOR(<int_sig>,<integer_size>);
  ·  integer转unsigned的函数:
  <unsigned_sig>=CONV_UNSIGNED(<int_sig>,<integer_size>);
  ·  signed转integer的函数:
  <int_sig>=CONV_INTEGER(<signed_sig>);
  ·  signed转std_logic_vector的函数:
  <slv_sig>=CONV_STD_LOGIC_VECTOR(<signed_sig>);
  ·  signed转unsigned的函数:
  <unsigned_sig>=CONV_UNSIGNED(<signed_sig>);
  ·  std_logic_vector转std_logic_vector(符号扩展)的函数:
  <slv_sxt_sig>=SXT(<slv_sig>);
  ·  std_logic_vector转std_logic_vector(零位扩展)的函数:
  <slv_sxt_sig>=EXT(<slv_sig>);
  ·  std_ulogic转sighed的函数:
  <signed_sig>=CONV_SIGNED(<sul_sig>);
  ·  std_ulogic转small_int的函数:
  <int_sig>=CONV_INTEGER(<sul_sig>);
  ·  std_ulogic转std_logic_vector的函数:
  <slv_sig>=CONV_STD_LOGIC_VECTOR(<sul_sig>);
  ·  std_ulogic转unsighed的函数:
  <unsigned_sig>=CONV_UNSIGNED(<sul_sig>);
  ·  unsighed转integer的函数:
  <int_sig>=CONV_INTEGER(<unsigned_sig>);
  ·  unsighed转signed的函数:
  <signed_sig>=CONV_SIGNED(<unsigned_sig>);
  ·  unsighed转std_logic_vector的函数:
  <slv_sig>=CONV_STD_LOGIC_VECTOR(<unsigned_sig>);
IEEE库std_logic_signed.all中常用的转换函数:
  ·  std_logic_vector转integer的函数:
  <int_sig>=CONV_INTEGER(<slv_sig>);
IEEE库std_logic_unsigned.all中常用的转换函数:
  ·  std_logic_vector转integer的函数:
  <int_sig>=CONV_INTEGER(<slv_sig>);
示例:
  signal u1 : unsigned (3 downto 0);
  signal s1 : signed (7 downto 0);
  signed v1,v2 : std_logic_vector (3 downto 0);
  signed v3,v4 : std_logic_vector (7 downto 0);
  signed i1,i2 : integer;
  u1 <= "1101";
  s1 <= "1101";
  i1 <= 13;
  i2 <= -2;
  wait for 10 ns;
  v1 <= conv_std_logic_vector(u1,4);    -- = "1101"
  v2 <= conv_std_logic_vector(s1,4);    -- = "1101"
  v3 <= conv_std_logic_vector(i1,8);    -- = "00001101"
  v4 <= conv_std_logic_vector(i2,8);    -- = "00001101"

示例2:
  signed b : std_logic;
  signed u1 : unsigned(3 downto 0);
  signed s1 : signed(3 downto 0);
  signed i1,i2 : integer;
  u1 <= "1001";
  s1 <= "1001";
  b <= 'X';
  wait for 10 ns;
  i1 <= conv_integer(u1);    -- 9
  i2 <= conv_integer(s1);    -- -7

3) 预定义属性:

属性是某一对象的特征表示,是一个内部预定义函数。VHDL语言中的预定义属性包括数组支持的预定义属性、对象支持的预定义属性、信号支持的预定义属性和类型支持的预定义属性。
①数组支持的预定义属性:
数组支持的预定义属性格式:
  <array_id>'attribute
其中,array_id为该属性所属的数组的名称,attribute为数组所支持的属性。数组支持的预定义属性包括以下几类:
  ·  <array_id>'range(<expr>)   ----得到数组的范围
  ·  <array_id>'left(<expr>)   ----得到数组的左限值
  ·  <array_id>'length(<expr>)   ----得到数组的范围个数
  ·  <array_id>'lower(<expr>)   ----得到数组的下限值
  ·  <array_id>'ascending(<expr>)   ----数组索引范围的升序判断
  ·  <array_id>'reverse_range(<expr>)   ----得到数组的逆向个数
  ·  <array_id>'right(<expr>)   ----得到数组的右限值
  ·  <array_id>'upper(<expr>)   ----得到数组的上限值
示例:
  signal x : std_logic_vector(7 downto 0);
  signal y : std_logic_vector(0 downto 8);
  type z is array(0 to 5,0 to 8) of std_logic;

  x'left=7, y'left=0;
  x'right=0, y'right=8, z'right(2)=8;
  x'high=7 y'high=8, y'high(1)=5;
  x'range=7 downto 0; x'reverse_range=0 to 7;
  x'length=8, y'length=9;

②对象支持的预定义属性:
对象支持的预定义属性格式:
  <object_id>'attribute
其中,object_id为该属性所属的对象的名称,attribute为对象所支持的属性,对象支持的预定义属性有以下几类:
  ·  <object_id>'simple_value   ----该属性将取得所指定命名项的名字,如标号、变量名、信号名等
  ·  <object_id>'instance_name   ----该属性将给出指定项的路径
  ·  <object_id>'path_name   ----该属性将给出指定项的路径,但不显式说明的设计单元
示例:
  signal clk : std_logic;
  type state is(ini,work1,finish);
  clk'simple_value-"clk";
  work'simple_value-"work1";

  full_addr'instance_name-":full_addr(dataflow):";
  full_addr'path_name-":full_addr):";

③信号支持的预定义属性:
信号支持的预定义属性格式:
  <signal_id>'attribute
其中,signal_id为该属性所属的信号的名称,attribute为信号所支持的属性。信号支持的预定义属性有以下几类:
  ·  <signal_id>'driving   ----取得当前进程中的信号值
  ·  <signal_id>'active   ----如果在当前相当小的时间间隔内信号发生了改变,将返回真,否则假
  ·  <signal_id>'delayed(<TIME>)   ----产生一个延迟信号,延迟信号类型与原信号类型相同
  ·  <signal_id>'event   ----如果在当前相当小的时间间隔内事件发生了,将返回真,否则为假
  ·  <signal_id>'quiet(<TIME>)   ----在指定时间内如果参考信号发生转换或其他事件,属性为真
  ·  <signal_id>'stable(<TIME>)   ----在指定时间内如果参考信号发生事件,属性为假
  ·  <signal_id>'last_active   ----返回一个从信号前一次变化到现在的时间值
  ·  <signal_id>'last_event   ----返回一个从信号前一次事件发生到现在的时间值
  ·  <signal_id>'transaction   ----当信号发生转换或事件时,建立的一个bit信号的值发生变化
  ·  <signal_id>'last_value   ----返回一个信号最后一次改变之前的值
  ·  <signal_id>'driving_active   ----得到信号的驱动值,只用于进程中
示例:
  if(clk='1' and clk'event and clk'last_value='0') then
  if(not(clk'stable) and (clk='1') and (clk'last_value='0')) then

④类型支持的预定义属性:
类型支持的预定义属性格式:
  <type_id>'attribute
其中,type_id为该属性所属的类型的名称,attribute为类型所支持的属性。类型支持的预定义属性有以下几类:
  ·  <type_id>'ascending   ----数据类或子类索引范围的升序判断
  ·  <type_id>'base   ----得到数据类型或子类型
  ·  <type_id>'left   ----得到数据类或子类区间最左端的值
  ·  <type_id>'low   ----得到数据类或子类区间的低端值
  ·  <type_id>'succ(<expr>)   ----得到输入expr值的下一个值
  ·  <type_id>'pos(<expr>)   ----得到输入expr值的位置序号
  ·  <type_id>'pred(<expr>)   ----得到输入expr值的前一个值
  ·  <type_id>'right   ----得到数据类或子类区间最右端的值
  ·  <type_id>'image(<expr>)   ----得到数据类或子类的一个标量值,并产生一个串描述
  ·  <type_id>'high   ----得到数据类或子类区间的高端值
  ·  <type_id>'val(<expr>)   ----得到输入位置序号expr的值
  ·  <type_id>'value(<string>)   ----取一个标量的值的串描述,并产生其等价值
  ·  <type_id>'leftof(<expr>)   ----得到邻接输入expr值左边的值
  ·  <type_id>'rightof(<expr>)   ----得到邻接输入expr值右边的值
示例:
  type counter is integer range 255 downto 0;
  counter'high=255;counter'low=0;counter'left=255;counter'right=0;

  type color is (red,green,blue,yellow);
  color'succ(green)=blue;color'rightof(green)=blue;color'pred(green)=red;
  color'leftof(green)=red;color'image(green)="green";color'value("green")=green;

⑤用户自定义属性:
用户自定义属性的书写格式为:
  attribute <attribute_name> : <data_subtype_name>;
  attribute <attribute_name> of <target_name> : <target_set> is <equation>;

其中,attribute_name为自定义属性名,data_subtype_name为数据子类型名,target_name为目标的名字,target_set为目标集合,equation为等式。
示例:
  attribute max_number : real;
  attribute max_number of fifo : entity is 150.0;
  attribute resistance : res;
  attribute resistance of clk,reset : signal is 20 ms;

7. VHDL语言的操作符:

VHDL语言中有5类操作符,分别为逻辑操作符、关系操作符、算术操作符、并置操作符、重载操作符,它们可以分别进行逻辑运算、关系运算、算术运算、并置运算、重载运算。被操作符所操作的对象是操作数,且操作数的类型应该与操作符所要求的类型一致。但各家EDA综合软件对运算操作符支持的程序各不相同。

1) 逻辑运算符Logical Operator

逻辑运算符共有6种,分别为and、or、nand、nor、xor、not,其要求的操作数类型必须相同。逻辑运算可操作的类型包括bit、bit_vector、std_logic、std_logic_vector、boolean。数组操作的维数、大小必须相同。当有两个以上的逻辑表达式时,左右没有优先差别,必须使用括号。示例:
  x <= (a and b) or (not c and d);
当逻辑表达式只有and、or、xor运算符时,可以省略括号:
  a <= b and c and d and e;   a <= b or c or d or e;   a <= b xor c xor d xor e;

2) 关系运算符Relational Operator

关系运算符共有6种,分别为=、/=(不等于)、<、<=、>、>=,用于比较相同父类的两个操作数,返回boolean值。

3) 算术运算符Arithmetic Operator

算术运算符包括+、-、*、/、mod(求模)、rem(求余)、**(幂)。其中,/、mod、rem三种操作符的右操作数必须为2的正整数次幂,即2n,实际电路用移位实现。

4) 并置操作符Overloading Operator

并置操作符“&”通过连接操作数来建立新的数组,操作数可以是一个数组或数组中的一个元素。示例:
  signal a,d : bit_vector (3 downto 0);
  signal b,c,g : bit_vector (1 downto 0);
  signal e : bit_vector (2 downto 0);
  signal f,h,i : bit;
  a <= not b & not c; ----array & array
  d <= not e & not f; ----array & element
  f <= not h & not i; ----element & element

5) 重载操作符Overload Operator

VHDL为强类型语言,相同类型的操作数才能进行操作,VHDL语言自身定义的算术和布尔函数仅对内部数据类型有效,运算符+、-、<、>、<=、>=仅对integer类型有效,运算符and、or、not仅对bit类型有效。
对已存在的操作符重新定义,使其能进行不同类型操作符之间的运算,称为重载操作,定义重载操作符的函数称为重载函数。重载操作符由原操作符加双引号表示,如"+"。
重载操作符的定义见IEEE库的包集合std_logic_arith、std_logic_signed、std_logic_unsigned。示例:
  variable a,b,c : integer;
  variable x,y,z : bit;
  c := a+b;
  z := x and y;

8. VHDL语言的顺序描述语句:

VHDL语言的语句按照执行的顺序可以分为顺序描述语句和并发描述语句两大类。在一个结构体内,可以有几个进程语句同时存在,各个进程语句是并发执行的;在进程内部的所有语句是顺序描述语句,也就是按照书写的顺序自上而下依次执行。
顺序描述语句的执行顺序与书写顺序一致,与传统软件设计语言的特点相似。顺序语句只能用在进程与子进程中,可描述组合逻辑、时序逻辑。
常用的顺序描述语句有变量与信号赋值语句、if语句、case语句、loop语句、next语句、exit语句、子程序、return语句、wait语句、null语句等类别。

1) 对象赋值语句

①对象赋值:
在赋值语句中,通常可以对如下对象进行赋值操作:
  ·  简单名称,如my_var。
  ·  索引名称,如my_array_var(3)。
  ·  片段语句,如my_array_var(3 to 6)。
  ·  记录域名,如my_record.a_field。
  ·  集合,如(my_var1, my_var2)。

②变量赋值与信号赋值:
在对象赋值语句中,主要分为对变量或信号的赋值操作,其不同点主要表现在赋值方式的不同和硬件实现的功能不同两个方面。
信号代表电路单元和功能模块间的互联,代表实际的硬件连线;变量代表电路单元内部的操作,代表暂存的临时数据。所有对象均可分为变量和信号对象。
信号的作用范围包括包集合、实体、结构体,是全局变量;变量的作用范围是进程、子程序,是局部量。信号赋值延迟更新数值,是时序电路;变量赋值立即更新数值,是组合电路。
对一个进程多次赋值时,只有最后一次赋值有效,多个进程的赋值表示包括多源驱动、线与、线或和三态。
③示例:
信号赋值:
  architecture rtl of sig is
     signal a,b : std_logic;   ----定义信号
  begin
     process(a,b)
     begin
         a <= b;
         b <= a;
     end process;
  end rtl;   ---- 结果是a和b的值互换

变量赋值:
  architecture rtl of var is
  begin
     process
       variable a,b: sta_logic;   ----定义变量
     begin
       a := b;
       b := a;
     end process;
  end rtl;   ---- 结果是a和b的值都等于b的初值

变量赋值实现循环语句功能:
  process(indicator, sig)
     variable temp : std_logic;
  begin
     temp := '0';
     for i in 0 to 3 loop
       temp := temp xor (sig(i) and indicator(i));
     end loop;
     output <= temp;
  end process;

以上语句等效为:
  process(indicator, sig)
     variable temp : std_logic;
  begin
     temp := '0';
     temp := temp xor (sig(0) and indicator(0));
     temp := temp xor (sig(1) and indicator(1));
     temp := temp xor (sig(2) and indicator(2));
     temp := temp xor (sig(3) and indicator(3));
     output <= temp;
  end process;

2) 转向控制语句

转向控制语句通过条件控制开关决定是否执行一条或几条语句,或重复执行一条或几条语句,或跳过一条或几条语句。转向控制语句主要有if语句、case语句、loop语句、next语句、exit语句、wait语句6种。
①if语句:
if语句是转向控制语句中最基本的语句之一,格式为:
  if <condition> then
     <statement>
  elsif <condition> then
     <statement>
  else
     <statement>
  end if

其中,condition为判断条件的描述,<statement>为在该判断条件成立的条件下的逻辑行为的描述。示例:
  architecture rtl of mux2 is
     begin
     process(a,b,sel)
     begin
       if (sel='1') then
         y<=a;
       else
         y<=a;
       end if;
     end process;
  end rtl;

if语句中隐含了优先级别的判断,最先出现的条件优先级最高,可用来设计具有优先级的电路,典型的是8:3编码电路。示例:
  library IEEE;
     use IEEE.STD_LOGIC_1164.ALL;
     entity coder is
       port(input: in std_logic_vector(7 downto 0);
       output: out std_logic_vector(2 downto 0));
     end coder;
  architecture art of coder is
  begin
     process(input)
     begin
       if input(7)='0' then output<="000";
       elsif input(6)='0' then output<="001";
       elsif input(5)='0' then output<="010";
       elsif input(4)='0' then output<="011";
       elsif input(3)='0' then output<="100";
       elsif input(2)='0' then output<="101";
       elsif input(1)='0' then output<="110";
       else output<="111";
       end if;
     end process;
  end art;

②case语句:
case语句常用来描述总线或编码、译码行为,可读性比if语句强。格式:
  case <expression> is
     when <condition> => <sequential sentence>;
     when <condition> => <sequential sentence>;
     ......
     when <condition> => <sequential sentence>;
  end case;

其中,expression为判断条件的表达式,condition为判断条件的一个特定值,sequential sentence为在该判断条件的某一特定值成立的情况下通过顺序描述语句所描述的逻辑行为。
在case语句中的分支条件可以写作如下形式:
  ·  when <value> => <sequential sentence>
  ·  when <value> to <value> => <sequential sentence>
  ·  when <value>|<value>|<value>|...|<value> => <sequential sentence>
  ·  when others => <sequential sentence>

使用case语句时需要注意:
  ·  分支条件的值必须在表达式的取值范围内
  ·  两个分支条件不能重叠
  ·  case语句执行时必须选中,且只能选中一个分支条件
  ·  如果没有others分支条件存在,则分支条件必须覆盖表达式所有可能的值
  ·  对于std_logic、std_logic_vector数据类型,要特别注意使用others分支条件
示例:4选1电路
  entity multiplexers_2 is
     port(a,b,c,d: in std_logic;
       s: in std_logic_vector(1 downto 0);
       o: out std_logic);
  end multiplexers_2;
  architecture archi of multiplexers_2 is
  begin
     process(a,b,c,d,s)
     begin
       case s is;
         when "00" => o <=a;
         when "01" => o <=b;
         when "10" => o <=c;
         when others => o <=d;
       end case;
     end process;
  end archi;

③loop语句:
Loop语句与其他高级语言中的循环语句相似,有下面的3种格式:
无限loop语句:
  [loop_label]: LOOP
     --sequential statement
     if <signal_name> = <value> then
       exit;
     end if;
     exit loop_label;
  end loop;

VHDL程序会重复执行loop循环内的语句,直至遇到exit语句所满足的结束条件时才退出循环。示例:
  L2: loop
     a:=a+1;
     exit L2 when a>10;
     end loop L2;
  ......

在上面的例子中,当a>10时,退出无限循环条件。
for...loop语句:
  for <variable_name> in <lower_limit> to <upper_limit> loop
     <statement>;
     <statement>;
  end loop;

其中,variable_name为循环变量的名字,lower_limit为变化的下限值,upper_limit为变化的上限值,statement为该循环语句中的行为描述。
for...loop语句的特点:
  ·  循环变量是loop内部自动声明的局部量,仅在loop内可见,不需要指定其变化方式
  ·  离散范围从lower_limit到upper_limit必须是可计算的整数范围
  Integer_expression to Integer_expression
  Integer_expression downto Integer_expression

其中,Integer_expression为整数表达式,在该式中可以确定表达式的上限和下限条件。
示例:8位奇偶校验电路
  library IEEE;
     use IEEE.STD_LOGIC_1164.ALL;
     entity parity_check is
       port(a: in std_logic_vector(7 downto 0);
         y: out std_logic);
     end parity_check;
  architecture rtl of parity_check is
  begin
     process(a)
       variable tmp : std_logic;
     begin
       tmp := '1';
       for I in 0 to 7 loop
         tmp:=tmp xor a(i);
       end loop;
       y<=tmp;
     end process;
  end rtl;

while...loop语句:
  while <condition> loop
     <statement>;
     <statement>;
  end loop;

其中,condition为循环成立的条件表达式,statement为该循环语句中的行为描述。示例:
  num:=0;
  i:=0;
  aaa: while (i<10) loop
     sum:=sum+i;
     i:=i+1;
  end loop aaa;

使用的循环变量需要先定义并赋初值,并指定其变化方式。一般综合工具不支持while...loop语句。
④next语句:
在loop循环中,next语句用来跳出本次循环。格式为:
  next [label] [when condition_expression]
该语句的使用分为3种情况:
  ·  next:无条件终止当前的循环,跳回到本次循环loop语句开始处,并开始下次循环
  ·  next [label]:无条件终止当前循环,跳转到lable的loop语句开始处,开始执行循环操作
  ·  next:next [label] [when condition_expression]:当条件表达式condition_expression的值为true时,执行next语句,进入跳转操作,否则继续向下执行。示例:
  L1: while i<10 loop
     L2: while j<20 loop
       ......
       next L1 when i=j;
       ......
     end loop L2;
  end loop L1;

⑤exit语句:
exit语句结束循环状态。格式:
  exit [label] [when condition_expression]
示例:
  process(a)
     variable int_a: integer;
  begin
     int_a := a;
     for i in 0 to max_limit loop
       if (int_a <= 0) then
         exit;
       else int_a := int_a-1;
       end if;
     end loop;
  end process;

⑥wait语句:
进程在仿真时的两个状态为执行和挂起。进程状态的变化受wait语句或敏感信号量变化的控制,可设置如下4种不同的条件。
  ·  wait:无限等待
  ·  wait on:敏感信号量变化
  ·  wait until:条件满足
  ·  wait for:时间到
wait on语句:不可综合
  wait on <signal_name>;
示例:
  process(a,b)
  begin
     y<=a and b;
  end process;

  process
  begin
     y<=a and b;
     wait on a, b;
  end process;

上面两种描述完全等价。注意,敏感信号量列表和wait语句只能选其一,两者不能同时使用。
wait until语句:可综合
  wait until <expression>;
其中,expression为判断表达式。当表达式的值为真时,进程被启动,否则进程被挂起。如下描述可实现相同的硬件电路结构:
  ·  wait until clk='1';
  ·  wait until rising_edge(clk);
  ·  wait until clk'event and clk='1';
  ·  wait until not(clk'stable) and clk='1';

示例:描述时钟沿来实现D触发器
  architecture rtl of d is
   begin
     process
     begin
       wait until clk'event and clk='1';
       q <= d;
     end process;
  end rtl;

3) 断言语句

在仿真中,为了能得到更多信息,经常要用到断言语句assert,语法为:
  Assert <condition>
  Report <message>
  Severity <error_level>;

断言语句可以监测到在VHDL程序设计中不希望的条件,比如在generic中的错误的值、常数和产生条件,或者在调用函数时错误的调用参数等。
对于在断言语句中的任何错误条件,综合工具都会根据错误的级别,产生警告信息,或者拒绝设计和产生错误信息。出错级别共有5种,分别为Note、Warning、Error、Failure以及Fatal。一些综合工具对断言语句只支持静态的条件。
示例:
  use IEEE.STD_LOGIC_1164.ALL;
  entity SINGLE_SRL is
     generic(SRL_WIDTH : integer := 16);
     port(clk: in std_logic;
         inp: in std_logic;
         outp: out std_logic);
   end SINGLE_SRL;
  architecture beh of SINGLE_SRL is
     signal shift_reg : std_logic_vector(SRL_WIDTH-1 downto 0);
  begin
     assert SRL_WIDTH<=17
     report "The size of Shift Register exceeds the size of a single SRL"
     severity FAILURE;
     out <= shift_reg(SRL_WIDTH-1);
     process(clk)
     begin
       if (clk'event and clk='1') then
         shift_reg <= shift_reg(SRL_WIDTH-1 downto 1) & inp;
       end if;
     end process;
  end beh;

  library ieee;
  use IEEE.STD_LOGIC_1164.ALL;
  entity TOP is
     port(clk: in std_logic;
         inp1,inp2: in std_logic;
         outp1,outp2: out std_logic);
   end TOP;
  architecture beh of TOP is
     component SINGLE_SRL is;
       generic (SRL_WIDTH : integer := 16);
       port(clk: in std_logic;
           inp: in std_logic;
           outp: out std_logic);
     end component;
  begin
     inst1 : SINGLE_SRL generic map (SRL_WIDTH => 13)
     port map(clk=>clk;
           inp=>inp1;
           outp=>outp1);
     inst2 : SINGLE_SRL generic map (SRL_WIDTH => 18)
     port map(clk=>clk;
           inp=>inp2;
           outp=>outp2);
  end beh;

使用综合工具时,会产生错误信息。

9. VHDL语言的并发描述语句:

常用的VHDL并发描述语句有,进程描述语句、并行信号赋值语句、条件信号赋值语句、并行过程调用语句和块语句、选择信号赋值语句。

1) 进程描述语句:

进程描述语句是VHDL语言中最基本的,也是最常用的并发描述语句。多个进程语句可以并发执行,提供了一种算法描述硬件行为的方法。进程描述语句有以下特点:
  ·  进程与进程,或其他并发语句之间可以并发执行
  ·  在进程内部的所有语句是按照顺序执行的
  ·  进程的启动由其敏感信号量表内的敏感向量或者wait语句确定
  ·  进程与进程,或其他并发语句之间通过传递信号量实现通信
进程描述语句的格式:
  process (<all_input_signals_seperated_by_commas>)
  begin
     <statements>;
  end process;

其中,process后面的括号内的部分称为敏感信号量表,括号里的每个部分称为敏感信号量,敏感信号量表内的输入信号使用逗号隔开。
同步进程的敏感信号表中只有时钟信号。示例:
  process (clk)
  begin
     if (clk'event and clk='1') then
       if reset ='1' then
         data <= "00";
       else
         data <= in_data;
       end if;
     end if;
  end process;

异步进程敏感信号表中除时钟信号外,还有其他信号。示例:
  process (clk, reset)
  begin
     if reset='1' then
       data <= "00";
     elsif(clk'event and clk='1') then
       data <= in_data;
     end if;
  end process;

如果有wait语句,则不允许有敏感信号表。格式为:
  process
  begin
     -- sequential statements
     wait on (a,b);
  end process;

2) 并行信号赋值语句:

信号赋值语句可以在进程内部使用,此时它以顺序语句的形式出现,当信号赋值语句在结构体的进程外使用时,信号赋值语句将以并行语句形式出现。示例:
  architecture behav of a_var is    --并行信号赋值语句
  begin
     output<=(a and b) or c;
  end behav;

  architecture behav of a_var is    --进程内部信号赋值语句
  begin
     process(a,b,c)
     begin
       output<=(a and b) or c;
     end process;
  end behav;

可见,一个简单的并行信号赋值语句实际上是一个进程的缩写。并行信号赋值语句中的任何一个信号值发生变化时,赋值操作都会立即执行。而在进程内,只有当敏感向量表中的敏感信号量发生变化时,赋值操作才会执行。

3) 条件信号赋值语句:

条件信号赋值语句是并发描述语句,它可以根据不同条件将多个不同表达式中的一个值代入信号量。条件信号赋值语句描述的格式为:
  <name><=<expression> when <condition> else
     <expression> when <condition> else
     ......
     <expression>;

其中,name表示目标信号,expression表示对目标信号的赋值过程,condition表示不同的选择条件。
示例:条件信号赋值语句描述的4选1电路
  entity mux4 is
     port(i0,i1,i2,i3: in std_logic;
       sel: in std_logic_vector(1 downto 0);
       q: out std_logic);
  end mux4;
  architecture rtl of mux4 is
  begin
     q<=i0 when sel = "00" else
     q<=i1 when sel = "01" else
     q<=i2 when sel = "10" else
     q<=i3 when sel = "11";
  end rtl;

条件信号赋值语句与进程中的多选择if语句等价。

4) 选择信号赋值语句:

  with <choice_expression> select
     <name> <= <expression> when <choices>,
       <expression> when <choices>,
       <expression> when others;

其中,choice_expression为选择条件的表达式,name为赋值过程的目标信号,expression为赋值过程的源表达式,choices为条件表达式的具体条件值。
在应用选择信号赋值语句时需要注意:
  ·  不能有重复的条件分支
  ·  最后条件可为others,否则其他条件必须能包含表达式的所有可能值
选择信号赋值语句与进程中的case语句等价。
示例:选择信号赋值语句描述的4选1电路
  entity mux4 is
     port(i0,i1,i2,i3: in std_logic;
       sel: in std_logic_vector(1 downto 0);
       q: out std_logic);
  end mux4;
  architecture rtl of mux4 is
     signal sel : std_logic_vector(1 downto 0);
  begin
     with sel select
     q<=i0 when sel = "00",
       i1 when sel = "01",
       i2 when sel = "10",
       i3 when sel = "11",
       'X' when others;
  end rtl;

5) 并行过程调用语句:

子程序是独立的、有名称的算法,可分为过程Procedure和函数Function两类。只要对其声明,可在任何地方根据其名字调用子程序。
①子程序调用格式:
  <procedure_name>(<comma_seperated_inputs>,<comma_seperated_outputs>);
其中,procedure_name为子程序名,括号里面为用逗号分割的输入变量和输出变量的名字。
用过程名在结构体或块语句中,即可实现并行过程调用,作用与一个进行等价。示例:
  procedure adder(signal a,b: in std_logic;
       signal sum: out std_logic)
       ......
       adder(a1,b1,sum1);
  process(c1,c2)
  begin
     adder(c1,c2,s1);
  end process;

②函数调用格式:
  <signal_name>=<function_name>(<comma_seperated_inputs>);
其中,signal_name为所需要赋值的信号名,function_name为函数名,括号里面为用逗号分割的输入变量的名字。

6) 块语句:

块语句将一系列并行描述语句进行组合,目的是改善并行语句及其结构的可读性,可使结构体层次鲜明,结构明确。块语句的语法为:
  label: block[(块保护表达式)]
     {块说明项}
     begin
       {并行语句}
    end block[label];

块语句的使用不影响逻辑功能。
示例:块描述语句
  a1: out1<='1' after 2 ns;
  a2: out2<='1' after 2 ns;
  a3: out3<='1' after 2 ns;

  a1: out1<='1' after 2 ns;
  blk1: block
  begin
     a2: out2<='1' after 2 ns;
     a3: out3<='1' after 2 ns;
  end blk1;

上面两种描述结果相同。
①嵌套块:
子块声明与父块声明的对象同名时,子块声明将忽略父块声明。示例:
  B1: block
     signal s:bit;
  begin
     s<=a and b;
     B2:block
       signal s:bit
     begin
       s<=c and d;
       B3:block
       begin
         z<=s;
       end block B3;
     end block B2;
  end block B1;

②卫式块:
由保护表达式值的真、假决定块语句的执行与否。综合工具不支持该语句。示例:
  entity eg1 is
     port(a: in bit;
       z: out bit);
  end eg1;
  architecture rtl of eg1 is
  begin
     guarded_block:blobk(a='1');
     begin
       z<='1' when guard else '0';
     end block;
  end rtl;

10. VHDL的元件声明及例化语句:

1) 元件声明:

元件声明是对所调用的较低层次的实体模块(元件)的名称、类属参数、端口类型、数据类型进行的说明。元件声明语句的格式:
  component <component_name>
  generic(
     <generic_name> : <type> := <value>;
     <other generics> ......
  );
  port(
     <port_name> : <mode> <type>;
     <other ports> ......
  );
  end components;

其中,component_name为所要声明的元件的名字,generic()为元件的类属说明部分,port()为元件的端口说明部分。
元件声明类似实体声明,可在结构体、包集合、块部分声明元件。被声明的元件的来源为VHDL设计实体、其他HDL设计实体,以及另外一种标准格式的文件(如EDIF或XNF)、厂商提供的工艺库中的元件和IP核。示例:
  component and2
  port(
     i1,i2 : in std_logic;
     o1 : out std_logic);
  );
  end components;
  component add
     generic(n : positive);
     port(x,y : in std_logic_vector(n-1 downto 0);
       z : out std_logic_vector(n-1 downto 0);
       carry : out std_logic);
  end components;

2) 元件例化:

元件例化,即把低层元件安装(调用)到当前层次设计实体内部的过程,包括类属参数传递和元件端口映射。元件例化语句的格式为:
  <instance_name> : <component_name>
  generic map(
     <generic_name> => <value>,
     <other generics> ......
  )
  port map(
     <port_name> => <signal_name>,
     <other ports> ......
  );

其中,instance_name为例化元件的名字,component_name为引用元件的名字,generic map()为例化元件的类属参数传递部分,port map()为例化元件的端口映射部分。
示例:
  u1: ADD generic map(N => 4)
     port map (x,y,z,carry);

采用名称关联方式:
低层次端口名 => 当前层次端口名, 信号名
示例:or2 port map(o => n6,i1 => n3,i2 => n1);
采用位置关联方式:
(当前层次端口名,当前层次端口名, ......)
示例:or2 port map(n3,n1,n6);
当采用位置关联方式时,例化的端口表达式(信号)必须与元件声明语句中的端口顺序一致。一个低层次设计在被例化前必须有一个元件声明。
示例:半加器
  entity NAND2 is
     port(A,B: in BIT;
       Y: out BIT);
  end NAND2;
  architecture ARCHI of NAND2 is
  begin
       Y <= A and B;
  end ARCHI;

  entity HALFADDER is
     port(X,Y: in BIT;
       C,S: out BIT);
  end HALFADDER;
  architecture ARCHI of HALFADDER is
     component NAND2
       port(A,B: in BIT;
         Y: out BIT);
     end component;
     for all : NAND2 use entity work.NAND2(ARCHI);
       signal S1,S2,S3 : BIT
  begin
     C <= S3;
     NANDA : NAND2 port map (X,Y,S3);
     NANDB : NAND2 port map (X,S3,S1);
     NANDC : NAND2 port map (S3,Y,S2);
     NANDD : NAND2 port map (S1,S2,S);
  end ARCHI;

3) 生成语句:

生成语句主要用于复制建立0个或多个备份,实质就是一种并行结构。生成语句分为两类:
①for...generate语句:
采用一个离散的范围决定备份的数目。格式:
  <LABEL_1>:
     for <name> in <lower_limit> to <upper_limit> generate
     begin
       <statement>
       <statement>
     end generate;

其中,LABEL_1为标号,name为循环变量的名字,lower_limit和upper_limit分别为整数表达式的下限和上限,statement为并行描述语句。
示例:8bit加法器
  entity EXAMPLE is
     port(A,B: in BIT_VECTOR (0 to 7);
       C: in BIT;
       SUM: in BIT_VECTOR (0 to 7);
       COUT: out BIT);
  end EXAMPLE;
  architecture ARCHI of EXAMPLE is
     signal C : BIT_VECTOR (0 to 8);
  begin
     C(0) <= CIN;
     COUT <= C(8);
     LOOP_ADD : for I in 0 to 7 generate;
       SUM(I) <= A(I) xor B(I) xor C(I);
       C(I+1) <= (A(I) and B(I)) or (A(I) and C(I)) or (B(I) and C(I));
     end generate;
  end ARCHI;

②if...generate语句:
有条件地生成0个或1个备份,为并行语句。if...generate语句没有类属于if语句的else或elsif分支语句。语法格式:
  <LABEL_1>:
     if <condition> generate
     begin
       <statement>
     end generate;

其中,LABEL_1为标号,condition为产生语句的运行条件,statement为并行描述语句。
示例:8bit加法器
  entity EXAMPLE is
     generic (N: INTEGER := 8);
     port(A,B: in BIT_VECTOR (N downto 0);
       CIN: in BIT;
       SUM: out BIT_VECTOR (N downto 0);
       COUT: out BIT);
  end EXAMPLE;
  architecture ARCHI of EXAMPLE is
     signal C : BIT_VECTOR (N+1 downto 0);
  begin
     L1:if (N>=4 and N<=32) generate
       C(0) <= CIN;
       COUT <= C(N+1);
       LOOP_ADD : for I in 0 to N generate;
         SUM(I) <= A(I) xor B(I) xor C(I);
         C(I+1) <= (A(I) and B(I)) or (A(I) and C(I)) or (B(I) and C(I));
       end generate;
     end generate;
  end ARCHI;

11. VHDL的文件操作:

VHDL语言中提供了一个预定义的包集合,是文本输入输出包集合TEXTIO,其中包含有对文件文本进行读写操作的过程和函数。这些文本文件是ASCII码文件,其格式由设计人员根据实际情况进行设定。
包集合按行对文件进行处理,一行为一个字符串,并以回车、换行符作为结束符。TEXTIO包集合提供了读、写一行的过程及检查文件结束的函数。下表为Xilinx的XST所支持的操作:

file (type text only) standard
access (type line only) standard
file_open (file,name,open_kind) standard
file_close (file) standard
endfile (file) standard
text std.textio
line std.textio
width std.textio
readline (text,line) std.textio
readline (line,bit,boolean) std.textio
readline (line,bit_vector,boolean) std.textio
read (line,bit) std.textio
read (line,bit_vector) std.textio
read (line,boolean,boolean) std.textio
read (line,boolean) std.textio
read (line,character,boolean) std.textio
read (line,character) std.textio
read (line,string,boolean) std.textio
read (line,string) std.textio
write (file,line) std.textio
write (line,bit,boolean) std.textio
write (line,bit) std.textio
write (line,bit_vector,boolean) std.textio
write (line,bit_vector) std.textio
write (line,boolean,boolean) std.textio
write (line,boolean) std.textio
write (line,character,boolean) std.textio
write (line,character) std.textio
write (line,integer,boolean) std.textio
write (line,integer) std.textio
write (line,string,boolean) std.textio
write (line,string) std.textio
read (line,std_ulogic,boolean) ieee.std_logic_textio
read (line,std_ulogic) ieee.std_logic_textio
read (line,std_ulogic_vector,boolean) ieee.std_logic_textio
read (line,std_ulogic_vector) ieee.std_logic_textio
read (line,std_logic_vector,boolean) ieee.std_logic_textio
read (line,std_logic_vector) ieee.std_logic_textio
write (line,std_ulogic,boolean) ieee.std_logic_textio
write (line,std_ulogic) ieee.std_logic_textio
write (line,std_ulogic_vector,boolean) ieee.std_logic_textio
write (line,std_ulogic_vector) ieee.std_logic_textio
write (line,std_logic_vector,boolean) ieee.std_logic_textio
write (line,std_logic_vector) ieee.std_logic_textio
hread ieee.std_logic_textio
示例:
  library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.STD_LOGIC_ARITH.ALL;
  use IEEE.STD_LOGIC_UNSIGNED.ALL;
  use STD.TEXTIO.all;
  use IEEE.STD_LOGIC_TEXTIO.all;
  entity file_support_1 is
     generic (data_width : integer := 4);
     port(clk,sel: in std_logic;
       din: in std_logic_vector (data_width-1 downto 0);
       dout: out std_logic_vector (data_width-1 downto 0));
  end file_support_1;
  architecture behavioral of file_support_1 is
     file results: text is out "test.dat";
     constant base_const: std_logic_vector (data_width-1 downto 0):=conv_std_logic_vector (3, data_width);
     constant new_const: std_logic_vector (data_width-1 downto 0):=base_std+"1000";
   begin
     process(clk)
       variable txtline: LINE;
     begin
         write(txtline,string'("--------------------"));
         write(results,txtline);
         write(txtline,string'("Base Const: "));
         write(results,base_const);
         write(txtline,string'("New Const: "));
         write(results,new_const);
         write(results,txtline);
         write(txtline,string'("--------------------"));
         write(results,txtline);
         if (clk'event and clk='1') then
           if (sel='1') then
             dout <= new_const;
           else
             dout <= din;
           end if;
         end if;
     end process;
  end behavioral;

Copyright@dwenzhao.cn All Rights Reserved   备案号:粤ICP备15026949号
联系邮箱:dwenzhao@163.com  QQ:1608288659