实现功能:
- FPGA实现串口接收,波特率可修改
- 按字节接收,有完成标志位输出
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
//
// 模块 1: UART 字节接收器 (修正版)
//
// 文件名: Uart_Rec.v
// 描述:
// - 用户提供的UART接收模块。
// - **FIXED**: 将系统时钟参数 CLK_FREQ 修改为 50MHz,以匹配顶层设计,
// 确保波特率计算正确。
//
//////////////////////////////////////////////////////////////////////////////////
module Uart_Rec(
input sys_clk, //系统时钟
input sys_rst_n, //系统复位,低电平有效
input uart_rxd, //UART接收端口
output reg uart_done, //接收一帧数据完成标志
output reg [7:0] uart_data //接收的数据
);
//parameter define
parameter CLK_FREQ = 50000000; // **FIXED**: 系统时钟频率为50MHz
parameter UART_BPS = 115200; // 串口波特率
localparam BPS_CNT = CLK_FREQ/UART_BPS; // 计算每个比特位的时钟周期数
//reg define
reg uart_rxd_d0;
reg uart_rxd_d1;
reg [15:0] clk_cnt;
reg [3:0] rx_cnt;
reg [7:0] rxdata;
reg rx_flag;
//wire define
wire start_flag;
assign start_flag = uart_rxd_d1 & (~uart_rxd_d0);
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart_rxd_d0 <= 1'b1;
uart_rxd_d1 <= 1'b1;
end
else begin
uart_rxd_d0 <= uart_rxd;
uart_rxd_d1 <= uart_rxd_d0;
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
rx_flag <= 1'b0;
else begin
if(start_flag)
rx_flag <= 1'b1;
else if((rx_cnt == 4'd9) && (clk_cnt == BPS_CNT/2))
rx_flag <= 1'b0;
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
clk_cnt <= 16'd0;
else if (rx_flag) begin
if (clk_cnt < BPS_CNT - 1)
clk_cnt <= clk_cnt + 1'b1;
else
clk_cnt <= 16'd0;
end
else
clk_cnt <= 16'd0;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
rx_cnt <= 4'd0;
else if (rx_flag) begin
if (clk_cnt == BPS_CNT - 1)
rx_cnt <= rx_cnt + 1'b1;
end
else
rx_cnt <= 4'd0;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
rxdata <= 8'd0;
else if(rx_flag)
if (clk_cnt == BPS_CNT/2) begin
case (rx_cnt)
4'd1 : rxdata[0] <= uart_rxd_d1;
4'd2 : rxdata[1] <= uart_rxd_d1;
4'd3 : rxdata[2] <= uart_rxd_d1;
4'd4 : rxdata[3] <= uart_rxd_d1;
4'd5 : rxdata[4] <= uart_rxd_d1;
4'd6 : rxdata[5] <= uart_rxd_d1;
4'd7 : rxdata[6] <= uart_rxd_d1;
4'd8 : rxdata[7] <= uart_rxd_d1;
default:;
endcase
end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart_data <= 8'd0;
uart_done <= 1'b0;
end
else if(rx_cnt == 4'd9 && clk_cnt == BPS_CNT/2) begin
uart_data <= rxdata;
uart_done <= 1'b1;
end
else begin
uart_done <= 1'b0;
end
end
endmodule