← 返回博客

如何使用FPGA实现UART通信

从 UART 帧格式、波特率生成到 Verilog 收发状态机,完成一个可仿真的串口通信模块。

如何使用FPGA实现UART通信 封面

UART 是 FPGA 项目中最常用的调试接口之一。本文实现一个 8N1 配置的收发模块:1 位起始位、8 位数据位、无校验、1 位停止位。

通信参数与时序

UART 没有共享时钟,双方依靠约定的波特率采样。以 50 MHz 系统时钟和 115200 baud 为例,每一位持续的时钟周期数约为:

CLKS_PER_BIT = 50_000_000 / 115_200 ≈ 434

接收端检测到下降沿后,应当先等待半个 bit,在起始位中心再次确认低电平,再按整 bit 间隔采样。

发送模块设计

发送器可以使用有限状态机依次输出起始位、数据位和停止位。

always @(posedge clk) begin
  if (tx_start && !tx_busy) begin
    tx_shift <= {1'b1, tx_data, 1'b0};
    tx_busy  <= 1'b1;
    bit_cnt  <= 0;
  end else if (tx_busy && baud_tick) begin
    tx       <= tx_shift[bit_cnt];
    bit_cnt  <= bit_cnt + 1'b1;
    if (bit_cnt == 9) tx_busy <= 1'b0;
  end
end

波特率使能

更推荐生成一个单周期的 baud_tick,而不是在逻辑内部派生新时钟。这样所有寄存器仍处于同一个时钟域,约束和时序分析都会更简单。

接收模块设计

异步输入首先应经过两级触发器同步,以降低亚稳态传播概率。状态机检测起始位后,在每个数据位中心采样,并按低位优先写入移位寄存器。

实际环境存在时钟误差和线路噪声。要求更高时,可以使用 8 倍或 16 倍过采样与多数表决。

仿真与验证

Testbench 中依次发送 8'h558'hA3 和边界值,检查接收数据以及 valid 脉冲。0x55 的比特交替变化,特别适合观察采样位置。

  1. 验证复位时输出保持高电平。
  2. 验证连续字节之间不会丢失停止位。
  3. 注入轻微波特率偏差,观察接收容限。
  4. 在开发板上做 TX/RX 环回测试。

小结

UART 模块的关键不是复杂逻辑,而是明确时序、同步异步输入并通过仿真覆盖边界情况。下一步可以加入 FIFO,让串口与上层逻辑解耦。