FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
登录
首页-技术文章/快讯-技术分享-正文

基于FPGA的UART通信协议设计与实现指南

二牛学FPGA二牛学FPGA
技术分享
2天前
0
0
9

Quick Start

  1. 安装 Vivado 或 Quartus Prime(推荐 Vivado 2020.1 或更高版本),并确认仿真工具(如 ModelSim、Questa)可用。
  2. 创建新工程,选择目标器件(如 Xilinx Artix-7 XC7A35T)。
  3. 编写 UART 发送模块(uart_tx),包含波特率生成器、移位寄存器和起始/停止位逻辑。
  4. 编写 UART 接收模块(uart_rx),包含边沿检测、采样时钟和字节组装逻辑。
  5. 编写顶层模块(uart_top),例化 tx 和 rx,连接数据端口和控制信号。
  6. 编写 testbench,模拟发送一个字节(如 0xA5),并验证接收端正确输出。
  7. 运行行为仿真,检查波形:tx 线在空闲时为高,起始位为低,数据位按 LSB 优先排列。
  8. 综合并实现,检查资源利用率(LUT/FF 应低于 100 个)和最大频率(通常 >200 MHz)。
  9. 生成比特流,下载到 FPGA 板卡,用串口助手(如 Putty)发送数据,观察板载 LED 或通过回环测试验证。
  10. 验收:发送 0x00-0xFF 所有字节,接收端无误码,波特率误差 < 2%。

前置条件与环境

项目推荐值替代方案
器件/板卡Xilinx Artix-7 XC7A35T(如 Nexys4 DDR)Intel Cyclone IV / Lattice iCE40
EDA 版本Vivado 2020.1 或更高Quartus Prime 18.0+ / ISE 14.7
仿真器Vivado Simulator 或 ModelSim SE-64 10.5Questa / GHDL + GTKWave
时钟/复位系统时钟 100 MHz,异步复位低有效50 MHz 时钟,高有效复位(需适配)
接口依赖FPGA 的 UART 引脚(如 PMOD 或 USB-UART 桥)使用板载 USB-UART(如 CP2102)
约束文件XDC 文件:时钟周期 10 ns,IO 标准 LVCMOS33SDC 文件(Quartus)
串口工具Putty / Tera Term(波特率 115200, 8N1)Python pyserial 脚本

目标与验收标准

本设计旨在实现一个全双工 UART 通信模块,支持可配置波特率(默认 115200)、8 位数据、无校验、1 位停止位(8N1)。验收标准如下:

    功能点:发送与接收独立,支持连续字节传输,无数据丢失。性能指标:波特率误差 < 2%(实际采样时钟频率与理想值偏差),最大传输速率 1 Mbps(时钟 100 MHz 时)。资源开销:LUT < 80,FF < 60,无 BRAM 使用。验收方式:仿真波形显示 tx 输出符合 UART 帧格式;上板测试通过回环(tx 接 rx)发送 256 字节无错。

实施步骤

阶段一:工程结构与顶层模块

创建工程目录:uart_project/src 放 RTL 文件,uart_project/sim 放 testbench。顶层模块 uart_top 例化 tx 和 rx,并连接数据总线(8 位并行输入/输出)、控制信号(tx_start, rx_ready)和串行线(tx, rx)。

// uart_top.v
module uart_top (
    input wire clk,
    input wire rst_n,
    input wire [7:0] data_in,
    input wire tx_start,
    output wire tx,
    input wire rx,
    output wire [7:0] data_out,
    output wire rx_done,
    output wire tx_busy
);

uart_tx u_tx (
    .clk(clk),
    .rst_n(rst_n),
    .data_in(data_in),
    .tx_start(tx_start),
    .tx(tx),
    .tx_busy(tx_busy)
);

uart_rx u_rx (
    .clk(clk),
    .rst_n(rst_n),
    .rx(rx),
    .data_out(data_out),
    .rx_done(rx_done)
);

endmodule

常见坑与排查

    若顶层模块例化时报错,检查模块名和端口顺序是否匹配。若未定义 tx_busy 信号,发送可能重叠。

阶段二:UART 发送模块(uart_tx)

发送模块核心是波特率发生器和移位状态机。波特率发生器将系统时钟分频为 16 倍波特率的采样时钟(例如 115200 bps 需 1.8432 MHz 采样时钟)。状态机依次输出起始位(0)、8 位数据(LSB 优先)、停止位(1)。

// uart_tx.v (核心片段)
localparam CLK_FREQ = 100_000_000;
localparam BAUD_RATE = 115200;
localparam DIVIDER = CLK_FREQ / (BAUD_RATE * 16); // 约 54

reg [5:0] baud_cnt;
wire baud_tick = (baud_cnt == DIVIDER-1);

always @(posedge clk or negedge rst_n)
    if (!rst_n)
        baud_cnt &lt;= 0;
    else if (baud_tick)
        baud_cnt &lt;= 0;
    else
        baud_cnt &lt;= baud_cnt + 1;

状态机采用三段式写法,状态包括 IDLE、START、DATA、STOP。在 DATA 状态下,每个 baud_tick 移出一位数据,共 8 位。

原因与机制分析

采用 16 倍过采样而非直接 1 倍采样,是为了在接收端提供更精确的位中心对齐,降低因时钟偏差导致的误码风险。分频系数计算时取整,实际波特率与理想值偏差需控制在 2% 以内,否则可能超出接收端容错范围。

落地路径

    先验证 baud_tick 波形频率是否正确(仿真中计算脉冲间隔)。再验证状态机输出帧格式:起始位、数据位、停止位顺序与电平。

风险边界

若系统时钟频率过低(如 50 MHz),分频系数较小,波特率误差可能增大;建议时钟不低于 50 MHz。此外,连续发送时需确保 tx_start 在 tx_busy 为低时置位,否则数据可能丢失。

阶段三:UART 接收模块(uart_rx)

接收模块同样依赖 16 倍过采样时钟。边沿检测电路识别起始位下降沿,启动采样计数器。在每位的中点(第 8 个采样点)采集数据,并组装成 8 位字节。完成后输出 rx_done 脉冲和 data_out。

// uart_rx.v (核心片段)
reg [3:0] sample_cnt; // 0-15 过采样计数器
reg [2:0] bit_cnt;    // 0-7 位计数器
reg [7:0] shift_reg;

always @(posedge clk or negedge rst_n)
    if (!rst_n) begin
        sample_cnt &lt;= 0;
        bit_cnt &lt;= 0;
        shift_reg &lt;= 0;
    end else begin
        // 边沿检测与采样逻辑(略)
    end

原因与机制分析

过采样并在位中点采样,可有效避开信号跳变沿附近的毛刺和抖动,提升抗干扰能力。边沿检测采用两级寄存器同步,避免亚稳态传播。

落地路径

    仿真中注入带噪声的 rx 信号,验证采样点是否正确。测试连续接收多个字节,检查 rx_done 脉冲间隔是否稳定。

风险边界

接收端波特率误差容限约为 ±4%(取决于采样点位置),设计应确保两端误差总和不超过此值。若使用非整数分频,需用累加器或小数分频技术。

阶段四:仿真验证

编写 testbench,实例化顶层模块,生成 100 MHz 时钟和复位信号。模拟发送过程:置位 tx_start,等待 tx_busy 拉低后发送下一字节。同时将 tx 输出直接连接到 rx 输入,实现回环测试。

// testbench 核心片段
initial begin
    clk = 0;
    forever #5 clk = ~clk; // 100 MHz
end

initial begin
    rst_n = 0;
    #100 rst_n = 1;
    #20 tx_start = 1; data_in = 8'hA5;
    #20 tx_start = 0;
    wait (rx_done);
    $display("Received: %h", data_out);
    #100 $finish;
end

验证结果

仿真波形应显示:tx 线在空闲时为高,起始位为低,数据位按 LSB 优先排列,停止位为高。接收端在停止位结束后输出 rx_done 脉冲,data_out 与发送数据一致。

排障指南

    仿真无输出:检查时钟和复位是否正常;确认 baud_tick 是否产生脉冲。数据错位:检查 LSB 优先顺序;确认采样点是否在位中心。上板无响应:检查引脚约束是否正确;确认串口工具波特率设置一致。误码率高:测量实际波特率偏差;检查电源噪声或时钟抖动。

扩展方向

    支持可配置数据位(5-8 位)、校验位(奇/偶/无)、停止位(1/1.5/2)。添加 FIFO 缓冲,实现连续流传输。集成 AXI4-Stream 接口,便于与 SoC 系统互联。实现自动波特率检测功能。

参考

    《UART 通信协议标准》(ANSI/EIA-232 系列)Xilinx UG901 Vivado 设计流程指南FPGA 设计实战:数字通信系统(作者:王金明)

附录

附录 A:完整代码清单(略,参见工程源码)

附录 B:约束文件示例

# XDC 约束
create_clock -period 10.000 -name sys_clk [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports {tx rx}]
set_property PACKAGE_PIN L17 [get_ports clk]
标签:
本文原创,作者:二牛学FPGA,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/40438.html
二牛学FPGA

二牛学FPGA

初级工程师
这家伙真懒,几个字都不愿写!
91919.29W3.99W3.67W
分享:
成电国芯FPGA赛事课即将上线
FPGA图像处理:实时Sobel边缘检测的Verilog实现指南
FPGA图像处理:实时Sobel边缘检测的Verilog实现指南上一篇
数字IC设计入门指南:从RTL到GDS的完整流程与实施步骤下一篇
数字IC设计入门指南:从RTL到GDS的完整流程与实施步骤
相关文章
总数:944
FPGA学习路线图:从零基础到项目实战的规划与实施指南

FPGA学习路线图:从零基础到项目实战的规划与实施指南

QuickStart:最短路径跑通第一个FPGA工程本指南旨在帮助零基…
技术分享
7天前
0
0
19
0
2026年FPGA就业与市场趋势深度解读:边缘AI、RISC-V与国产化浪潮下的机遇与挑战

2026年FPGA就业与市场趋势深度解读:边缘AI、RISC-V与国产化浪潮下的机遇与挑战

2026年,FPGA行业正经历一场由边缘AI、RISC-V生态成熟、Ch…
技术分享
4天前
0
0
28
0
FPGA时序约束通关指南:从理论到代码的实战心法

FPGA时序约束通关指南:从理论到代码的实战心法

时序约束,为什么非学不可?在FPGA的世界里,时序约束(Timi…
技术分享
1个月前
0
0
77
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容