跳转到内容

可编程逻辑/VHDL 模块结构

来自维基教科书,开放的书籍,开放的世界

模块结构概述

[编辑 | 编辑源代码]

创建模型有两种方法:自顶向下和自底向上。模型也可以定义到不同的详细程度。

作为一种建模语言,VHDL 提供了丰富多样的结构来适应建模中使用的各种方法和详细程度。其中包括:实体、体系结构、包和库。

这里的信号用于将数据通过实现的不同阶段进行传播。有时这些信号用于实例化我们在设计中使用的组件。它们的行为就像一个用于传播数据的路线图。

 variable variable_name : type;
 variable variable_name : type := initial_value;

规则和示例

[编辑 | 编辑源代码]
variable HEIGHT : integer := 8;
variable COND : boolean := true;
variable IN_STRING : string(1 to 80);
variable M,N : bit := '1';
variable I : integer range 0 to 3;

在声明变量时,可以为其赋予显式的初始值。如果未为变量赋予显式值,其默认值将为其声明类型的最左侧值('left)。

variable I : integer range 0 to 3;
-- initial value of I is 0
variable X : std_ulogic;
-- initial value of X is 'U'

子程序(函数和过程)中的变量在每次调用子程序时都会被初始化。

function PARITY (X : std_ulogic_vector)
                 return std_ulogic is
  variable TMP : std_ulogic := '0';
begin
    for J in X'range loop
        TMP := TMP xor X(J);
    end loop; --no need to initialise TMP
    return TMP;
end PARITY;

进程中的变量,除了“FOR LOOP”变量,都会在模拟开始时(时间 = 0 ns)接收到其初始值。

process (A)
    variable TMP : std_ulogic := '0';
begin
    TMP := '0';
    -- in this example we need to reset
    -- TMP to '0' each time the process 
    -- is activated
    for I in A'low to A'high loop
        TMP := TMP xor A(I);
    end loop;
    ODD <= TMP;
end process;

SFC

标量数据类型

[编辑 | 编辑源代码]

复合数据类型

[编辑 | 编辑源代码]

实体用于描述 VHDL 模块与其他模块的接口。所有进入或退出 VHDL 模块的信号都必须在实体声明中声明。下面是一个描述两个输入 AND 门接口的实体示例。

ENTITY and2 IS
    PORT(A : in std_logic;
         B : in std_logic;
         F : out std_logic
	);
END and2;

在实体内部,可以找到一个端口声明。有以下几种类型的端口

类型 描述
in 指定一个只能读取不能写入的端口。in 端口不能用在赋值左侧。
out 指定一个只能写入不能读取的端口。out 端口只能用在赋值左侧。
in/out 指定一个可以读写端口。inout 端口通常用于描述三态总线。
buffer 指定一个 out 端口,其当前值可以读取。可以通过将内部信号分配给 VHDL 代码中的内部信号来实现相同的功能,并在需要时从该信号读取,并使用并发语句将内部信号分配给 out 端口。

体系结构

[编辑 | 编辑源代码]

VHDL 中的体系结构描述了模块功能的实现方式。以下是两个输入 AND 门的体系结构。

ARCHITECTURE and2_rtl OF and2 IS
  -- Signal, component, type and constant declarations go here.
  ...
BEGIN
  -- Concurrent statements and processes go here
  F <= A and B;
  ...
END and2_rtl;

体系结构实现类型

[编辑 | 编辑源代码]

体系结构的实现方式可以根据其目的进行不同的方式。

结构实现连接和实例化其他模块。它用于组织和连接模块。严格的结构实现仅包含使用端口映射连接在一起的其他实例化块。

行为实现使用可用的全部 VHDL 结构描述了模块的运行方式。行为设计模块不一定是可综合的,但对于建模和测试可综合模块很有用。

寄存器传输

[编辑 | 编辑源代码]

寄存器传输实现根据寄存器和寄存器之间数据流的转换来描述模块的功能。寄存器传输实现通常用于描述要在实际设备上综合的模块。

VHDL 包用于包含一组可重用的数据类型、函数、过程和其他 VHDL 结构。包的基本语法如下。

PACKAGE package_name IS
...
END package_name;

PACKAGE BODY package_name IS
...
END package_name;

包头用于声明 VHDL 结构。包体用于实现它们。并非所有结构(如数据类型)都需要在主体中进行条目。主体通常用于函数和过程的实现。

库为模块的生存提供命名空间。当由模拟器或综合工具编译时,每个包和实体都被编译到一个库中。VHDL 文件无法指定要将其编译到哪个库中。这由用于编译 VHDL 代码的工具决定。工具将 VHDL 对象编译到的默认库称为工作库。这意味着在创建 VHDL 模型时,以下语句会被假设。

library work;

VHDL 模型可以使用 library 关键字使库对模块可见,并使用库中的对象。 这对于包含来自其他库的包以及直接实例化来自其他库的实体是必需的。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

library 关键字使库对 VHDL 设计可见。 库可见后,就可以使用库中的包。 下一行表示在当前命名空间中声明 ieee.std_logic_1164 命名空间中声明的所有内容。 例如,这允许我们使用以下语句

signal sQ: std_logic;

而不是

signal sQ: ieee.std_logic_1164.std_logic;

VHDL 模块的实例化

[编辑 | 编辑源代码]

有两种方法可以实例化 VHDL 模块。 VHDL '87 中指定的方法使用组件、端口映射和相应的实体声明。 VHDL '93 中指定的新方法只使用端口映射和相应的实体声明。 每个方法在某些情况下都有用。 对于每种方法,将实例化以下实体

entity D_FF is
    port(
        clk : out std_logic;
        rst : out std_logic;
        D : in std_logic;
        Q : in std_logic
        );
end entity D_FF;

architecture rtl of D_FF is
  ...
begin
  ...
end architecture rtl;

使用组件

[编辑 | 编辑源代码]
architecture rtl of uses_d_ff is
  ...
  component D_FF is
    port(
        clk : out std_logic;
        rst : out std_logic;
        D : in std_logic;
        Q : in std_logic
        );
  end component D_FF;
  ...
  signal sClk: std_logic;
  signal sRst: std_logic;
  signal sD:   std_logic;
  signal sQ:   std_logic;
  ...
begin
  u_D_FF: component D_FF
    port map(
        clk => sClk,
        rst => sRst,
        D   => sD,
        Q   => sQ
    );
  
  ...
end architecture rtl;

不使用组件

[编辑 | 编辑源代码]

不使用组件可以缩短语法。 为了实例化上面的 D_FF,使用以下代码

architecture rtl of uses_d_ff is
  ...
  signal sClk: std_logic;
  signal sRst: std_logic;
  signal sD:   std_logic;
  signal sQ:   std_logic;
  ...
begin
  u_D_FF: entity work.D_FF(rtl)
    port map(
        clk => sClk,
        rst => sRst,
        D   => sD,
        Q   => sQ
    );
  
  ...
end architecture rtl;

只要使用的工具支持这种语法,不使用组件是推荐的,因为它可以提高代码的可维护性。 当信号被添加/删除和从实体中删除时,它们只需要被添加到实体声明和端口映射中,或从其中删除。 当实例化的对象没有 VHDL 模块时,组件很有用。 当在 VHDL 中实例化 Verilog 设计或使用 IP 核时,有时需要这样做。 这允许 VHDL 编译器在编译 VHDL 时创建一个“黑盒”,并稍后将实际模型连接到黑盒。

华夏公益教科书