-
波特率发生器模块(baudrate_gen.v)
// 波特率发生器:50MHz系统时钟 → 1倍波特率时钟(可配置波特率)
module baudrate_gen #(
parameter SYS_CLK_FREQ = 50_000_000, // 系统时钟频率(默认50MHz)
parameter BAUD_RATE = 9600 // 目标波特率(默认9600)
)(
input clk, // 系统时钟
input rst_n, // 低电平复位
output reg baud_clk_1x // 1倍波特率时钟(高电平持续1个clk周期)
);// 计算分频系数:分频值 = 系统时钟频率 / 波特率
localparam DIV_NUM = SYS_CLK_FREQ / BAUD_RATE;
// 计数器位宽:足够容纳分频系数即可
localparam CNT_WIDTH = $clog2(DIV_NUM);reg [CNT_WIDTH-1:0] cnt; // 分频计数器
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
cnt <= 'd0;
baud_clk_1x <= 1'b0;
end else begin
if (cnt == DIV_NUM - 1) begin // 计数到分频值-1
cnt <= 'd0; // 计数器清零
baud_clk_1x <= 1'b1; // 生成1个clk周期的高电平脉冲
end else begin
cnt <= cnt + 1'b1; // 计数器递增
baud_clk_1x <= 1'b0; // 其余时间为低
end
end
endendmodule
-
UART 发送模块(uart_tx.v)
// UART发送模块:并行数据 → 串行UART信号
module uart_tx (
input clk, // 系统时钟
input rst_n, // 低电平复位
input baud_clk_1x, // 1倍波特率时钟
input [7:0] tx_data, // 待发送的8位并行数据
input tx_en, // 发送使能(高电平触发一次发送)
output reg tx_pin, // UART发送引脚(串行输出)
output reg tx_done // 发送完成标志
);// 状态定义
localparam IDLE = 2'b00; // 空闲状态
localparam SEND = 2'b01; // 发送状态
localparam DONE = 2'b10; // 发送完成状态// 内部寄存器
reg [1:0] state; // 状态机寄存器
reg [3:0] bit_cnt; // 位计数器(0-9:起始位+8数据位+停止位)
reg [7:0] tx_data_reg; // 数据缓存寄存器// 状态机逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
tx_pin <= 1'b1; // UART空闲时引脚为高
bit_cnt <= 4'd0;
tx_data_reg <= 8'd0;
tx_done <= 1'b0;
end else begin
case (state)
IDLE: begin
tx_done <= 1'b0;
if (tx_en) begin // 触发发送
state <= SEND;
tx_pin <= 1'b0; // 发送起始位(低电平)
bit_cnt <= 4'd1;
tx_data_reg <= tx_data;
end
endSEND: begin if (baud_clk_1x) begin // 每1个波特率时钟发送1位 // 逐位发送数据 case (bit_cnt) 4'd1: tx_pin <= tx_data_reg[0]; // 第1位:LSB 4'd2: tx_pin <= tx_data_reg[1]; 4'd3: tx_pin <= tx_data_reg[2]; 4'd4: tx_pin <= tx_data_reg[3]; 4'd5: tx_pin <= tx_data_reg[4]; 4'd6: tx_pin <= tx_data_reg[5]; 4'd7: tx_pin <= tx_data_reg[6]; 4'd8: tx_pin <= tx_data_reg[7]; // 第8位:MSB 4'd9: tx_pin <= 1'b1; // 第9位:停止位(高电平) default: ; endcase // 计数器更新 if (bit_cnt == 4'd9) begin // 停止位发送完成 state <= DONE; bit_cnt <= 4'd0; end else begin bit_cnt <= bit_cnt + 4'd1; end end end DONE: begin tx_done <= 1'b1; // 置位完成标志 state <= IDLE; // 回到空闲态 end default: state <= IDLE; endcase endend
endmodule
-
UART 接收模块(uart_rx.v)
// UART接收模块:串行UART信号 → 并行数据
module uart_rx (
input clk, // 系统时钟
input rst_n, // 低电平复位
input baud_clk_1x, // 1倍波特率时钟
input rx_pin, // UART接收引脚(串行输入)
output reg [7:0] rx_data, // 接收完成的8位并行数据
output reg rx_done // 接收完成标志
);// 状态定义
localparam IDLE = 2'b00; // 空闲状态
localparam RECV = 2'b01; // 接收状态
localparam DONE = 2'b10; // 接收完成状态// 内部寄存器
reg [1:0] state; // 状态机寄存器
reg [3:0] bit_cnt; // 位计数器(0-9:起始位+8数据位+停止位)
reg [7:0] rx_data_reg; // 数据缓存寄存器// 状态机逻辑
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= IDLE;
rx_data <= 8'd0;
rx_data_reg <= 8'd0;
bit_cnt <= 4'd0;
rx_done <= 1'b0;
end else begin
case (state)
IDLE: begin
rx_done <= 1'b0;
// 检测起始位(低电平),触发接收
if (rx_pin == 1'b0 && baud_clk_1x) begin
state <= RECV;
bit_cnt <= 4'd1; // 准备接收第1位数据
end
endRECV: begin if (baud_clk_1x) begin // 每1个波特率时钟接收1位 // 逐位接收数据(跳过起始位,接收8位数据) case (bit_cnt) 4'd1: rx_data_reg[0] <= rx_pin; // 第1位:LSB 4'd2: rx_data_reg[1] <= rx_pin; 4'd3: rx_data_reg[2] <= rx_pin; 4'd4: rx_data_reg[3] <= rx_pin; 4'd5: rx_data_reg[4] <= rx_pin; 4'd6: rx_data_reg[5] <= rx_pin; 4'd7: rx_data_reg[6] <= rx_pin; 4'd8: rx_data_reg[7] <= rx_pin; // 第8位:MSB 4'd9: ; // 停止位(仅检测,不存储) default: ; endcase // 计数器更新 if (bit_cnt == 4'd9) begin // 停止位接收完成 state <= DONE; bit_cnt <= 4'd0; rx_data <= rx_data_reg; // 输出接收的数据 end else begin bit_cnt <= bit_cnt + 4'd1; end end end DONE: begin rx_done <= 1'b1; // 置位完成标志 state <= IDLE; // 回到空闲态 end default: state <= IDLE; endcase endend
endmodule
-
UART 顶层模块(uart_top.v)
// UART顶层模块:整合波特率发生器、发送、接收模块
module uart_top #(
parameter SYS_CLK_FREQ = 50_000_000, // 系统时钟频率
parameter BAUD_RATE = 9600 // 波特率
)(
input clk, // 系统时钟
input rst_n, // 低电平复位
// 发送接口
input [7:0] tx_data, // 待发送数据
input tx_en, // 发送使能
output tx_pin, // UART发送引脚
output tx_done, // 发送完成
// 接收接口
input rx_pin, // UART接收引脚
output [7:0] rx_data, // 接收数据
output rx_done // 接收完成
);// 内部连线:波特率时钟
wire baud_clk_1x;// 例化波特率发生器
baudrate_gen #(
.SYS_CLK_FREQ(SYS_CLK_FREQ),
.BAUD_RATE(BAUD_RATE)
) u_baudrate_gen (
.clk (clk),
.rst_n (rst_n),
.baud_clk_1x(baud_clk_1x)
);// 例化UART发送模块
uart_tx u_uart_tx (
.clk (clk),
.rst_n (rst_n),
.baud_clk_1x(baud_clk_1x),
.tx_data (tx_data),
.tx_en (tx_en),
.tx_pin (tx_pin),
.tx_done (tx_done)
);// 例化UART接收模块
uart_rx u_uart_rx (
.clk (clk),
.rst_n (rst_n),
.baud_clk_1x(baud_clk_1x),
.rx_pin (rx_pin),
.rx_data (rx_data),
.rx_done (rx_done)
);endmodule