**这是本文档旧的修订版!**

FPGA设计过程

在这篇文章中,我们将更详细地讨论FPGA的设计过程。这包括对设计过程的所有主要阶段的讨论——设计架构、FPGA设计建模和测试我们的设计。我们还研究了两种主要硬件描述语言(HDL)之间的区别——Verilog和VHDL。 在本系列的前一篇文章中,我们对整个FPGA开发过程进行了概述。 从这里我们看到了FPGA项目中涉及的三个主要过程——设计、验证和实现。 在接下来的文章中,我们将讨论构成设计过程的任务。 虽然这里的主要任务是编写代码来创建模型,但这个过程还有其他重要的方面。这包括构建我们的芯片和测试我们的模型。 我们将在单独的文章中更详细地讨论FPGA的实现过程和FPGA验证。

1. 架构设计

设计过程的第一阶段是构建我们的设计。 这涉及到将设计分解成许多更小的块,以简化VHDL编码过程。 对于大型设计,这是特别有益的,因为它允许工程师并行工作。 在这种情况下,我们应该认为这是整个过程的一个组成部分。 对于较小的项目,我们不需要正式执行这个步骤。然而,在开始详细的设计工作之前,总是值得仔细考虑架构。

2. 模型设计

该过程的下一个阶段是创建设计模型。我们使用这个模型来模拟我们的设计行为,并为我们的FPGA构建一个编程文件。 我们通常使用两种主要的硬件描述语言(HDL)之一——verilog或VHDL——来编写这个模型。 我们在这个过程中使用了两种主要的建模风格。这些通常被称为寄存器传输级别(RTL)和门级别。 让我们更详细地看看这两者。

3. RTL编码风格

使用RTL方法的设计包括描述FPGA内寄存器之间的数据流的代码。 这意味着我们要编写代码,明确地描述FPGA在触发器、逻辑门、有限状态机和RAM方面的行为。 让我们考虑下面的示例电路来演示这个概念。 dffdff_example.png 在这个电路的RTL模型中,我们将编写代码来描述两个D型触发器和非门的行为。 下面的代码给出了该电路的VHDL实现。如果语法不熟悉,请不要担心,因为它并不重要。

dff1_d <= not dff2_q;
dff1:
process (clock) is
begin
  if rising_edge(clock) then
    dff1_q <= dff1_d;
  end if;
end process dff1;
dff2:
process (clock) is
begin
  if rising_edge(clock) then
    dff2_q <= dff1_q;
  end ill
end process dff2;

在这段代码中,第一行模拟非门的行为。 标签为dff1和dff2的触发器使用VHDL过程建模。 当时钟上有上升沿时,这些进程锁存输入的值。这与D类型触发器的预期行为相匹配。 从这个例子中,我们可以看到我们是如何描述设计中组件的行为的,以及它们之间的相互连接。 这是RTL建模的定义特性,而其他类型的建模只是简单地定义组件之间的连接。

4. 门级模型

门级建模由代码组成,这些代码定义了不同预先存在的组件的互连。 这些组件是集成FPGA元素的实例,如pll、查找表(LUT)或寄存器单元。 下面显示的代码是门级建模的一个例子。这实现了我们之前考虑过的相同的双触发器电路。

inverter : component not_gate
  port map (
    inv_in  => dff2_q,
    inv_out => dff1_d
  );
dff1 : component dff
  port map (
    clock => clock,
    D     => dff1_d,
    Q     => dff1_q,
    Q_bar => open
  );
 
dff2 : component dff
  port map (
    clock => clock,
    D     => dff1_q,
    Q     => dff2_q,
    Q_bar => open
  );