FPGA串口通信实现方案
目录
什么是串口
系统架构
UART发送模块 (TX)
UART接收模块 (RX)
波特率发生器
FIFO缓冲区
关键参数
波特率计算
器波特率发生
串口帧结构波形图
UART发送模块
UART接收模块
什么是串口
串口(Serial Port),也叫串行通信接口,是一种用于在计算机与外部设备之间逐位顺序传输数据的通信接口。
-
并行通信: 同时使用多条数据线(例如 8 条、16 条、32 条)来传输数据。每个时钟周期可以传输多个比特(一个字节或更多)。速度快,但线缆复杂、成本高、易受干扰、传输距离短。典型的并行接口如早期的打印机接口(LPT 端口)。
-
串行通信: 只使用一条数据线(或者一对差分线)来传输数据。数据的所有比特按照顺序,一个接一个地在这条线上发送出去。速度相对并行慢,但线缆简单(最少只需要 2-3 根线:发送、接收、地线)、成本低、抗干扰能力强、传输距离远。
关键组成部分
串口协议通常涵盖以下层面:
-
物理层 (硬件接口标准 & 电气特性):
-
RS-232: 最经典标准,使用±3V至±15V电平(负逻辑:+3~+15V = 0, -3~-15V = 1),常见于老式电脑、工控设备。传输距离短(<15米),点对点连接。
-
RS-422: 差分信号(平衡传输),抗干扰强,全双工,点对多点(1主多从),传输距离长(可达1200米)。
-
RS-485: RS-422的扩展,半双工或全双工,真正的多点总线(多主多从),广泛用于工业自动化(Modbus RTU等)。
-
TTL UART: 芯片级电平(通常 0V = 0, 3.3V/5V = 1),距离极短(板级或短电缆)。需要电平转换芯片(如MAX232)才能连接RS-232设备。
-
-
数据链路层 (帧格式 & 时序):
-
UART (Universal Asynchronous Receiver/Transmitter): 这是最核心的异步串行通信协议引擎。它定义了数据的打包和解包方式,但不包括物理电平。
-
关键参数 (双方必须严格匹配):
-
波特率 (Baud Rate): 每秒传输的符号数(通常等同于比特率bps)。常见值:9600, 19200, 38400, 57600, 115200等。误差容忍度低(通常<3%)。
-
数据位 (Data Bits): 每个数据帧的有效数据长度(通常7或8位)。
-
停止位 (Stop Bits): 标志数据帧结束(通常1位,有时1.5或2位)。
-
校验位 (Parity Bit): 简单的错误检测机制(奇校验/偶校验/无校验)。
-
流控制 (Flow Control): 管理发送速率,防止接收方溢出(硬件RTS/CTS, 软件
-
-
系统架构
UART发送模块 (TX)
将并行数据转换为串行输出,添加起始位、停止位和可选的校验位。
UART接收模块 (RX)
采样串行输入,检测起始位,提取数据位,验证停止位和校验位。
波特率发生器
通过分频产生精确的波特率时钟,支持多种常用波特率。
FIFO缓冲区
解决发送端和接收端速度不匹配问题,提高系统稳定性。
关键参数
参数 | 值 | 说明 |
---|---|---|
波特率 | 115200 bps | 可配置为9600, 19200, 38400等 |
数据位 | 8位 | 支持5-9位数据位 |
停止位 | 1位 | 支持1、1.5、2位停止位 |
校验位 | 无 | 支持奇校验、偶校验、无校验 |
系统时钟 | 50 MHz | FPGA主时钟频率 |
FIFO深度 | 16字节 | 发送和接收缓冲区大小 |
波特率计算
分频系数 = 系统时钟频率 / 波特率
50,000,000 / 115200 ≈ 434
器波特率发生
module baud_gen
( input clk, input reset, input [15:0] baud_rate, output reg baud_tick );
reg [15:0] counter;
always @(posedge clk or posedge reset) begin if (reset) begin counter <= 0;
baud_tick <= 0;
end else if (counter == baud_rate - 1) begin counter <= 0;
baud_tick <= 1;
end else begin counter <= counter + 1;
baud_tick <= 0;
end end endmodule
串口帧结构波形图
UART发送模块
module uart_tx( input clk, reset,
input [7:0] data_in, input data_valid,
input baud_tick, output reg tx, output reg tx_busy );
reg [3:0] state; reg [3:0] bit_count;
reg [7:0] data_reg;
parameter IDLE = 0, START = 1, DATA = 2, STOP = 3;
always @(posedge clk or posedge reset)
begin if (reset)begin state <= IDLE;
tx <= 1'b1; // 空闲状态高电平
tx_busy <= 0;
end else if (baud_tick)begin
case (state)
IDLE: begin tx <= 1'b1;
tx_busy <= 0;
if (data_valid)
begin state <= START;data_reg <= data_in;
tx_busy <= 1;
end end START:
begin tx <= 1'b0; // 起始位
bit_count <= 0;state <= DATA;
end
DATA: begin tx <= data_reg[bit_count];
if (bit_count == 7)
begin state <= STOP;
endelse beginbit_count <= bit_count + 1;
end
end
STOP: begin tx <= 1'b1; // 停止位
state <= IDLE;
end
endcase
end
end endmodule
UART接收模块
module uart_rx( input clk, reset, input rx,
baud_tick, output reg [7:0] data_out,
output reg data_valid );
reg [3:0] state;
reg [3:0] bit_count;
reg [7:0] data_reg; reg [3:0]
sample_count;
parameter
IDLE = 0,
START = 1,
DATA = 2,
STOP = 3;
always @(posedge clk or posedge reset)
begin if (reset)
begin state <= IDLE;
data_out <= 0;
data_valid <= 0;
end
else if (baud_tick)
begin case (state)
IDLE: begin data_valid <= 0;
if (!rx) begin // 检测起始位
state <= START;
sample_count <= 0;
end
end
START:
begin if (sample_count == 7)
begin // 在起始位中间采样
if (!rx) begin // 确认起始位
state <= DATA;
bit_count <= 0;
sample_count <= 0;
end
else begin
state <= IDLE;
end end else begin sample_count <= sample_count + 1;
end end DATA:
begin if (sample_count == 15) begin // 在数据位中间采样
data_reg[bit_count] <= rx; sample_count <= 0;
if (bit_count == 7) begin state <= STOP;
end
else begin
bit_count <= bit_count + 1;
end
end
else
begin sample_count <= sample_count + 1;
end
end STOP:
begin if (sample_count == 15) begin data_out <= data_reg; // 锁存数据
data_valid <= 1; // 数据有效
state <= IDLE;
end e
lse
begin
sample_count <= sample_count + 1;
end
end
endcase
end
end endmodule