Quick Start
安装 Vivado 2024.2(或更高版本)及 Git 客户端。克隆开源仓库:
git clone https://github.com/example/fpga_project_template打开 Vivado,选择 Tools → Run Tcl Script,运行仓库中的 build.tcl。等待综合与实现完成,确认无严重时序违规。连接开发板(如 Nexys A7-100T),下载比特流。观察板载 LED 按预期闪烁或 UART 输出测试信息。
前置条件与环境
| 项目/推荐值 | 说明 | 替代方案 |
|---|---|---|
| 器件/板卡 | Xilinx Artix-7 (XC7A100T) 如 Nexys A7-100T | Altera Cyclone IV / Lattice iCE40 |
| EDA 版本 | Vivado 2024.2(或 2025.1) | Vivado ML 免费版 / ISE 14.7(仅旧器件) |
| 仿真器 | Vivado Simulator 或 ModelSim SE-64 2024 | Verilator(仅仿真) |
| 时钟/复位 | 100 MHz 板载晶振,低电平复位 | 50 MHz 晶振需调整 PLL |
| 接口依赖 | USB-UART(FTDI FT2232) | CH340 / CP2102 需改驱动 |
| 约束文件 | XDC 文件指定时钟周期 10 ns,管脚映射 | SDC 文件(Altera) |
| 版本控制 | Git + GitHub / Gitee | SVN / Mercurial |
| 文档工具 | Markdown + Draw.io(流程图) | LaTeX / PlantUML |
目标与验收标准
- 功能点:实现一个 UART 收发器,波特率 115200,8N1 格式,能回环发送接收数据。
- 性能指标:系统时钟 100 MHz 下,UART 无丢帧,误码率 < 1e-9。
- 资源/Fmax:占用 LUT < 200,FF < 150,Fmax ≥ 150 MHz(以 Vivado 报告为准)。
- 验收方式:仿真波形显示 TX 与 RX 数据一致;上板后用串口助手发送 0x55,接收回显 0x55。
实施步骤
工程结构
创建目录 uart_loopback/,内含 rtl/、sim/、constr/、scripts/。使用 Tcl 脚本自动化创建 Vivado 工程,避免手动操作。常见坑:路径不要含中文或空格;版本控制忽略 .cache、.hw、.runs 等生成目录。
关键模块
// uart_tx.v
module uart_tx (
input wire clk,
input wire rst_n,
input wire [7:0] data_in,
input wire send,
output reg tx,
output reg busy
);
localparam BAUD_CNT = 868; // 100MHz / 115200
reg [9:0] cnt;
reg [3:0] bit_idx;
reg [9:0] shift;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
tx <= 1'b1;
busy <= 1'b0;
cnt <= 0;
bit_idx <= 0;
end else begin
// ... 状态机逻辑
end
end
endmodule逐行说明
- 第 1 行:模块声明,端口列表。
- 第 2-5 行:时钟、复位、并行数据输入、发送使能。
- 第 6-7 行:串行输出和忙标志。
- 第 9 行:波特率计数器最大值,由 100 MHz / 115200 计算得到。
- 第 10-12 行:计数器、位索引、移位寄存器。
- 第 13-21 行:时序逻辑,复位时输出高电平(空闲),忙标志清零。
- 第 19 行:状态机占位,实际需补充发送状态转移。
时序/CDC/约束
所有寄存器使用单时钟域,避免跨时钟域问题。约束文件 top.xdc 中声明主时钟:create_clock -period 10.000 -name sys_clk [get_ports clk]。常见坑:未约束异步复位,导致时序分析不准确;应添加 set_false_path 或使用同步复位。
验证
// tb_uart.v
module tb_uart;
reg clk = 0;
reg rst_n = 0;
wire tx;
wire rx;
// 实例化 DUT
uart_loopback uut (.*);
initial begin
#100 rst_n = 1;
#200 send_data(8'h55);
#5000 $finish;
end
always #5 clk = ~clk;
task send_data(input [7:0] d);
// 模拟 UART 发送
endtask
endmodule逐行说明
- 第 1 行:仿真模块声明。
- 第 2-5 行:生成时钟和复位信号。
- 第 6-7 行:顶层模块的串行端口。
- 第 9 行:实例化待测设计,使用 .* 连接。
- 第 10-13 行:初始化序列,释放复位后发送数据 0x55。
- 第 14 行:时钟周期 10 ns,占空比 50%。
- 第 15-17 行:发送任务,需实现起始位、数据位、停止位时序。
上板
连接开发板,确认电源和 JTAG 驱动正常。在 Vivado 中生成比特流,通过 Program Device 下载。打开串口助手(波特率 115200,8N1),发送 0x55,观察回显。常见坑:管脚约束与原理图不一致,导致无输出;应核对开发板原理图。
原理与设计说明
为什么选用 UART 作为入门项目?因为 UART 是 FPGA 中最典型的串行通信协议,涉及状态机设计、波特率生成、跨时钟域(若双时钟)等核心概念。面试官通常通过 UART 项目考察候选人对时序、资源与 Fmax 的权衡能力。
关键权衡
- 资源 vs Fmax:使用查找表实现计数器比专用 DSP 更省资源,但可能降低 Fmax;对于 100 MHz 时钟,LUT 级联 10 级以内通常无时序问题。
- 吞吐 vs 延迟:UART 本身是低吞吐协议(115200 bps),无需优化吞吐;但应确保发送/接收 FIFO 不溢出,避免丢帧。
- 易用性 vs 可移植性:使用 Vivado IP 核(如 UART Lite)可快速集成,但不利于学习底层细节;推荐手写 RTL 以加深理解。
为什么这样设计:采用单时钟域简化 CDC 问题;状态机使用三段式写法(组合逻辑输出、时序状态转移、组合逻辑次态)以提高可读性和综合质量。
验证与结果
| 指标 | 测量值(示例) | 条件 |
|---|---|---|
| Fmax | 210 MHz | Vivado 2024.2,Artix-7 -1 速度等级 |
| LUT 占用 | 156 | 仅 UART 收发 + 回环逻辑 |
| FF 占用 | 112 | 同上 |
| 误码率 | < 1e-9 | 100 MHz 时钟,115200 bps,发送 1e6 字节 |
| 波形特征 | TX 起始位低电平,数据位 LSB 优先 | 仿真 5000 ns |
测量条件:Vivado 默认综合策略,实现后时序报告;仿真使用 Vivado Simulator,激励为连续发送 0x55。
故障排查
- 现象:上板后无输出 → 原因:管脚约束错误 → 检查点:核对原理图,确认 TX 管脚映射 → 修复:修正 XDC 文件。
- 现象:仿真波形无变化 → 原因:复位未释放或时钟未翻转 → 检查点:查看 rst_n 和 clk 信号 → 修复:修改 testbench 初始化。
- 现象:串口助手收到乱码 → 原因:波特率不匹配 → 检查点:计算 BAUD_CNT 是否正确 → 修复:重新计算并仿真验证。
- 现象:综合报时序违规 → 原因:组合逻辑路径过长 → 检查点:查看关键路径报告 → 修复:插入流水线寄存器。
- 现象:下载比特流失败 → 原因:JTAG 驱动问题 → 检查点:设备管理器中查看 Digilent USB 设备 → 修复:重新安装驱动或更换 USB 线。
- 现象:LED 不亮 → 原因:电源不足或短路 → 检查点:测量板卡电压 → 修复:更换电源适配器。
- 现象:仿真时间过长 → 原因:$finish 未设置 → 检查点:添加 #5000 $finish → 修复:限制仿真运行时间。
- 现象:Git 冲突 → 原因:多人修改同一文件 → 检查点:查看 git log → 修复:手动合并或使用 git mergetool。
扩展与下一步
- 参数化:将波特率、数据位宽等定义为参数,便于复用。
- 带宽提升:升级到 USB 3.0 或以太网接口,实现高速数据传输。
- 跨平台:将设计移植到 Altera 或 Lattice 器件,学习不同工具链。
- 加入断言:在 testbench 中使用 SystemVerilog 断言(SVA)自动化验证。
- 覆盖分析:使用 Vivado 覆盖率工具,确保状态机所有分支被覆盖。
- 形式验证:用 SymbiYosys 或 JasperGold 验证 UART 协议的正确性。
参考与信息来源
- Xilinx UG949: Vivado Design Suite User Guide
- Digilent Nexys A7 Reference Manual
- OpenCores UART 项目 (https://opencores.org/projects/uart)
- FPGA4Fun UART 教程 (https://www.fpga4fun.com/SerialInterface.html)
- GitHub: fpga_uart_loopback 示例仓库
技术附录
术语表
- UART:通用异步收发器,串行通信协议。
- CDC:跨时钟域,处理不同时钟域间的信号同步。
- Fmax:最大工作频率,由时序分析报告给出。
- LUT:查找表,FPGA 基本逻辑单元。
- FF:触发器,用于寄存状态。
检查清单
- [ ] 工程结构符合规范,无中文路径。
- [ ] RTL 代码通过 lint 检查(如 Verilator)。
- [ ] 约束文件包含时钟和管脚约束。
- [ ] 仿真通过,波形符合协议。
- [ ] 综合实现无严重警告或错误。
- [ ] 上板验证通过。
- [ ] 项目已上传至 GitHub 并添加 README。
关键约束速查
# top.xdc
create_clock -period 10.000 -name sys_clk [get_ports clk]
set_property PACKAGE_PIN E3 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property PACKAGE_PIN D4 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
set_property PACKAGE_PIN C4 [get_ports tx]
set_property IOSTANDARD LVCMOS33 [get_ports tx]
set_property PACKAGE_PIN A4 [get_ports rx]
set_property IOSTANDARD LVCMOS33 [get_ports rx]逐行说明
- 第 1 行:创建主时钟,周期 10 ns,对应 100 MHz。
- 第 2-3 行:时钟管脚约束,使用 LVCMOS33 电平标准。
- 第 4-5 行:复位管脚约束。
- 第 6-7 行:UART 发送管脚约束。
- 第 8-9 行:UART 接收管脚约束。



