Quick Start
- 步骤1:在Vivado中新建工程,选择目标器件(如XC7A35T-1CSG324C)。
- 步骤2:创建顶层模块
uart_top,例化UART发送模块uart_tx、接收模块uart_rx和回环测试模块loopback。 - 步骤3:编写UART发送模块——实现波特率发生器(115200 bps)、并行转串行、起始位/数据位/停止位生成。
- 步骤4:编写UART接收模块——检测起始位、采样数据位、串行转并行、输出接收到的字节。
- 步骤5:编写回环模块——将接收到的字节立即发送回去(loopback测试)。
- 步骤6:添加时序约束(时钟周期、输入输出延迟),运行综合与实现。
- 步骤7:生成比特流并下载到FPGA开发板。
- 步骤8:使用串口调试工具(如Putty、串口助手)连接开发板,发送任意字节,观察是否回显相同内容。
- 步骤9:若回显正确,则UART通信协议实现成功;否则检查波特率匹配、引脚分配或逻辑错误。
前置条件与环境
| 项目 | 推荐值 | 说明/替代方案 |
|---|---|---|
| 器件/板卡 | Xilinx Artix-7 XC7A35T-1CSG324C | 其他Xilinx 7系列或Intel Cyclone V |
| EDA版本 | Vivado 2022.2 | Vivado 2018.3及以上,或Quartus Prime 20.1+ |
| 仿真器 | Vivado Simulator | ModelSim/QuestaSim,VCS |
| 时钟/复位 | 板载50MHz晶振,低电平有效复位 | 可改用PLL倍频,复位极性可配置 |
| 接口依赖 | USB-UART转换器(如CP2102) | 板载UART转USB芯片(如FT232) |
| 约束文件 | XDC文件:时钟周期20ns,输入延迟5ns,输出延迟5ns | 根据实际板级走线调整 |
| 调试工具 | Putty(串口终端) | Tera Term,串口助手 |
目标与验收标准
功能点:FPGA通过UART接收PC发送的字节,并立即回显相同字节。
性能指标:支持115200 bps波特率,误码率低于10^-6(在标准串口线缆长度内)。
资源占用:LUT < 200,FF < 150,BRAM < 1(对于基本回环)。
Fmax:> 100 MHz(时钟域为系统时钟50MHz,满足时序)。
验收方式:串口助手发送0x55(交替位模式),回显波形应稳定无毛刺;发送连续数据流(如1000字节),无丢包。
实施步骤
工程结构
uart_top.v // 顶层模块,例化发送、接收和回环
uart_tx.v // UART发送模块
uart_rx.v // UART接收模块
uart_baud_gen.v // 波特率发生器(分频计数器)
loopback.v // 回环控制逻辑
uart_top.xdc // 时序与引脚约束说明:顶层模块负责连接各子模块,波特率发生器为发送和接收提供统一的采样时钟(16倍波特率,即115200*16=1.8432MHz)。
关键模块:波特率发生器(uart_baud_gen)
module uart_baud_gen #(
parameter CLK_FREQ = 50_000_000,
parameter BAUD_RATE = 115200
)(
input clk,
input rst_n,
output reg baud_clk_en
);
localparam DIV = CLK_FREQ / (BAUD_RATE * 16) - 1;
reg [15:0] cnt;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 0;
baud_clk_en <= 0;
end else begin
if (cnt == DIV) begin
cnt <= 0;
baud_clk_en <= 1;
end else begin
cnt <= cnt + 1;
baud_clk_en <= 0;
end
end
end
endmodule机制分析:该模块通过系统时钟分频产生16倍波特率的使能脉冲。选择16倍过采样是为了在接收端能够更精确地定位数据位的中心点,从而容忍时钟偏差和信号抖动。分频系数DIV的计算公式为CLK_FREQ / (BAUD_RATE * 16) - 1,其中减1是因为计数器从0开始计数。对于50MHz时钟和115200波特率,DIV = 50000000 / (115200 * 16) - 1 ≈ 26,即每27个时钟周期产生一个使能脉冲。
UART发送模块(uart_tx)
该模块负责将并行数据(8位)转换为串行数据,并按照UART协议帧格式发送:起始位(低电平)、数据位(LSB优先)、可选的奇偶校验位、停止位(高电平)。核心逻辑包括:
- 状态机控制:空闲、发送起始位、发送数据位、发送停止位。
- 移位寄存器:在发送数据位阶段,每个波特率时钟将并行数据右移一位。
- 波特率时钟同步:使用
baud_clk_en作为发送节拍,确保每位持续时间准确。
UART接收模块(uart_rx)
接收模块需要检测起始位(检测到RXD线从高到低跳变),然后以16倍波特率时钟采样数据位。关键设计点:
- 起始位检测:连续采样到低电平持续至少半个位时间,确认是有效起始位而非噪声。
- 数据位采样:在每个数据位的中心时刻(即从起始位开始计数8个16倍时钟周期)采样,避免边缘抖动。
- 串行转并行:将采样到的8位数据存入寄存器,并在接收完成后输出。
回环模块(loopback)
该模块实现最简单的功能:每当uart_rx输出一个接收到的字节,立即将其作为发送数据输入到uart_tx,并触发发送使能。注意需要处理发送忙信号,避免在发送过程中覆盖数据。
验证结果
通过串口助手发送测试数据,观察回显结果:
- 发送单字节0x55(二进制01010101),回显应为0x55,波形无毛刺。
- 发送连续1000字节递增序列(0x00-0xFF循环),回显应完全一致,无丢包或错位。
排障指南
常见问题与解决方案:
- 无回显:检查引脚分配是否正确(尤其是TXD和RXD是否交叉连接);确认波特率设置一致;检查复位信号是否释放。
- 数据错位或乱码:波特率发生器分频系数计算错误,导致实际波特率与预期不符;检查时钟频率是否与参数一致。
- 偶尔丢包:接收模块的起始位检测过于敏感,增加去抖动逻辑;或发送模块的停止位宽度不足,确保停止位至少1位时间。
- 时序违例:检查XDC约束中的输入输出延迟是否合理;如果时钟频率较高,考虑使用PLL生成更低频的时钟。
扩展建议
在基本回环验证通过后,可进行以下扩展:
- 增加奇偶校验位,提高数据可靠性。
- 实现多字节缓冲区(FIFO),支持连续收发。
- 添加自定义协议帧(如起始标志、长度、CRC校验),构建更复杂的通信链路。
- 将UART与FPGA内部其他模块(如ADC控制器、传感器接口)集成,实现数据采集与上传。
参考
- Xilinx UG949: Vivado Design Suite User Guide
- UART协议规范(RS-232标准)
附录
附录A:完整XDC约束示例
# 时钟约束
create_clock -period 20.000 -name sys_clk [get_ports clk]
# 输入延迟(UART RXD)
set_input_delay -clock sys_clk -max 5.000 [get_ports rxd]
set_input_delay -clock sys_clk -min 2.000 [get_ports rxd]
# 输出延迟(UART TXD)
set_output_delay -clock sys_clk -max 5.000 [get_ports txd]
set_output_delay -clock sys_clk -min 2.000 [get_ports txd]
# 引脚分配(根据实际板卡修改)
set_property PACKAGE_PIN R4 [get_ports clk]
set_property PACKAGE_PIN U16 [get_ports rst_n]
set_property PACKAGE_PIN V17 [get_ports rxd]
set_property PACKAGE_PIN W17 [get_ports txd]附录B:仿真测试激励要点
- 模拟PC发送0x55,检查FPGA回显波形是否与发送波形一致(注意TXD相对RXD有延迟)。
- 模拟波特率偏差(如发送端使用115200,接收端使用115000),验证系统容错能力。





