FPGA基础回顾:从架构到开发流程

各位同学,今天我们聊聊FPGA的基础。说实话,这部分内容看起来简单,但很多坑都藏在这些基础里。我在做硬件加速卡的时候,就吃过不少亏。今天我把这些经验掰开揉碎了讲给你听。

FPGA架构:到底长什么样?

FPGA的全称是现场可编程门阵列。说白了,它就是一盒乐高积木。你买回来的时候,里面全是散件。你想搭成什么,完全由你说了算。

一个典型的FPGA芯片,内部包含三大块:

  • 可编程逻辑块——这是核心,负责实现你的逻辑功能
  • 可编程互连资源——相当于高速公路,把各个模块连起来
  • 可编程I/O块——负责和外界打交道

我刚开始接触FPGA时,总觉得它和CPU差不多。后来才发现,完全不是一回事。CPU是固定架构,你只能写软件。FPGA呢?你可以重新定义硬件本身。这个区别,决定了硬件加速的底层逻辑。

核心理解:FPGA不是处理器,它是可重构的硬件。你写的不是程序,是电路。

FPGA 芯片内部架构 可编程 I/O 块(四周环绕) 逻辑块 逻辑块 逻辑块 可编程互连 BRAM DSP PLL 嵌入式硬核:BRAM、DSP、PLL 等

查找表(LUT)与触发器(FF):FPGA的细胞

FPGA里最小的逻辑单元是什么?就是LUT和FF。这两个东西,你天天都要打交道。

查找表(LUT)

LUT的全称是Look-Up Table,查找表。它本质上是一块小型的RAM。你输入几个信号,它查一下表,输出结果。

举个例子,一个4输入的LUT,可以存储16种组合的结果。你想实现任何4输入的逻辑函数,一个LUT就够了。

我的经验:在行情加速卡里,我们经常用LUT来实现比较器、状态机。但要注意,LUT不是无限的。一个中等规模的FPGA,LUT数量也就几万到几十万。设计时心里要有数。

触发器(FF)

触发器负责存储状态。它只有一个bit,但可以记住上一个时钟周期的值。没有FF,你就没法做流水线,没法做状态机。

我见过不少新手,写Verilog时忘了加寄存器。结果综合出来一堆组合逻辑,时序一塌糊涂。嗯,这里要注意:每个always块里,敏感列表一定要写对

// 正确的写法:带触发器的寄存器
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        data_out <= 8'b0;
    else if (en)
        data_out <= data_in;
end

// 错误的写法:没有触发器,纯组合逻辑
always @(*) begin
    data_out = data_in;  // 这只是一个连线
end

避坑指南:我曾经在做一个高频交易加速卡时,因为漏写了一个posedge clk,导致整个模块变成了组合逻辑。仿真没问题,上板就跑飞。查了整整两天才找到原因。从那以后,我写always块第一件事就是检查敏感列表。

可编程互连资源:别让连线成为瓶颈

逻辑块再强,连不起来也是白搭。FPGA内部有丰富的互连资源,包括:

  • 局部互连——逻辑块之间的短连线,延迟低
  • 全局互连——跨区域的長连线,用于时钟、复位等全局信号
  • DSP/BRAM专用互连——硬核之间的高速通道

做硬件加速时,互连资源往往是瓶颈。你想想看,行情数据每秒几百万笔,每个数据都要从I/O送到处理单元。如果互连不够宽,或者延迟太大,整个系统就卡住了。

我个人的习惯是:先规划数据流,再分配逻辑资源。数据怎么走,决定了互连怎么用。别等到布局布线完了才发现,关键路径上绕了一大圈。

FPGA开发流程:从代码到比特流

开发FPGA,不是写完代码就完事了。完整的流程是这样的:

  1. 设计输入——写Verilog/VHDL,或者用HLS
  2. 功能仿真——验证逻辑对不对
  3. 综合——把RTL代码转成网表
  4. 布局布线——把网表映射到实际的LUT和FF上
  5. 时序仿真——带上延迟信息再仿真一次
  6. 静态时序分析——检查能不能跑到目标频率
  7. 生成比特流——下载到FPGA

这里面,最容易出问题的是综合和布局布线。我见过有人仿真跑得好好的,综合完就变了。为什么?因为综合工具会优化你的代码。你写的逻辑,它可能给你换一种实现方式。

关键提醒:写代码时就要想着硬件。别把FPGA当软件写。你写的每一行代码,最终都会变成实实在在的电路。

举个例子,在行情加速卡里,我们经常用流水线来提高吞吐量。但流水线级数多了,资源消耗也大。这时候就要权衡:是要更高的频率,还是要更低的延迟?

// 流水线示例:3级流水线加法器
always @(posedge clk) begin
    pipe1 <= a + b;      // 第一级
    pipe2 <= pipe1 + c;  // 第二级
    result <= pipe2 + d; // 第三级
end

这段代码综合后,会生成3级寄存器。每级之间是组合逻辑。这样时钟频率可以跑得很高,但输出会延迟3个时钟周期。在行情加速场景里,延迟很敏感。有时候我们宁愿频率低一点,也要减少流水线级数。

设计目标 流水线策略 典型场景
高吞吐量 多级流水线 数据包处理、视频处理
低延迟 少级流水线或组合逻辑 行情解析、高频交易
低功耗 门控时钟、减少翻转 物联网、边缘计算

好了,FPGA基础就回顾到这里。这些内容看似简单,但都是后面做硬件加速卡的基石。你把这些搞透了,后面学起来就顺了。

一个小建议:初学者别急着上板。先在仿真里把逻辑调通,把时序看明白。仿真过了,上板基本不会有大问题。我当年就是太心急,结果烧坏了两块开发板……嗯,都是学费。

专注资料整理