Menu Close

VHDL实体与端口

VHDL设计文件的基本格式一文中谈到实体(entity)是VHDL语言设计的入口部分,特别端口部分是必不可少的。VHDL语言是描述数字集成电路的硬件描述语言,因此在描述集成电路的逻辑行为之前要先定义输入、输出端口。这一部分由实体部分承担。由于entity由参数和端口两个部分组成,本文就entity格式、参数、端口等内容进行详细讲解。

1. 数字电路输入输出到实体的映射

在数字电路设计中,首先要设计输入、输出端口,然后根据需求设计内部数字逻辑。因此在逻辑电路完成之前可以将端口部分看成一个黑盒子,此时只关心该电路那些管脚为输入管脚,那些管脚为输出管脚或双向端口即可,如图1所示。

%title插图%num

图1 数字电路端口

图1描述了一个数字电路的需求。该电路的名称为full_addition, 有3个输入端分别为ci、a 、b,有2个输出端分别为sum和co。输入、输出使用有方向的箭头表示。这是数字电路设计的初步,那么如果用VHDL语言设计,如何将该数字电路的黑盒子映射到VHDL语言的文本描述中呢?首先VHDL语言利用entity定义了参数及输入、输出端口,格式如下:

  • 实体(entity)的声明,
    • 参数(generic),
    • 输入、输出端口描述(in, out,inout,buffer  declaration),

实例如下:

entity top_logic is
generic(
WIDTH_IN: integer:=1;
WIDTH_OUT: integer:=1
);
    port ( a : in  bit_vector(WIDTH_IN-1 downto 0);
           b : in  bit_vector(WIDTH_IN-1 downto 0);
           c : out bit_vector(WIDTH_OUT-1 downto 0)
           );
end top_logic;

从上面的文本描述可以看出,从数字电路的方框图描述到VHDL的文本描述是一个翻译的过程,事实上VHDL设计的目的就是要用文本替代图形设计的方法。特别是利用EDA软件的配合,文本输入更快捷,EDA软件对文本的解析也比图形解析快很多。但由于数字电路经过多年的发展,在图形设计方面已经非常成熟,因此早期的设计思维往往还定格在图形设计的想象空间。VHDL的entity格式定义正是满足这个方面的要求,做到文本输入与图形输入一一对应,相互之间可以映射。

2. 实体语法格式详解

  • 实体(entity)格式
    • 实体名:

一个设计实体无论多大和多复杂 ,在实体中定义的实体名即为这个设计实体的名称。在例化已有元件的调用和连接中,即可以用此名对相应的设计实体进行调用。实体描述由entity  name_of_entity开始,由end name_of _entity结束。其中name_of _entity是entity的名称, 除了VHDL的关键字不能使用外,只要符合VHDL的标识符的命名规则都可以使用,但要求尽量有一定的含义,便于识别和理解。如图1中的full_addition, 从该实体名基本可以知道该实体以及实体所配对的构造体应该是全加器的设计。当然使用full_adder, full_add等也都是相对比较好的实体名称。entity的格式如下:

entity full_addition is           — no semicolon to end, 本行的最后是关键字”is”, 不能有分号

end full_addition;                  — end by semicolon “;”   本行必须以分号结束

         entity 和end 就像一对括号,将entity的内容包装起来。其内部又由泛型(generic)和端口(port) 组成,其中generic是可选部分,需要时可以加入,可以实现参数化设计。

    • 参数部分(generic)

generic提供参数化设置,例如提供参数WIDTH_IN, WIDTH_OUT 等,可以用来设置输入输出端口的位宽等,当然根据需要可以定义其它的参数。WIDTH_IN, WIDTH_OUT为参数名称,只要符合VHDL标识符的命名规则即可。建议使用有一定含义的大写英文单词或首字母缩写以及下划线等组成。

generic (                                   – – key words followed by “(” , no  semicolon is need in the end. 关键字后跟括号,本句不使用分号。
WIDTH_IN: integer:=1;       – – “name of one generic”  +” :”  + “data type”  +” := initial value”+”;”         参数名称+参数类型+ 默认值。 三者之间用冒号”:”隔开。以分号结束。
WIDTH_OUT: integer:=1    – – same as above line except  for no “;” at the end. Since this is the last generic line.  最后一行的结尾没有分号。
);                                                – – right parentheses followed by semicolon to end the generic. 右括号及分号结束generic。

                     注意参数在声明时的格式。参数一般使用整形(integer),布尔(Boolean)类型,在仿真时亦可以使用实型(real),时间类型(time)等参数。关于数据类型请阅读数据类型相关章节内容。

    • 端口(port)
      • 端口书写格式

端口描述输入、输出。由关键字port引导,括号内定义输入、输出。VHDL对于空格以及空行的使用相对宽松,只要不引起混淆,可以插入空格和空行,以提高程序的可读性。如下面的几段书写方式是相同的。

(1)
 port ( a : in bit;
        b : in bit;
        c : out bit
      );
(2) 
 port 
( a : in bit;
  b : in bit;
  c : out bit
);

(3)

port 
( 
  a : in bit;
  b : in bit;
  c : out bit
);

(4)
port ( a : in bit; b : in bit; c : out bit );

 

      • 端口类型

端口类型一般由如下几种: bit, Boolean, integer, bit_vector,  std_logic,  std_logic_vector等几种。其中bit, Boolean, integer ,bit_vector等是VHDL的内置类型,不需要引用其它的库就可以使用。但std_logic,std_logic_vector 等类型是封装在IEEE库中的,以封装包的方式提供,因此要使用std_logic类型,需要在entity之前引用和打开包含该类型的库文件,如:

 

library ieee;
use ieee.std_logic_1164.all;
entity std_logic_top is
generic(
WIDTH_IN: integer:=1;
WIDTH_OUT: integer:=1
);
    port 
    ( 
    a : in std_logic_vector(WIDTH_IN-1 downto 0);    
    b : in std_logic_vector(WIDTH_IN-1 downto 0);
    c : out std_logic_vector(WIDTH_OUT-1 downto 0)
     );
end std_logic_top;
    •  端口方向

端口方向有五种分别为: in, out, inout, buffer, linkage。 这五种端口方向的特性及使用见表2

注释
In Read only 只读 Read only within this entity.

本实体内只读,是输入信号

out updated 只更新(写) Only can be updated within this entity.

本实体只输出(写),不能回读

Inout Read  and updated 读/写 Read and updated, but the read and updated can not be simultaneously, time duplex mode.

读/写分时复用,不能同时进行读写

buffer Read and updated 更新(写)/回读 More like out direction mode, yet there is a buffer, through buffer the signal can be read back

像out端口一样可以更新,同时又能回读,回读更新过的内容。

linkage 方向不定 可读、可写 可读可写,但实体之间的方向模式应匹配。但需要在interface中使用。

out与buffer的区别是, out对应是芯片的输出管脚, 在本实体中不能读取,即不能再直接使用该管脚作为输入。但buffer则可以作为输出,同时又可以作为本实体模块内的输入参与运算。比较下面两端代码就可以看出差别;

---------code (1)
entity top_logic is
generic(
WIDTH_IN: integer:=1;
WIDTH_OUT: integer:=1
);
    port 
    ( 
    a  : in bit_vector(0 to WIDTH_IN-1);    
    b  : in bit_vector(WIDTH_IN-1 downto 0);
    m  : in bit_vector(WIDTH_IN-1 downto 0);
    c  : buffer bit_vector(WIDTH_OUT-1 downto 0);
    d  : out bit_vector(WIDTH_OUT-1 downto 0)
     );
end top_logic;

architecture Behavioral of top_logic is
--signal      declaretion 
--component   declaretion 
begin
 
  c<=a and b ;
  d<=m and c;

end Behavioral;



----code (2)
entity top_logic is
generic(
WIDTH_IN: integer:=1;
WIDTH_OUT: integer:=1
);
    port 
    ( 
    a  : in bit_vector(0 to WIDTH_IN-1);    
    b  : in bit_vector(WIDTH_IN-1 downto 0);
    m  : in bit_vector(WIDTH_IN-1 downto 0);
    c  : out bit_vector(WIDTH_OUT-1 downto 0);
    d  : out bit_vector(WIDTH_OUT-1 downto 0)
     );
end top_logic;

architecture Behavioral of top_logic is
--signal      declaretion 
--component   declaretion 
begin
 
  c<=a and b ;
  d<=m and c;

end Behavioral;

上面两端代码中,代码(1)是可综合的代码,综合后可以形成电路,而代码(2)是不可综合的,在综合代码(2),Vivado报出如下错误类型。

%title插图%num

图2

3. 代码实战

根据以上内容介绍,完成图1中数字电路到VHDL entity代码转换。

entity full_addition is

    port 
    ( 
    ci   : in bit;
    a    : in bit;    
    b    : in bit;
    sum  : out bit;
    co  :  out bit
     );
end full_addition;

上面的代码以简单的方式实现了从数字电路的输入、输出到实体对应的输入、输出端口的转换。实现了用VHDL语言描述电路的第一步。关于电路行为的描述见VHDL构造体部分内容。

 

 

 

 

 

 

 

 

 

 

 

 

Posted in FPGA, FPGA 教材教案, IC, IC 教材教案, VHDL, Vivado, 开发工具, 开发语言, 教材与教案, 文章

发表回复

相关链接