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

相关推荐
南檐巷上学3 小时前
基于FPGA的正弦信号发生器、滤波器的设计(DAC输出点数受限条件下的完整正弦波产生器)
fpga开发·数字信号处理·dsp·dds
嵌入式-老费8 小时前
Linux Camera驱动开发(fpga + csi rx/csi tx)
fpga开发
ALINX技术博客20 小时前
【202601芯动态】全球 FPGA 异构热潮,ALINX 高性能异构新品预告
人工智能·fpga开发·gpu算力·fpga
JJRainbow1 天前
SN75176 芯片设计RS-232 转 RS-485 通信模块设计原理图
stm32·单片机·嵌入式硬件·fpga开发·硬件工程
s9123601011 天前
FPGA眼图
fpga开发
北京青翼科技1 天前
【PCIe732】青翼PCIe采集卡-优质光纤卡- PCIe接口-万兆光纤卡
图像处理·人工智能·fpga开发·智能硬件·嵌入式实时数据库
minglie11 天前
verilog信号命名规范
fpga开发
XINVRY-FPGA1 天前
中阶FPGA效能红线重新划定! AMD第2代Kintex UltraScale+登场,记忆体频宽跃升5倍
嵌入式硬件·fpga开发·硬件工程·dsp开发·fpga
南檐巷上学2 天前
基于FPGA的音频信号监测识别系统
fpga开发·音频·verilog·fpga·傅立叶分析·fft·快速傅里叶变换
Aaron15882 天前
基于RFSOC的数字射频存储技术应用分析
c语言·人工智能·驱动开发·算法·fpga开发·硬件工程·信号处理