第一个工程:点亮LED,从零到一
说实话,每次拿到一块新开发板,我做的第一件事都是点亮一个LED。这就像程序员写"Hello World"一样,是个仪式感。但更重要的是,它能帮你验证整个开发链条——从软件安装、工程创建、代码编译到硬件下载,每个环节都没问题。
这一章,我们就来走完这个流程。你跟着我做一遍,后面30章的路就顺了。
1. 创建Diamond工程
打开Lattice Diamond软件,我习惯先建个文件夹。比如在D盘下建个MachXO_Project,里面再按章节分。这样项目多了不乱。
具体步骤:
- 点击 File → New → Project
- 弹窗里选 New Project,点OK
- Project Name填
led_blink,Location选你刚建的文件夹 - Next到Device Selection页
这里要注意了,开发板型号别选错。MachXO系列有好几款,你得看板子上的丝印。我用的这块是 LCMXO2-1200HC-4TG100C。如果你不确定,翻翻板子背面,或者看包装盒上的标签。
选好器件后,一路Next到底,Finish。工程就建好了。
2. 编写Verilog代码
工程建好后,左侧的File List面板是空的。我们需要新建一个Verilog源文件。
右键点击 Input Files → New File → 选择 Verilog File,文件名写 led_top.v。
然后敲入以下代码:
module led_top (
input wire clk, // 板载时钟,12MHz
input wire rst_n, // 复位,低有效
output reg led // 板载LED
);
// 分频计数器
reg [23:0] cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 24'd0;
led <= 1'b0;
end else begin
cnt <= cnt + 1'b1;
// 当计数器满时,翻转LED
if (cnt == 24'd11_999_999) begin
cnt <= 24'd0;
led <= ~led;
end
end
end
endmodule
这段代码的逻辑很简单:用12MHz时钟计数,计到1200万次(差不多1秒)就翻转一次LED。这样你就能看到LED以1Hz的频率闪烁。
3. 综合与布局布线
代码写完了,接下来要把它变成FPGA能理解的比特流。这个过程分两步:Synthesis(综合)和 Place & Route(布局布线)。
在Diamond的Process面板里,你会看到一排流程按钮。双击 Synthesis Design,软件就开始综合了。说白了,综合就是把Verilog代码翻译成逻辑门和触发器的网表。
综合完成后,双击 Place & Route Design。这一步是把逻辑门放到FPGA内部的物理位置上,并连好线。你可以想象成:综合是画了张电路图,布局布线是把这个电路图焊到板子上。
嗯,这里有个小坑。如果你综合时报错说 Unresolved reference to 'clk',八成是顶层模块名字写错了,或者文件名和模块名不一致。我当年就因为这个卡了半小时,后来发现是文件名多打了个空格。
✅ 检查清单:
- 模块名和文件名是否一致?
- 端口声明有没有拼写错误?
- 器件型号是否选对?
4. 下载比特流到开发板
布局布线成功后,Process面板里会多出一个 Bitstream File 的选项。双击它,生成 .bit 文件。这就是我们要下载到板子上的二进制文件。
接下来,把开发板通过USB线连到电脑。打开 Programmer 工具(Diamond自带)。
点击 Detect Cable,软件会自动识别你的下载器。如果识别不到,检查一下驱动有没有装好。Windows下有时候需要手动安装FTDI驱动。
识别成功后,点击 Add Device,选择刚才生成的 .bit 文件。然后点 Program。
几秒钟后,你会看到板子上的LED开始闪烁。那一刻,说实话,挺有成就感的。
5. 本章知识体系
为了让你对整个流程有个直观印象,我画了张图:
这张图把整个流程串起来了。你做完一遍后,再回头看这张图,会发现每一步都对应着你刚才的操作。
6. 避坑指南
最后,我总结几个新手最容易踩的坑:
- 器件选错 —— 前面说过了,这是最隐蔽的错误
- 端口约束没写 —— 代码里写了clk和rst_n,但没告诉软件它们对应板子上的哪个引脚。下一章我们会讲怎么加约束文件
- 下载线没插牢 —— 别笑,我见过有人折腾一上午,结果是USB线松了
- LED正负极接反 —— 有些开发板的LED是高电平点亮,有些是低电平。代码里我默认了高电平点亮,如果你的板子是反的,把
led <= ~led改成led <= led试试
好了,第一个工程到这里就结束了。你成功点亮了LED,也走通了整个开发流程。后面的事情,无非是在这个框架上添砖加瓦。