fpga uart串口verilog波特率 奇偶 校验 可配置rs232 rs422 rs485代码 资料包清单: 1.uart_test:串口 Verilog altera工程代码,支持:波特率、校验位可配置,主时钟可配置。 2.uart说明书 3.quartus ii 13.0 :安装包及破解 注1:工程均带有激励testbench,工程安装好之后,仿真路径设置之后,打开,点击RTL Simulation即可开始仿真 注2:代码均为纯Verilog,没有IP 注3:可进行顶层应用指导 注4:给出的工程为quartus II 13.0,给出testbench代码,并且已经在电路板中验证过。

这年头玩FPGA不搞点串口协议都不好意思打招呼。今天要拆解的这套Verilog代码堪称串口界的瑞士军刀,支持RS232/422/485三协议通吃,波特率奇偶校验全可调。先看关键参数设置:
verilog
parameter CLK_FREQ = 50_000_000; // 主时钟50MHz
parameter BAUD_RATE = 115200; // 波特率自由配
parameter PARITY = "ODD"; // 校验位:NONE/EVEN/ODD
parameter DATA_WIDTH = 8; // 数据位5~8可调
重点看波特率生成模块。这里用了相位累加器方案,比传统计数器方案更精准。核心代码截取:
verilog
// 相位累加器实现波特率
always @(posedge clk) begin
if(!rst_n) begin
baud_cnt <= 0;
end else begin
baud_cnt <= baud_cnt + BAUD_DIV;
if(baud_cnt >= CLK_FREQ)
baud_cnt <= baud_cnt - CLK_FREQ;
end
end
assign baud_tick = (baud_cnt < BAUD_DIV); // 产生波特率脉冲
状态机设计是串口模块的灵魂。接收模块采用三级流水:
- 起始位检测
- 数据位采样
- 校验位验证
注意这个奇葩的亚稳态处理技巧:在数据位中间连续采样三次取众数。实测能有效对抗信号毛刺。
verilog
// 三重采样抗干扰
always @(posedge clk) begin
case(sample_cnt)
2'd0: sample0 <= rxd_sync;
2'd1: sample1 <= rxd_sync;
2'd2: sample2 <= rxd_sync;
endcase
end
assign data_bit = (sample0 & sample1) | (sample0 & sample2) | (sample1 & sample2);
测试环节更骚------直接用SystemVerilog写了个智能校验生成器。这坨代码会自动根据当前配置生成对应的测试序列:
verilog
// 自动生成测试数据包
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*1.5);
end
endtask
实际部署时要注意RS485的方向控制,代码里用了三态门动态切换:
verilog
assign rs485_tx = (tx_en) ? tx_data : 1'bz;
assign rs485_rx = (tx_en) ? 1'b1 : rs485_tx;
这套代码最妙的是顶层封装------通过宏定义切换协议类型。想用RS422就把下面这行注释取消:
verilog
`define RS422_MODE // 默认RS232,RS485需改硬件驱动
实测发现个骚操作:把波特率设成250k,用50MHz时钟居然能稳定跑,看来相位累加器的精度优势体现出来了。不过注意RS485长距离传输时建议适当降低波特率。

最后提醒:烧录前务必检查停止位设置。有次配置成1.5停止位结果把下位机搞崩了,后来发现是某国产芯片的硬件bug...(别问,问就是玄学)

