4. 引脚分配基础:在 .lpf 中使用 LOCATE 命令为顶层端口分配物理引脚号

好,咱们进入正题。引脚分配,说白了就是把你的 Verilog 代码里那些顶层端口——比如 clkrst_nled_out——跟芯片实际的物理引脚一一对应起来。你代码写得再漂亮,这一步搞错了,板子照样不干活。

我刚开始用 Lattice 的时候,就犯过这种低级错误。明明代码仿真都过了,下载到板子上就是没反应。查了半天,发现是引脚号写错了,把 BANK 0 的引脚写成了 BANK 1 的。嗯,从那以后,我对 LOCATE 命令就格外上心。

4.1 什么是 LOCATE 命令?

在 Lattice 的 .lpf 文件里,LOCATE 是核心命令。它的作用就一个:告诉综合工具,你的某个顶层信号,要绑定到芯片的哪个物理引脚上。

语法其实很简单:

LOCATE COMP "顶层端口名" SITE "引脚号";

举个例子:

LOCATE COMP "clk" SITE "A10";
LOCATE COMP "rst_n" SITE "B12";
LOCATE COMP "led_out" SITE "C14";

你看,COMP 后面跟的是你代码里的端口名,SITE 后面跟的是芯片数据手册里的引脚编号。注意,引脚号要用双引号括起来,分号结尾。这是 LPF 文件的规矩,少一个分号,工具就报错。

关键点:端口名必须跟顶层模块里定义的名字完全一致,大小写敏感。我见过有人把 LED_OUT 写成 led_out,结果工具找不到,直接报错。

4.2 引脚分配的基本原则

你可能会想,引脚随便分配不就行了?当然不是。这里有几个硬性规则,我一个个说。

4.2.1 信号类型与 BANK 电压匹配

Lattice FPGA 的引脚是按 BANK 分组的。每个 BANK 有独立的供电电压,比如 3.3V、2.5V、1.8V。你分配引脚时,必须保证信号的电气标准跟 BANK 电压一致。

举个例子:你的 led_out 是 3.3V 的 LVCMOS 信号,那就只能分配到供电为 3.3V 的 BANK 上。如果分到 1.8V 的 BANK,信号电平不对,要么不工作,要么烧芯片。

BANK 编号 典型电压 支持的 I/O 标准
BANK 0 3.3V LVCMOS33, LVTTL33, SSTL33
BANK 1 2.5V LVCMOS25, LVTTL25, SSTL25
BANK 2 1.8V LVCMOS18, LVTTL18
BANK 3 1.2V LVCMOS12, HSTL12

我在项目中遇到过一个问题:板子上有个 1.8V 的 SPI Flash,我随手把它的数据引脚分配到了 BANK 0。结果 BANK 0 是 3.3V 供电,电平不匹配,通信一直出错。后来重新改板才解决。所以,分配引脚前,一定先看原理图,确认每个 BANK 的供电电压。

4.2.2 差分信号对

如果你用的是差分信号,比如 LVDS、差分时钟,那必须成对分配。Lattice 芯片里,差分对通常是相邻的两个引脚,比如 P 和 N。

写法是这样的:

LOCATE COMP "clk_p" SITE "A10";
LOCATE COMP "clk_n" SITE "A11";

注意,clk_pclk_n 必须是一对。你不能把 clk_p 放在 A10,clk_n 放在 B12,那样工具会报错,说它们不是合法的差分对。

警告:差分信号对的两个引脚,必须属于同一个 BANK,且必须是芯片手册里指定的配对关系。乱配的话,轻则时序不满足,重则信号完全无法识别。

4.2.3 特殊功能引脚

有些引脚有特殊功能,比如全局时钟输入、配置引脚、JTAG 引脚。这些引脚不能随便分配给普通信号。

举个例子:芯片的 GCLK 引脚是专门接外部时钟的。如果你把普通 GPIO 信号分配到 GCLK 引脚上,虽然工具不会报错,但会浪费一个宝贵的时钟资源。反过来,如果你把时钟信号分配到普通 GPIO 上,时钟质量会变差,因为普通引脚没有专用的时钟布线网络。

我个人的习惯是:先看数据手册里的引脚功能表,把特殊功能引脚圈出来,再分配普通信号。这样能避免很多坑。

4.3 实战:一个完整的引脚分配示例

光说不练假把式。咱们来个实际例子。假设我有一个顶层模块,端口如下:

module top (
    input  wire clk,      // 系统时钟,50MHz
    input  wire rst_n,    // 复位,低有效
    output wire led_r,    // 红色 LED
    output wire led_g,    // 绿色 LED
    output wire led_b     // 蓝色 LED
);

对应的 .lpf 文件可以这样写:

# 时钟引脚分配
LOCATE COMP "clk" SITE "A10";

# 复位引脚
LOCATE COMP "rst_n" SITE "B12";

# LED 输出引脚
LOCATE COMP "led_r" SITE "C14";
LOCATE COMP "led_g" SITE "C15";
LOCATE COMP "led_b" SITE "D14";

你看,我习惯在每行前面加个注释,说明这个引脚是干什么的。这样以后维护起来,一眼就能看懂。

小技巧:注释用 # 开头。LPF 文件里,# 后面的内容都是注释,工具会忽略。我建议每个引脚都加注释,尤其是大项目,几百个引脚,没注释根本记不住。

4.4 引脚分配后的验证

写完 .lpf 文件,别急着下载。先做一步验证。Lattice Diamond 或者 Radiant 软件里,都有引脚分配检查功能。你点一下,工具会告诉你:

  • 有没有未分配的引脚
  • 有没有重复分配的引脚
  • 有没有违反 BANK 电压规则的分配
  • 有没有差分对不匹配的问题

我建议你养成习惯:每次修改 .lpf 文件后,都跑一遍引脚检查。我曾经有一次,改了一个引脚号,结果不小心跟另一个信号重复了。工具报错我才发现,不然下载到板子上,两个信号短路,后果不堪设想。

4.5 常见错误与避坑指南

这里总结几个我踩过的坑,你遇到了可以少走弯路。

  • 引脚号写错:芯片引脚编号通常是字母+数字,比如 A10、B12。注意,没有 "PIN_" 前缀,直接写 "A10" 就行。我见过有人写成 "PIN_A10",工具不认识。
  • 端口名拼写错误:顶层模块里定义的是 led_r,LPF 里写成 led_R,大小写不一致,工具报错。记住,大小写敏感。
  • 漏掉分号:LPF 文件里,每条命令必须以分号结尾。漏一个分号,工具会报语法错误,而且错误信息可能指向下一行,容易让人摸不着头脑。
  • 分配了不存在的引脚:比如你的芯片只有 100 个引脚,你写了个 "A200",工具直接报错。分配前,一定对照芯片数据手册的引脚图。

重要提醒:如果你用的是开发板,板厂通常会提供引脚分配表或者 .lpf 模板。我建议你直接拿那个模板改,别自己从头写。这样可以避免很多低级错误。

4.6 知识体系:引脚分配的核心逻辑

为了让你更直观地理解引脚分配的整体流程,我画了一张图。你可以看到,从顶层端口到物理引脚,中间要经过几个关键步骤。

引脚分配核心逻辑流程图 步骤1:顶层端口 Verilog 模块定义 步骤2:LOCATE 命令 LPF 文件编写 步骤3:物理引脚 芯片引脚号 检查项:BANK 电压匹配 | 差分对正确 | 特殊功能引脚未占用 | 无重复分配 工具验证 Diamond/Radiant 生成比特流 下载到芯片 板级测试 验证功能正确 修改后重新验证 图4-1:引脚分配从顶层端口到物理引脚的完整流程

从这张图你可以看到,引脚分配不是一步到位的事。写完 LPF 文件后,必须经过工具验证、生成比特流、板级测试这几个环节。任何一个环节出问题,都要回到 LPF 文件修改,然后重新走一遍流程。

嗯,这就是引脚分配的基础。说白了,就是 LOCATE COMP "端口名" SITE "引脚号" 这一条命令,但背后要考虑的东西不少。BANK 电压、差分对、特殊引脚,每一个都不能马虎。你只要把这几条规则记牢了,引脚分配这块基本就不会出大问题。