项目目标:
串口通信回环, 使用USB-CDC IP 虚拟串口与串口上位机通信,在FPGA内部将接收的上位机数据转为串口时序,在FPGA内部实现串口回环。
硬件连接电路
原理图如下:

使用H10,H11作为UART_RXD和UART_TXD

实物连接图如下:

软件工程

配置如下:
IO_LOC "UART_TXD" H11;
IO_PORT "UART_TXD" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8 BANK_VCCIO=3.3;
IO_LOC "UART_RXD" H10;
IO_PORT "UART_RXD" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
FPGA 顶层设计包含:
- 时钟管理 :
- 使用 PLL 将 25MHz 输入时钟转换为 50MHz 系统时钟
- 包含复位控制逻辑,确保系统在 PLL 锁定后稳定工作
- UART 通信 :
- 波特率配置为 115200bps
- 包含一个整数分频器,生成 16 倍波特率的采样时钟
- UART 接收模块:接收 PC 发送的数据
- UART 发送模块:将接收到的数据回传给 PC
- 测试接口 :
- test_io 输出是 UART_RXD 和 UART_TXD 的逻辑与
代码如下:
module FPGA_G60_Top
(
input clk_25M,
input UART_RXD,
output UART_TXD,
output test_io
);
assign test_io = UART_RXD&UART_TXD;
wire w_sys_clk ;
wire w_sys_rst, w_sys_rstn;
wire w_pll_locked;
PLL_25_50 u_system_pll(
.lock(w_pll_locked),
.clkout0(w_sys_clk),
.clkin(clk_25M)
);
Reset rst_sys_clk (.clk_i(w_sys_clk), .rstn_i(1'b1), .locked_i(w_pll_locked), .rstn_o(w_sys_rstn), .rst_o(w_sys_rst));
parameter CLOCK_MAIN = 50_000_000;
parameter BAUD_RATE = 115200;
wire divide_clken;
integer_divider
#(
.DEVIDE_CNT ((CLOCK_MAIN / BAUD_RATE)>>4)
)
u_integer_devider
(
.clk (w_sys_clk),
.rst_n (w_sys_rstn),
.divide_clken (divide_clken)
);
wire clken_16bps = divide_clken;
wire rxd_flag;
wire [7:0] rxd_data;
uart_receiver#(
.BAUD_RATE(BAUD_RATE)
)u_uart_receiver
(
.clk (w_sys_clk),
.rst_n (w_sys_rstn),
.clken_16bps (clken_16bps),
.rxd (UART_RXD),
.rxd_data (rxd_data),
.rxd_flag (rxd_flag)
);
uart_transfer u_uart_transfer
(
.clk (w_sys_clk),
.rst_n (w_sys_rstn),
.clken_16bps (clken_16bps),
.txd (UART_TXD),
.txd_en (rxd_flag),
.txd_data (rxd_data),
.txd_flag ( )
);
endmodule
- 代码实现了一个简单的 UART 回环功能,即接收什么数据就发送什么数据
- 波特率设置为 115200bps,可以通过修改 BAUD_RATE 参数进行调整
- 系统时钟设置为 50MHz,可以通过修改 CLOCK_MAIN 参数进行调整
- 发送模块的 txd_flag 输出
波特率设置:
`timescale 1 ns / 1 ns
module uart_receiver#(
parameter BAUD_RATE = 115200
)
(
input clk,
input rst_n,
input clken_16bps,
input rxd,
output reg [7:0] rxd_data,
output reg rxd_flag
);
状态机与计数器定义
localparam R_IDLE = 2'd0;
localparam R_START = 2'd1;
localparam R_SAMPLE = 2'd2;
localparam R_STOP = 2'd3;
reg [1:0] rxd_state;
reg [3:0] rxd_cnt;
reg [3:0] smp_cnt;
localparam SMP_TOP = 4'd15;
localparam SMP_CENTER = (BAUD_RATE < 115200)?4'd3:4'd7;
- 定义了 UART 接收状态机的四个状态:
R_IDLE(空闲状态,检测起始位)、R_START(检测起始位)、R_SAMPLE(采样 8 位数据)、R_STOP(检测停止位)。
rxd_state为状态机状态寄存器,rxd_cnt用于计数接收的数据位数,smp_cnt用于对 16 倍波特率时钟进行计数,以找到采样的中间点。
SMP_TOP表示 16 倍波特率时钟计数的最大值,SMP_CENTER根据波特率不同设置采样中间点的计数值。
实际效果:
打开串口调试工具,连接好串口typec串口。波特率设置为115200.
点击发送,即可显示。
