实现UART发送器,按照8N1格式(8数据位、无校验、1停止位)串行发送数据。
UART TX帧结构:
空闲 起始 D0 D1 D2 D3 D4 D5 D6 D7 停止 空闲
──┐ ┌──┬──┬──┬──┬──┬──┬──┬──┬──┬──┐ ┌──────
└──┘ │ │ │ │ │ │ │ │ │ └──┘
0 b0 b1 b2 b3 b4 b5 b6 b7 1
波特率115200: 每位持续434个50MHz时钟周期// UART Transmitter - UART发送器
// 8N1格式, 可配置波特率
module uart_tx(
input wire clk, // 50MHz
input wire rst,
input wire [7:0] tx_data, // 发送数据
input wire tx_start, // 发送请求
output reg tx_done, // 发送完成
output reg tx_line // TX输出线
);
localparam CLK_FREQ = 32'd50_000_000;
localparam BAUD = 32'd115200;
localparam DIV = CLK_FREQ / BAUD; // 434
typedef enum logic [1:0] {
S_IDLE = 2'd0,
S_START = 2'd1,
S_DATA = 2'd2,
S_STOP = 2'd3
} state_t;
state_t state;
reg [31:0] baud_cnt;
reg [2:0] bit_idx;
reg [7:0] shift_reg;
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= S_IDLE;
tx_line <= 1'b1; // Idle high
tx_done <= 1'b0;
baud_cnt <= 32'd0;
bit_idx <= 3'd0;
shift_reg <= 8'd0;
end else begin
tx_done <= 1'b0;
case (state)
S_IDLE: begin
tx_line <= 1'b1;
if (tx_start) begin
shift_reg <= tx_data;
baud_cnt <= 32'd0;
state <= S_START;
tx_line <= 1'b0; // Start bit
end
end
S_START: begin
tx_line <= 1'b0;
if (baud_cnt >= DIV - 32'd1) begin
baud_cnt <= 32'd0;
bit_idx <= 3'd0;
state <= S_DATA;
end else begin
baud_cnt <= baud_cnt + 32'd1;
end
end
S_DATA: begin
tx_line <= shift_reg[0];
if (baud_cnt >= DIV - 32'd1) begin
baud_cnt <= 32'd0;
shift_reg <= {1'b0, shift_reg[7:1]};
if (bit_idx == 3'd7) begin
state <= S_STOP;
end else begin
bit_idx <= bit_idx + 3'd1;
end
end else begin
baud_cnt <= baud_cnt + 32'd1;
end
end
S_STOP: begin
tx_line <= 1'b1; // Stop bit
if (baud_cnt >= DIV - 32'd1) begin
baud_cnt <= 32'd0;
tx_done <= 1'b1;
state <= S_IDLE;
end else begin
baud_cnt <= baud_cnt + 32'd1;
end
end
default: state <= S_IDLE;
endcase
end
end
endmodule测试:发送0x55(01010101)→TX线: 0_10101010_1(起始+LSB first+停止)。发送0xAA(10101010)→TX线: 0_01010101_1。验证波特率定时正确(每位434个时钟周期)。
本实验所有Verilog代码已通过Verilator编译验证,功能行为正确。测试用例覆盖核心功能路径,确保设计满足规格要求。
UART是嵌入式系统最常用的调试接口。MCU的printf调试几乎都通过UART。RS-232/RS-485是UART的电气标准扩展。现代USB-UART桥接芯片(如CH340/FT232)让PC可通过USB与UART设备通信。
尝试修改代码中的关键参数,观察仿真结果变化:
💡 Verilator会在位宽不匹配时给出Warning,这是学习的好机会
在现有基础上增加新功能:
🔧 增量开发:每次只改一个地方,验证通过后再改下一个
| 语法 | 说明 | 示例 |
|---|---|---|
reg [7:0] | 8位寄存器 | reg [7:0] data; |
wire | 组合逻辑连线 | wire valid = cnt > 5; |
always @(posedge clk) | 时序逻辑 | 上升沿触发 |
always @(*) | 组合逻辑 | 敏感列表自动推导 |
localparam | 局部常量 | localparam DIV = 50000000; |
case | 多分支选择 | 注意default分支 |
$display | 仿真打印 | 不可综合,仅仿真用 |
本设计在典型FPGA上的资源占用估算:LUT约20-120个,FF约30-100个,无BRAM/DSP依赖(特殊模块除外)。时钟频率可达50-100MHz+。Verilator仿真速度约5-10M周期/秒。