Verlog实现串口的收发功能

  1. 波特率发生器模块(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
    end

    endmodule


  1. 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
    end

    复制代码
             SEND: 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
     end

    end

    endmodule


  1. 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
    end

    复制代码
             RECV: 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
     end

    end

    endmodule


  1. 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

相关推荐
Aaron158829 分钟前
基于RFSOC的数字射频存储技术应用分析
c语言·人工智能·驱动开发·算法·fpga开发·硬件工程·信号处理
碎碎思9 小时前
当 FPGA 遇见怀旧计算:486 与 Atari ST 的硬件级重生
fpga开发
数字芯片实验室11 小时前
怎么定义芯片上的异步时钟?
单片机·嵌入式硬件·fpga开发
unicrom_深圳市由你创科技12 小时前
基于ARM+DSP+FPGA异构计算架构的高速ADC采集卡定制方案
arm开发·fpga开发
北京青翼科技13 小时前
高速采集卡丨AD 采集丨 多通道数据采集卡丨高速数据采集系统丨青翼科技FMC 子卡
图像处理·人工智能·fpga开发·信号处理·智能硬件
北京青翼科技1 天前
PCIe接口-高速模拟采集—高性能计算卡-青翼科技高品质军工级数据采集板-打造专业工业核心板
图像处理·人工智能·fpga开发·信号处理·智能硬件
dadaobusi1 天前
verilog重音符号
fpga开发
s09071361 天前
Xilinx FPGA ISERDES 使用详细介绍
fpga开发·xilinx·ddr·iserdes
虹科智能自动化2 天前
虹科分享 | SocTek IP Cores:FPGA高端网络与时间同步解决方案
fpga开发·ip核·tsn时间敏感网络
秋风战士2 天前
无线通信算法之340:信道均衡除法定标讨论
算法·fpga开发·信息与通信