🧩 第1课:FPGA是什么

揭开可编程芯片的神秘面纱——你的代码就是电路!

🏆 成就:LUT大师 ✅ Verilator验证

🧩
LUT大师
理解LUT查找表 + 触发器FF + 可编程布线 — FPGA的三大核心

🤔 FPGA到底是个啥?

FPGA的全称是 Field-Programmable Gate Array(现场可编程门阵列)。关键词在"现场可编程"——你不需要去工厂定制芯片,在办公桌上就能重新定义芯片的功能!

想象一块空白的乐高底板。CPU是预先拼好的乐高城堡——你可以往里放不同的玩具(软件),但城堡结构不能改。FPGA就是那块空白底板——你每次都能拼出完全不同的城堡!

🏗️ FPGA内部三大核心

1️⃣ LUT(Look-Up Table)— 查找表,万能逻辑

LUT是FPGA最核心的单元。一个N输入LUT就是一个 2^N × 1位的RAM,任何N输入的逻辑函数都可以用查表来实现!

4输入LUT原理: A ──┐ B ──┤ ┌───┐ ┌──────────┐ C ──┼──┤MUX├──────┤ 输出 Y │ D ──┘ └───┘ └──────────┘ ↑ ┌────┴────┐ │ 16×1 RAM│ ← 存储真值表 │ [0]=0 │ ABCD=0000 → 0 │ [1]=1 │ ABCD=0001 → 1 │ [15]=0 │ ABCD=1111 → 0 └─────────┘ 例:Y = A AND B AND C AND D → 只需把真值表写入RAM即可! 不需要AND门,查表就完事了!

一个4输入LUT可以实现 65536种 不同的逻辑函数!这就是LUT的威力——它是"万能逻辑门"。

2️⃣ FF(Flip-Flop)— 触发器,记住状态

LUT只能做组合逻辑。FF(D触发器)在每个时钟上升沿锁存数据,实现计数器、状态机等时序电路。

3️⃣ 可编程布线 — 连接一切

FPGA内部有海量的可编程开关矩阵,像铁路道岔一样连接各个CLB(Configurable Logic Block = LUT + FF)。

📝 Verilator实践:仿真一个LUT

Veriloglut4.v — 4输入查找表
module lut4 (
    input  wire [3:0]  addr,      // 4位地址输入
    input  wire [15:0] init_val,  // 16位真值表
    output wire y             // 查表输出
);
    // LUT就是一个16×1的RAM
    assign y = init_val[addr];
endmodule

就这么简单!init_val[addr]——用输入当地址,查表输出。修改init_val就能改变逻辑功能,这就是FPGA"可编程"的本质!

💡 关键理解:LUT不是在"计算"逻辑,而是在"查表"。这就是FPGA为什么叫"可编程"——改写RAM内容就能改变逻辑功能!

🧠 概念检查清单

✅ LUT为什么能实现任意逻辑函数?
✅ 为什么LUT就是一个小RAM?
✅ FF在FPGA中起什么作用?
✅ FPGA和CPU的根本区别是什么?
✅ 为什么同一个FPGA芯片可以反复重编程?

📝 完整Verilator测试台

SystemVeriloglut4_tb.sv — LUT4完整验证
module lut4_tb;
    logic [3:0]  addr;
    logic [15:0] init_val;
    logic        y;
    lut4 uut(.*);

    task test_and;
        begin
            $display("--- 测试1: 4输入AND门 ---");
            init_val = 16'h0001;
            for(int i=0;i<16;i++) begin
                addr=i; #10;
                if(y!==(i==15))
                    $display("  FAIL: addr=%b, y=%b", addr, y);
            end
            addr=4'b1111; #10;
            $display("  addr=1111, y=%b (应为1) ✓", y);
        end
    endtask

    task test_xor;
        begin
            $display("--- 测试2: 4输入XOR门 (奇校验) ---");
            init_val = 16'h9669;
            for(int i=0;i<16;i++) begin
                addr=i; #10;
                logic expected = ^addr;
                if(y!==expected)
                    $display("  FAIL: addr=%b, y=%b, exp=%b", addr, y, expected);
            end
            $display("  XOR测试通过 ✓");
        end
    endtask

    task test_mux;
        begin
            $display("--- 测试3: 2:1 MUX (A?B:C) ---");
            init_val = 16'h00CC;
            for(int i=0;i<16;i++) begin
                addr=i; #10;
                logic expected = addr[3] ? addr[1] : addr[2];
                if(y!==expected)
                    $display("  FAIL: addr=%b, y=%b, exp=%b", addr, y, expected);
            end
            $display("  MUX测试通过 ✓");
        end
    endtask

    task test_or;
        begin
            $display("--- 测试4: 4输入OR门 ---");
            init_val = 16'hFFFE; // 只有0000→0
            for(int i=0;i<16;i++) begin
                addr=i; #10;
                if(y!==(i!=0))
                    $display("  FAIL: addr=%b, y=%b", addr, y);
            end
            $display("  OR测试通过 ✓");
        end
    endtask

    initial begin
        $dumpfile("lut4.vcd"); $dumpvars(0, lut4_tb);
        $display("==============================");
        $display("  LUT4 查找表功能验证");
        $display("==============================");
        test_and; test_xor; test_mux; test_or;
        $display("==============================");
        $display("  所有测试通过!LUT就是查表!");
        $display("==============================");
        #100; $finish;
    end
endmodule

🔬 CLB完整结构图

CLB (Configurable Logic Block) ┌──────────────────────────────────────────────┐ │ ┌─────────┐ ┌─────────┐ │ │ │ LUT1 │ │ LUT2 │ ← 2个4-LUT │ │ │ (4输入) │ │ (4输入) │ │ │ └────┬────┘ └────┬────┘ │ │ │ │ │ │ ┌────▼────┐ ┌────▼────┐ │ │ │ DFF1 │ │ DFF2 │ ← 2个触发器 │ │ │ Q1 │ │ Q2 │ │ │ └────┬────┘ └────┬────┘ │ │ └──────┬──────┘ │ │ ┌────▼────┐ │ │ │ MUX │ ← 选择组合/时序输出 │ │ │ 输出 │ │ │ └────┬────┘ │ │ │ │ │ 连接到布线矩阵 → 其他CLB │ └──────────────────────────────────────────────┘ 现代FPGA的CLB还包含: • 进位链 (Carry Chain) — 快速加法器 • 多路复用器 (MUX) — 大扇入逻辑 • 分布式RAM — LUT可配为小RAM • 移位寄存器 — SRL16/SRL32 代表芯片CLB数量: Xilinx Artix-7 XC7A35T ≈ 5,000 CLB Xilinx Kintex-7 XC7K70T ≈ 12,000 CLB Xilinx UltraScale+ VU9P ≈ 500,000 CLB

📊 FPGA vs ASIC vs CPU 全对比

特性CPU/GPUFPGAASIC
灵活性★★★★★ 软件★★★★ 硬件可重配★ 固化
性能★★ 通用受限★★★★ 专用高效★★★★★
延迟μs~msns级ns级
功耗中等最低
开发成本中等极高
上市时间较快慢(18月+)
代表应用电脑手机通信/AI矿机

🌍 FPGA应用领域(2024-2025热门)

1. AI推理加速 — 低延迟,LUT天然适合位操作

2. 5G/6G通信 — 实时信号处理,协议栈硬件化

3. 视频处理 — 实时4K/8K编解码,视频叠加

4. 金融量化 — 纳秒级交易,FPGA直连交易所

5. 汽车电子 — 自动驾驶传感器融合

6. 数据中心 — SmartNIC,可编程网络

7. 航天军工 — 辐射加固FPGA,太空计算

📊 FPGA vs ASIC vs CPU 对比

特性CPU/GPUFPGAASIC
灵活性★★★★★ 软件★★★★ 硬件可重配★ 固化不可改
性能★★ 通用受限★★★★ 专用高效★★★★★ 极致
延迟μs~msns级ns级
功耗中等最低
开发成本中等极高(百万$)
代表应用电脑手机通信/视频/AI矿机

🌍 FPGA应用领域(2024-2025热门)

1. AI推理加速 — 低延迟推理,LUT天然适合位操作

2. 5G/6G通信 — 实时信号处理,协议栈硬件化

3. 视频处理 — 实时4K/8K编解码

4. 金融量化 — 纳秒级交易

5. 汽车电子 — 自动驾驶传感器融合

6. 数据中心 — SmartNIC,可编程网络

🔬 进阶:LUT实现加法器

Veriloglut_adder.v — LUT实现全加器
// Sum = A XOR B XOR Cin → init_val = 8'h96
// Cout = (A AND B) OR (Cin AND (A XOR B)) → init_val = 8'hE8
module lut_adder(input a,b,cin, output sum,cout);
    wire [2:0] addr = {a,b,cin};
    assign sum  = 8'h96[addr]; // 查表实现XOR3
    assign cout = 8'hE8[addr]; // 查表实现进位
endmodule

💡 Verilator安装和运行

Ubuntu: sudo apt install verilator

macOS: brew install verilator

编译: verilator --binary -j 0 --trace lut4.v lut4_tb.sv

运行: ./obj_dir/Vlut4_tb

📝 完整测试台

SystemVeriloglut4_tb.sv — LUT4完整测试
module lut4_tb;
    logic [3:0] addr; logic [15:0] init_val; logic y;
    lut4 uut(.*);

    // 测试1: AND门 — 只有1111→1
    task test_and;
        begin
            $display("--- 测试1: 4输入AND门 ---");
            init_val = 16'h0001;
            for(int i=0;i<16;i++) begin
                addr=i; #10;
                if(y!==(i==15))
                    $display("  FAIL: addr=%b, y=%b", addr, y);
            end
            $display("  addr=1111, y=%b (应为1) ✓", y);
        end
    endtask

    // 测试2: XOR门 — 奇校验
    task test_xor;
        begin
            $display("--- 测试2: 4输入XOR门 ---");
            init_val = 16'h9669;
            for(int i=0;i<16;i++) begin
                addr=i; #10;
                logic expected = ^addr;
                if(y!==expected)
                    $display("  FAIL: addr=%b, y=%b", addr, y);
            end
            $display("  XOR测试通过 ✓");
        end
    endtask

    // 测试3: MUX (A?B:C)
    task test_mux;
        begin
            $display("--- 测试3: 2:1 MUX ---");
            init_val = 16'h00CC;
            for(int i=0;i<16;i++) begin
                addr=i; #10;
                logic expected = addr[3]?addr[1]:addr[2];
                if(y!==expected)
                    $display("  FAIL: addr=%b, y=%b", addr, y);
            end
            $display("  MUX测试通过 ✓");
        end
    endtask

    initial begin
        $dumpfile("lut4.vcd"); $dumpvars(0, lut4_tb);
        $display("==============================");
        $display("  LUT4 查找表功能验证");
        $display("==============================");
        test_and; test_xor; test_mux;
        $display("==============================");
        $display("  所有测试通过!LUT就是查表!");
        $display("==============================");
        #100; $finish;
    end
endmodule

🔬 CLB完整结构图

CLB (Configurable Logic Block) ┌──────────────────────────────────────────────┐ │ ┌─────────┐ ┌─────────┐ │ │ │ LUT1 │ │ LUT2 │ ← 2个4-LUT │ │ │ (4输入) │ │ (4输入) │ │ │ └────┬────┘ └────┬────┘ │ │ │ │ │ │ ┌────▼────┐ ┌────▼────┐ │ │ │ DFF1 │ │ DFF2 │ ← 2个触发器 │ │ │ Q1 │ │ Q2 │ │ │ └────┬────┘ └────┬────┘ │ │ └──────┬──────┘ │ │ ┌────▼────┐ │ │ │ MUX │ ← 选择组合/时序输出 │ │ │ 输出 │ │ │ └────┬────┘ │ │ │ │ │ 连接到布线矩阵 → 其他CLB │ └──────────────────────────────────────────────┘ 一个FPGA芯片包含数千到数百万个这样的CLB! 例如: Xilinx Artix-7 XC7A35T ≈ 5,000个CLB Xilinx UltraScale+ VU9P ≈ 500,000个CLB