第二篇:UART硬件架构设计与FPGA实现
1. 模块化架构设计
1.1 系统级框图与时钟域划分
-
核心模块划分 :
发送模块(TX) :负责数据帧组装与串行输出。
接收模块(RX) :负责串行数据采样与帧解析。
波特率生成器(Baud Generator) :生成发送/接收时钟。
控制寄存器组(Control Registers) :配置数据位宽、校验模式、波特率等参数。 -
时钟域划分 :
系统时钟域(clk_sys) :主时钟,用于控制逻辑和寄存器访问。
波特率时钟域(clk_baud) :由波特率生成器分频得到,用于发送/接收时序控制。 -
跨时钟域同步策略 :
-
异步信号(如外部中断信号)需通过两级同步器(2-FF)消除亚稳态:
verilogalways @(posedge clk_sys) begin
sync_reg <= async_signal; // 第一级同步
sync_signal <= sync_reg; // 第二级同步
end
-
1.2 波特率生成器设计
-
分频器参数化建模 :
分频系数计算 :分频系数 =系统时钟频率 /(波特率 ×过采样倍数)
- 例如:系统时钟50 MHz,波特率115200,16x过采样 → 分频系数 = 50,000,000 / (115200 × 16) ≈ 27.13 → 取整为27。
-
Verilog实现 :
verilogmodule baud_generator (
input wire clk, // 系统时钟
input wire [15:0] div_value, // 分频系数
output wire baud_clk // 波特率时钟
);
reg [15:0] counter = 0;
always @(posedge clk) begin
if (counter == div_value) begin
counter <= 0;
baud_clk <= ~baud_clk;
end else begin
counter <= counter + 1;
end
end
endmodule
1.3 过采样技术(16x Oversampling)
-
抗噪声设计原理 :
接收端以波特率的16倍频率采样,通过多数表决过滤瞬时噪声。
-
实现步骤 :
- 在16个采样周期内检测起始位下降沿。
- 对每个数据位取中间3次采样(第7、8、9次)的多数值作为最终值。
-
Verilog代码片段 :
verilog// 起始位检测 always @(posedge clk_16x) begin if (rx_sync == 1'b0 && start_detected == 1'b0) begin // 检测到起始位 sample_counter <= 0; start_detected <= 1'b1; end end // 数据位采样 always @(posedge clk_16x) begin if (start_detected) begin sample_counter <= sample_counter + 1; if (sample_counter % 16 == 7) begin // 采样中点 data_shift <= {rx_sync, data_shift[7:1]}; end end end
2. 发送器(Transmitter)RTL实现
2.1 状态机设计
-
状态定义 :
IDLE :等待发送请求(发送使能信号拉高)。
START :发送起始位(逻辑0)。
DATA :依次发送数据位(LSB优先)。
PARITY :发送校验位(可选)。
STOP :发送停止位(逻辑1)。
RETURN_IDLE :返回IDLE状态,等待下一帧。 -
状态转移图 :
IDLE → (发送使能) → START → (1个波特周期) → DATA → (数据位发送完成) → PARITY → (校验位发送完成) → STOP → (停止位发送完成) → RETURN_IDLE
2.2 数据缓冲与移位寄存器
-
双缓冲设计 :
发送缓冲区(TX Buffer) :存储待发送数据,允许连续写入。
移位寄存器(Shift Register) :从缓冲区加载数据,逐位输出。 -
Verilog实现 :
verilogreg [7:0] tx_buffer; reg [7:0] shift_reg; reg tx_busy; always @(posedge clk_baud) begin if (!tx_busy && tx_enable) begin shift_reg <= tx_buffer; // 加载数据到移位寄存器 tx_busy <= 1'b1; end else if (tx_busy) begin shift_reg <= {1'b0, shift_reg[7:1]}; // 右移输出 end end
2.3 亚稳态防护
-
同步器链应用 :
外部信号(如发送使能)需跨时钟域同步:
verilogreg tx_enable_sync1, tx_enable_sync2; always @(posedge clk_baud) begin tx_enable_sync1 <= tx_enable; // 第一级同步 tx_enable_sync2 <= tx_enable_sync1; // 第二级同步 end
3. 接收器(Receiver)关键逻辑
3.1 起始位检测与毛刺滤波
-
滤波算法 :
在16x过采样下,连续3次检测到低电平视为有效起始位。 -
Verilog实现 :
verilogreg [2:0] start_samples;
always @(posedge clk_16x) begin
start_samples <= {start_samples[1:0], rx_sync};
if (start_samples == 3'b000) begin // 连续3次低电平
start_detected <= 1'b1;
end
end
3.2 数据采样点动态校准
-
中点采样策略 :
在16x过采样下,每个数据位在第7、8、9次采样点取中间值。 -
多数表决逻辑 :
verilogwire [2:0] samples = {sample7, sample8, sample9};
assign data_bit = (samples >= 2) ? 1'b1 : 1'b0; // 至少2个高电平视为1
3.3 错误检测电路
-
帧错误(Frame Error) :
停止位未检测到高电平 → 标志位置1。
verilog
always @(posedge clk_baud) begin if (stop_bit_received != 1'b1) begin frame_error <= 1'b1; end end
-
溢出错误(Overrun Error) :
接收缓冲区未读取时新数据到达 → 标志位置1。 -
奇偶校验错误(Parity Error) :
接收校验位与计算值不匹配 → 标志位置1。
4. FPGA验证方法论
4.1 基于SystemVerilog的断言验证
-
协议规则检查 :
systemverilog// 检查停止位为高电平 assert property (@(posedge clk_baud) (tx_state == STOP) |-> (txd == 1'b1) ) else $error("Stop bit error!"); // 检查奇偶校验位正确性 assert property (@(posedge clk_baud) (parity_generated == expected_parity) ) else $error("Parity error!");
4.2 自动化测试平台
-
回环测试(Loopback Test) :
将发送端(TXD)直接连接至接收端(RXD),验证数据完整性。
verilog
uart_top uut ( .clk(clk), .txd(loopback_rxd), // 发送端输出连接至接收端输入 .rxd(loopback_txd) );
-
随机化测试向量 :
systemverilogfor (int i=0; i<1000; i++) begin data = $urandom(); // 生成随机数据 send_data(data); check_received_data(data); end
4.3 时序收敛分析
-
建立/保持时间约束 :
tcl# XDC约束示例(Xilinx Vivado) create_clock -period 20 [get_ports clk] # 50MHz时钟 set_input_delay -clock clk 2 [get_ports rxd] set_output_delay -clock clk 3 [get_ports txd]
-
时序报告分析 :
确保关键路径(如状态机逻辑)满足时序要求。
附录:关键RTL代码与仿真波形
1. 发送状态机Verilog代码
verilog
typedef enum {IDLE, START, DATA, PARITY, STOP} tx_state_t;
tx_state_t current_state = IDLE;
always @(posedge clk_baud) begin
case (current_state)
IDLE:
if (tx_enable_sync2) begin
current_state <= START;
txd <= 1'b0; // 发送起始位
end
START:
current_state <= DATA;
DATA:
if (bit_counter == 7) begin
current_state <= PARITY;
end
PARITY:
current_state <= STOP;
STOP:
current_state <= RETURN_IDLE;
endcase
end
2. 仿真波形
- 起始位(低电平)→ 数据位(LSB优先)→ 停止位(高电平)。