在嵌入式系统和工业控制领域,串口通信作为最基础也最可靠的通信方式之一,其重要性不言而喻。传统方案通常使用专用串口芯片,但在FPGA中实现串口模块不仅能提高系统集成度,还能获得更大的设计灵活性。本文介绍的这套Verilog实现的万用串口模块,支持RS232、RS422和RS485三种协议,波特率、校验位等参数均可配置,堪称串口界的"瑞士军刀"。
这套代码的核心优势在于:
传统串口实现通常使用计数器分频来产生波特率时钟,但这种方案存在累积误差问题。本设计采用相位累加器方案,其数学原理类似于DDS(直接数字频率合成)技术:
code复制// 相位累加器参数计算
localparam BAUD_DIV = (CLK_FREQ * 2**16) / BAUD_RATE;
reg [31:0] baud_cnt;
相位累加器的工作原理是:每个时钟周期将BAUD_DIV值累加到baud_cnt寄存器中,当累加结果超过2^16时自动回绕。通过检测最高位的变化来产生波特率时钟脉冲,这种方法的分辨率可以达到主时钟频率的1/2^16。
实测对比数据:
接收模块采用三级流水线状态机设计,每个状态都有精确的时序控制:
起始位检测:
数据位采样:
verilog复制// 三重采样表决逻辑
assign data_bit = (sample0 & sample1) | (sample0 & sample2) | (sample1 & sample2);
校验位验证:
发送模块采用经典的移位寄存器方案,但增加了以下增强功能:
特别值得注意的是RS485方向控制逻辑:
verilog复制assign rs485_tx = (tx_en) ? tx_data : 1'bz;
assign rs485_rx = (tx_en) ? 1'b1 : rs485_tx;
这种设计确保了在发送状态时,接收端能看到确定的高电平,避免总线冲突。
通过宏定义切换不同协议模式:
verilog复制`define RS232_MODE // 默认模式
// `define RS422_MODE // 取消注释启用RS422
// `define RS485_MODE // 取消注释启用RS485
各协议的主要区别:
RS232:
RS422:
RS485:
顶层参数化设计使得模块可以灵活适配不同应用场景:
verilog复制parameter CLK_FREQ = 50_000_000; // 主时钟频率
parameter BAUD_RATE = 115200; // 波特率
parameter PARITY = "NONE"; // 校验方式
parameter DATA_WIDTH = 8; // 数据位宽
parameter STOP_BITS = 1; // 停止位数
测试平台采用SystemVerilog编写,主要特点包括:
systemverilog复制task generate_packet;
input [7:0] data;
begin
// 生成起始位
txd_ref = 0;
#BIT_TIME;
// 数据位
for(int i=0; i<DATA_WIDTH; i++) begin
txd_ref = data[i];
#BIT_TIME;
end
// 奇偶校验位
if(PARITY != "NONE") begin
txd_ref = ^data;
if(PARITY == "EVEN") txd_ref = ~txd_ref;
#BIT_TIME;
end
// 停止位
txd_ref = 1;
#(BIT_TIME*STOP_BITS);
end
endtask
在50MHz时钟下测试不同波特率的稳定性:
| 目标波特率 | 实测波特率 | 误差率 |
|---|---|---|
| 9600 | 9599.8 | 0.002% |
| 115200 | 115199.3 | 0.0006% |
| 250000 | 249998.7 | 0.0005% |
| 1000000 | 999995.2 | 0.0005% |
环境准备:
工程配置:
引脚分配:
通信不稳定:
数据错误:
RS485总线冲突:
资源优化:
时序优化:
功耗优化:
在实际项目中,这套串口模块已经成功应用于工业控制器、智能仪表和通信网关等多个领域。特别是在一个分布式采集系统中,使用RS485模式实现了1公里距离的可靠通信,连续运行3年无故障记录。