这一篇在干嘛?
调试 FPGA 工程时,串口(UART)是最常用的「耳朵和嘴巴」:把内部状态打印给 PC 看,或从 PC 下发命令。这个实验实现最经典的入门功能——环回(loopback):PC 发什么,FPGA 原样发回什么。实验原文很短,本文把 UART 帧格式和波特率原理展开讲透,并保留全部原文约束与流程。
实验目标与原理
实验目的原文:
上位机通过串口调试助手发送数据给 FPGA,FPGA 通过串口接收数据并将接收到的数据发送给上位机,完成串口数据环回。
RS232 与 USB 转串口
2.1 相关关于 RS232 可以查找相关资料。 2.2 在此开发板上,通过 CH340 芯片由 USB 转串口。相关原理图请查找「开发板手册」。
展开说一下背景:RS232 是古老的串行电气标准,用正负电平表示逻辑 0/1;而现代电脑早已没有 RS232 口,所以板卡上放一颗 CH340 芯片做「翻译」——一端是 USB 协议,另一端是 UART 的 TX/RX 逻辑电平。PC 侧看到的是一个虚拟 COM 口,FPGA 侧看到的就是普通的 TX/RX 两根线。对 FPGA 而言,CH340 完全透明:你按 UART 时序收发即可。
UART 帧格式:没有时钟线,靠约定同步
UART 与 SPI、I2C 最大的不同是没有时钟线。双方只靠事先约定好的波特率(每秒传多少位)各自计时。一帧标准 8N1 数据的构成:
| 位序 | 内容 | 电平 |
|---|---|---|
| 起始位 | 1 位 | 恒为 0(空闲为 1,拉低表示「开始」) |
| 数据位 D0~D7 | 8 位 | 低位在先 |
| 校验位(可选) | 0 或 1 位 | 本实验不用 |
| 停止位 | 1 位 | 恒为 1,之后回到空闲 |
接收方检测到 RX 线从 1 跳到 0,就认定起始位到来,随后在每一位的中点采样数据位——中点采样是为了避开边沿抖动,让采样时刻落在电平最稳定的位置。每一位持续多长?1 / 波特率秒。本实验用 115200bps,一位约 8.68µs;50MHz 系统时钟下一位约 434 个时钟周期,用计数器就能精确对准中点。
波特率必须两端一致
串口调试助手里选错波特率,收到的就是乱码——因为接收方按错误的节拍采样。115200 是调试最常用的档位,误差需控制在约 ±2% 以内,50MHz 分频出的 434 分之一精度足够。如果换成 9600 等低速档,容错更宽,但也别两端各配各的。
设计思路:两个模块、一条通路
原文设计思路:
在 FPGA 内部实现串口接收与串口发送模块,串口接收模块接收上位机发送的数据,然后通过串口发送模块将数据发回上位机,实现串口数据环回。如图 1

图 1
数据流非常干净:
PC 发送 → CH340 → uart_rx(FPGA 接收模块,串转并)→ 数据寄存
→ 通知信号 → 发送模块(并转串)→ uart_tx → CH340 → PC 显示
原文对模块行为的说明:
串口接收模块从串口接收端口接收上位机发送的串行数据,并在一帧数据(8 位)接收结束后给出通知信号为串口发送模块,将接收到的数据通过串口发送端口发送出去在串口通信软件上显示。
「接收完成 → 拉一个通知脉冲 → 发送模块取走字节并回发」,这是典型的握手设计。写自己的 UART 时把这个握手信号显式定义出来,比让发送模块自己去猜「数据什么时候有效」可靠得多。
接线与电平的两个细节
写 UART 模块前先在心里过一遍信号名,避免「自发自收」的低级错误:FPGA 的 uart_rx 接的是 CH340 的 TX 输出,FPGA 的 uart_tx 接的是 CH340 的 RX 输入——你的接收端对着它的发送端,交叉相连。
第二个细节是空闲电平:UART 空闲时 TX 线保持高电平,起始位用「拉低」来宣告。所以 FPGA 侧把 uart_rx 配置成上拉输入(见后文引脚约束的 PULLTYPE = PULLUP),保证线缆未插或对方未驱动时不会因为悬空而误判出一个假起始位。
引脚分配
原文引脚约束一字不改。
时钟周期约束与 IO 约束:
set_pin_assignment { clk } { LOCATION = R7; IOSTANDARD = LVCMOS33; PULLTYPE = PULLUP; }
set_pin_assignment { rst_n } { LOCATION = A2; IOSTANDARD = LVCMOS33; PULLTYPE = PULLUP; }
set_pin_assignment { uart_rx } { LOCATION = F12; IOSTANDARD = LVCMOS33; PULLTYPE = PULLUP; }set_pin_assignment { uart_tx } { LOCATION = D12; IOSTANDARD = LVCMOS33; DRIVESTRENGTH = 8; PULLTYPE = NONE;}整理成速查表:
| 信号 | 方向 | 引脚 | 说明 |
|---|---|---|---|
| clk | 输入 | R7 | 50MHz 系统时钟 |
| rst_n | 输入 | A2 | 复位(低有效) |
| uart_rx | 输入 | F12 | 串口接收,来自 CH340 TX |
| uart_tx | 输出 | D12 | 串口发送,接 CH340 RX |
注意 uart_rx 配置了上拉:UART 空闲电平为高,上拉保证 CH340 未连接或未驱动时接收端不悬空、不误判起始位。
上板流程:驱动安装与调试助手
这一步对第一次玩串口的人最容易卡住,原文流程照录并补充要点。
第一步:连接硬件
准备对应接口的 USB 线,连接 USB 转串口,在连接 USB 转串口的时候,在板子上的左边的接口 Type-c 口。上位机第一次使用 USB 串口线与 FPGA 开发板连接时,需要安装 USB 串口驱动。在开发板资料中找到「驱动软件//CH340 驱动(USB 串口驱动)」的文件夹,双击打开文件夹中的「SETUP.EXE」进行安装,驱动安装界面如图 2 所示。界面中提示 INF 文件为 CH341SER.INF,我们不需要理会(CH330,CH341 驱动是通用的),直接点安装即可。

图 2
第二步:确认驱动装好了
安装完以后,在资源管理器,点开「端口(COM 和 LPT)」,看驱动是否装好,图 3。

图 3
记下这里显示的 COM 号(例如 COM3),稍后调试助手要选同一个口。
第三步:下载程序并打开调试软件
下载,程序下载完毕。找到资料中的「调试软件」,点击如图 4 的标识。

图 4

第四步:环回测试
打开软件后,串口号 COM 口要跟设置驱动的图 3 串口号一致,波特率显示是 115200,在字符串输入框输入字母或数字,点击发送,在上框显示同样的字符。

环回成功≠双向都正常吗?
严格说,环回测试验证的是「接收 + 发送」整条链路能走通,但无法区分哪个环节出问题时(比如 TX 与 RX 接反、波特率不符、COM 口选错),现象都是「收不到回显」。排查顺序建议:确认 COM 口 → 确认波特率 115200 → 确认 Type-c 线是数据线不是纯充电线 → 重新下载程序并复位。
现象与总结
成功标准只有一个:在调试助手的字符串输入框输入字母或数字、点击发送后,上方的接收框出现同样的字符。看到回显,就意味着你独立完成了一次「PC → CH340 → FPGA 接收 → FPGA 发送 → CH340 → PC」的完整数据旅程。
这个实验虽然小,却包含三个值得带走的经验:
- 异步串行的本质是「约定 + 计数」:没有时钟线,起始位提供同步锚点,波特率提供节拍,中点采样提供鲁棒性。理解了这三点,9600 到 3M 波特率的所有 UART 都是同一件事。
- 握手信号让模块解耦:接收模块完成后给一个脉冲,发送模块据此取数发送——两个模块互不依赖内部细节,这也是所有 FPGA 工程里模块间协作的标准范式。
- 先装驱动再上电调试:CH340 驱动、COM 号、波特率是串口调试三大坑。养成先在设备管理器确认 COM 口的习惯,能省掉大量「程序没错就是不通」的时间。
下一步可以试着把环回改成「收到命令后返回固定字符串」,或把波特率参数化,做成可配置 9600/115200 的通用 UART 模块,以后所有工程都能直接复用。
自测
自测
- UART 一帧 8N1 数据包含哪些位?起始位和停止位的电平分别是什么?
- 没有时钟线的 UART 靠什么实现收发同步?为什么接收方要在每一位的中点采样?
- 波特率 115200 时,一位数据持续多长时间?在 50MHz 时钟下大约对应多少个时钟周期?
- CH340 芯片在本实验链路中起什么作用?FPGA 侧需要关心 USB 协议吗?
- 环回测试时收不到回显,列出至少三个可能的原因和排查顺序。