Menu Close

VHDL 语言数据类型概述

在数据对象的声明章节中可以看到,信号和变量的声明都跟着具体的数据类型,也就是数据对象不是抽象的,而是与具体的数据类型相结合的。那么在VHDL语言中有那些数据类型呢?由于VHDL语言是电路的描述,除了类似计算机语言的数据类型外,还有时间类型,物理类型等。下面就VHDL语言的数据类型,使用规则及应用场景进行探讨。

1. VHDL语言类型强度

VHDL 是一种非常强的类型语言 ,对运算关系与赋值关系中各量(操作数)的数据类型有严格要求。 VHDL 要求设计实体中的每一个常数, 信号, 变量, 函数以及设定的各种参量都必须具有确定的数据类型, 并且相同数据类型的量才能互相传递和运算。如bit类型只能与bit类型进行运算和赋值,即使与之相近的std_logic类型也不能直接与bit类型进行运算。相同类型的数据,如果数据宽度不同多数运算符也不支持直接运算。VHDL 作为强类型语言的好处是使VHDL编译或综合工具很容易地找出设计中的各种常见错误,避免了因为设计疏忽,遗漏,多义性等结果。因此可以说VHDL语言的数据类型及使用规则是极其严谨。当然任何事都有利弊,严谨性使设计结果可靠,减少了不确定错误的调试时间。但这样也往往给使用者带来了一定程度上困难,特别使初学者在学习了一段时间后,还不能写出可综合的,可应用的VHDL语言的工程代码,总会觉得有挫败感,VHDL语言学习曲线的初始比较陡,但经过一段时间的学习与练习,掌握了规则后,会发现后面的学习和使用都会变得很容易。 VHDL中的各种预定义数据类型大多数体现了硬件电路的不同特性 ,因此也为其它大多数硬件描述语言所采纳 。如 BIT 可以描述电路中的开关信号,在system verilog中也有相同的数据类型,只是使用规则不同。

2. VHDL语言具体数据类型

VHDL 中的数据类型可以分成四大类

  • 标量型(Scalar Type)

标量型 是单元素的最基本的数据类型, 即不可能再有更细小、 更基本的数据类型 。它们通常用于描述一个单值数据对象。标量类型包括:

    • 实数类型(real)

实数类型的数据只能用于仿真,不能用于综合。real是VHDL的基本类型,在standard库中有定义,可以直接使用。其表达范围为:-1.7014111e+308 to 1.7014111e+308;实数类型在standard库中定义如下:

type real is range -1.7014111e+308 to 1.7014111e+308;

实数据类型在MATH_REAL的库中定义更多的操作方式,但必须在代码中的实体声明之前包含 use ieee.math_real.all; 语句。

    • 整数类型(integer)

整形也是standard库中定义的数据类型,其范围-2147483647 ~ 2147483647,其定义格式如下:

type integer is range -2147483647 to 2147483647;

    • 枚举类型(enumeration)

Enumeration 类型是是通过显式列出(枚举)可能的值来定义的。此类型值由枚举文字(标识符或字符文字)表示。由关键字type引导,其定义格式如下:

type type_name is (type_element, type_element, …);

           枚举类型的顺序是从左到右的方式索引,所以枚举类型如果没有赋值,则默认值为左边的第一个值。如:在standard的数据包中定义了bit类型如下:

                          type BIT is (‘0’, ‘1’);

                      可见bit类型也是标准的枚举类型,只是在standard的库中预定义而已。当数据对象使用bit类型声明时,如果没有赋值,则默认为‘0’。

                         例1: 观察enumeation类型的赋值及未赋值变量使用情况

entity enum_tb is
end entity;
 
architecture sim of enum_tb is
    signal Sig1 : bit :='1';
    signal Sig2 : bit ;
    signal sig3 : bit;
    signal sig4 : bit;
begin
   sig3<=Sig1;
   sig4<=sig4;
   
end architecture;

例1在Vivado下仿真波形如图1所示,

%title插图%num

图1

枚举类型应用非常广泛,不仅各个程序包中在使用,在许多应用中可以根据需要自定各种枚举类型。

    •  时间类型

时间类型定义时间类型time, time类型不仅含有数字表示大小,还有时间单位用于表达清晰的时间概念,time也是在standard库中预定义的,见VHDL的预定义数据类型中的详细介绍。

以上仅介绍了常用的4种类型,还有许多其它的基本数据类型,都是通过type 或subtype定义的,并分散的各个库文件中,将在库和数据包章节介绍。

  •  复合类型(Composite Type)
    复合类型可以由细小的数据类型复合而成, 如可由标量型复合而成 。复合类型主要有

    • 数组型(Array)

数组类型可以由以上三种基本类型组成数组,称为矢量类型如bit_vector, std_logic_vector等

    • 记录型(Record)

VHDL 中的 记录类型(Record )类似于 C 中的结构体(structure)。记录类型最常用于定义新的 VHDL 类型。这种新类型包含用户想要的任何已定义的类型的组合。大多数情况下,这用于简化接口。这对于具有大量相同的信号的接口使用非常方便。例如,与片外存储器的接口可能很大,并且在整个设计中一遍又一遍地具有相同的信号。记录可用于缩小代码大小并减少实体中需要维护的信号。设计者只需在单个包文件中定义记录类型,然后将包文件用于任何使用该记录类型的实体。

  例2:在一个包文件 (example_record_pkg.vhd) 中创建了两种记录类型。这些类型在 example_record.vhd 中用于简化 FIFO 接口。为来自 FIFO 的所有输入创建一个 t_FROM_FIFO 类型的信号,并为 FIFO 的所有输出创建一个类型为 t_TO_FIFO 的单独信号。

(1) package 文件

library ieee;
use ieee.std_logic_1164.all;
 
package example_record_pkg is
 
  -- Outputs from the FIFO.
  type t_FROM_FIFO is record
    wr_full  : std_logic;                -- FIFO Full Flag
    rd_empty : std_logic;                -- FIFO Empty Flag
    rd_dv    : std_logic;
    rd_data  : std_logic_vector(7 downto 0);
  end record t_FROM_FIFO;  
 
  -- Inputs to the FIFO.
  type t_TO_FIFO is record
    wr_en    : std_logic;
    wr_data  : std_logic_vector(7 downto 0);
    rd_en    : std_logic;
  end record t_TO_FIFO;
 
  constant c_FROM_FIFO_INIT : t_FROM_FIFO := (wr_full => '0',
                                              rd_empty => '1',
                                              rd_dv => '0',
                                              rd_data => (others => '0'));
 
  constant c_TO_FIFO_INIT : t_TO_FIFO := (wr_en => '0',
                                          wr_data => (others => '0'),
                                          rd_en => '0');
   
   
end package example_record_pkg;

(2)package,record 的引用和使用

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
use work.example_record_pkg.all; -- USING PACKAGE HERE!
 
entity example_record is
  port (
    i_clk  : in  std_logic;
    i_fifo : in  t_FROM_FIFO;
    o_fifo : out t_TO_FIFO := c_TO_FIFO_INIT  -- intialize output record
    );
end example_record;
 
architecture behave of example_record is
 
  signal r_WR_DATA : unsigned(7 downto 0) := (others => '0');
   
begin
 
  -- Handles writes to the FIFO
  p_FIFO_WR : process (i_clk) is
  begin
    if rising_edge(i_clk) then
      if i_fifo.wr_full = '0' then
        o_fifo.wr_en   <= '1';
        o_fifo.wr_data <= std_logic_vector(r_WR_DATA + 1);
      end if;
    end if;
  end process p_FIFO_WR;
   
  -- Handles reads from the FIFO
  p_FIFO_RD : process (i_clk) is
  begin
    if rising_edge(i_clk) then
      if i_fifo.rd_empty = '0' then
        o_fifo.rd_en <= '1';
      end if;
    end if;
  end process p_FIFO_RD;
   
end behave;

 

  •  存取类型(Access Type)
    为给定的数据类型的数据对象提供存取方式。细节在后续章节中介绍。
  •  文件类型(Files Type)
    用于提供多值存取类型。细节在后续章节中介绍。

这四大数据类型又可分为预定义数据类型和用户自定义数据类型两大类别。预定义的VHDL 数据类型是VHDL 最常用 、最基本的数据类型。这些数据类型都已在 VHDL 的标准程序包 STANDARD、 STD_LOGIC_1164以 及其它的标准程序包中作了定义, 并可在设计中随时调用。
如上所述 除了标准的预定义数据类型外, VHDL 还允许用户自定义其它的数据类型以及子类型。 通常新定义的数据类型和子类型的基本元素一般仍属VHDL 的预定义数据类型。 尽管 VHDL 仿真器支持所有的数据类型 ,但 VHDL 综合器并不支持所有的预定义数据类型和用户定义的数据类型 ,如 REAL 、TIME 、FILE 等数据类型 在综合中, 它们将被忽略或干脆报出语法错误,停止编译。 这意味着 ,不是所有的数据类型都能在目前的数字系统硬件中实现 ,由于在综合后, 所有进入综合的数据类型都转换成二进制类型和高阻态类型(只有部分芯片支持内部高阻态) 即电路网表中的二进制信号 ,综合器通常忽略不能综合的数据类型 并给出警告信息。

3. 数据类型的引用与使用

在Vhdl语言中,所有的类型在使用之前都是预先定义的。包括bit,bit_vector, integer,real等,但在引用和使用这些类型是既没有看到引用,也没有看大如何定义的,为什么可以直接使用呢?由于在VHDL的组织结构中,在standard包中定义的数据类型,以作为VHDL的基本类型被使用,因此可以省略对standard库的引用,对该库的数据类型可以直接使用,VHDL的EDA 工具也直接支持该库的编译和仿真。

Posted in FPGA, FPGA 教材教案, IC, VHDL, VHDL, 开发语言, 教材与教案, 文章, 编程语言

发表回复

相关链接