当前位置: 首页 > article >正文

别再只会调库了!手把手教你用Verilog从零实现一个可配置的UART收发器(附完整代码)

从零构建可配置UART收发器的Verilog实战指南在数字电路设计中UART通用异步收发器作为最基础的串行通信协议之一其重要性不言而喻。许多工程师虽然能够熟练调用现成的UART IP核但对底层实现原理却知之甚少。本文将带领读者从零开始用Verilog实现一个完全可配置的UART收发器支持5-8位数据宽度、可调波特率和可选的奇偶校验功能。1. UART核心模块架构设计一个完整的UART系统主要由三个关键模块组成波特率发生器、发送器和接收器。我们先来看整体架构module uart_top #( parameter DATA_WIDTH 8, parameter STOP_BITS 1, parameter PARITY_EN 1, parameter CLK_FREQ 100_000_000, parameter BAUD_RATE 115200 )( input clk, input rst_n, input tx_start, input [DATA_WIDTH-1:0] tx_data, output tx_done, output tx_busy, input rx_in, output [DATA_WIDTH-1:0] rx_data, output rx_valid, output rx_error ); // 内部信号声明 wire baud_tick; wire [15:0] baud_div; // 实例化子模块 baud_generator #( .CLK_FREQ(CLK_FREQ), .BAUD_RATE(BAUD_RATE) ) u_baud_gen ( .clk(clk), .rst_n(rst_n), .baud_tick(baud_tick), .baud_div(baud_div) ); uart_tx #( .DATA_WIDTH(DATA_WIDTH), .STOP_BITS(STOP_BITS), .PARITY_EN(PARITY_EN) ) u_tx ( .clk(clk), .rst_n(rst_n), .baud_tick(baud_tick), .tx_start(tx_start), .tx_data(tx_data), .tx_out(tx_out), .tx_done(tx_done), .tx_busy(tx_busy) ); uart_rx #( .DATA_WIDTH(DATA_WIDTH), .STOP_BITS(STOP_BITS), .PARITY_EN(PARITY_EN) ) u_rx ( .clk(clk), .rst_n(rst_n), .baud_tick(baud_tick), .rx_in(rx_in), .rx_data(rx_data), .rx_valid(rx_valid), .rx_error(rx_error) ); endmodule这个顶层模块通过参数化设计实现了高度可配置性DATA_WIDTH: 数据位宽度(5-8位)STOP_BITS: 停止位数量(1或2位)PARITY_EN: 奇偶校验使能CLK_FREQ: 系统时钟频率BAUD_RATE: 波特率设置2. 波特率生成器的精确实现波特率生成器的核心是一个分频计数器它将系统时钟分频到所需的波特率时钟。这里的关键是避免累积误差module baud_generator #( parameter CLK_FREQ 100_000_000, parameter BAUD_RATE 115200 )( input clk, input rst_n, output reg baud_tick, output [15:0] baud_div ); // 计算分频系数 localparam DIVIDER CLK_FREQ / BAUD_RATE; assign baud_div DIVIDER; reg [15:0] counter; always (posedge clk or negedge rst_n) begin if (!rst_n) begin counter 0; baud_tick 0; end else begin if (counter DIVIDER - 1) begin counter 0; baud_tick 1; end else begin counter counter 1; baud_tick 0; end end end endmodule注意实际设计中需要考虑系统时钟频率与波特率的整数倍关系。当不能整除时可以采用累加器实现小数分频。3. UART发送器的状态机设计发送器采用有限状态机(FSM)实现状态转换图如下IDLE → START → DATA0 → DATA1 → ... → DATAn → PARITY → STOP1 → STOP2(可选) → IDLE对应的Verilog实现module uart_tx #( parameter DATA_WIDTH 8, parameter STOP_BITS 1, parameter PARITY_EN 1 )( input clk, input rst_n, input baud_tick, input tx_start, input [DATA_WIDTH-1:0] tx_data, output reg tx_out, output reg tx_done, output reg tx_busy ); // 状态定义 typedef enum { IDLE, START, DATA, PARITY, STOP } state_t; state_t current_state, next_state; reg [3:0] bit_counter; reg [DATA_WIDTH-1:0] data_reg; reg parity_bit; // 状态寄存器 always (posedge clk or negedge rst_n) begin if (!rst_n) current_state IDLE; else if (baud_tick) current_state next_state; end // 下一状态逻辑 always (*) begin case (current_state) IDLE: next_state tx_start ? START : IDLE; START: next_state DATA; DATA: begin if (bit_counter DATA_WIDTH - 1) next_state PARITY_EN ? PARITY : STOP; else next_state DATA; end PARITY: next_state STOP; STOP: next_state IDLE; default: next_state IDLE; endcase end // 输出逻辑 always (posedge clk or negedge rst_n) begin if (!rst_n) begin tx_out 1b1; tx_done 1b0; tx_busy 1b0; bit_counter 0; data_reg 0; parity_bit 0; end else if (baud_tick) begin case (next_state) IDLE: begin tx_out 1b1; tx_done 1b0; tx_busy 1b0; if (tx_start) begin data_reg tx_data; tx_busy 1b1; // 计算奇偶校验位 if (PARITY_EN) parity_bit ^tx_data; end end START: begin tx_out 1b0; // 起始位 bit_counter 0; end DATA: begin tx_out data_reg[bit_counter]; bit_counter bit_counter 1; end PARITY: tx_out parity_bit; STOP: begin tx_out 1b1; if (current_state STOP (STOP_BITS 1 || bit_counter 1)) tx_done 1b1; end endcase end end endmodule4. UART接收器的抗干扰设计接收器设计的关键在于起始位检测和数据的抗干扰采样。我们采用16倍过采样和多数表决机制来提高可靠性module uart_rx #( parameter DATA_WIDTH 8, parameter STOP_BITS 1, parameter PARITY_EN 1 )( input clk, input rst_n, input baud_tick, input rx_in, output reg [DATA_WIDTH-1:0] rx_data, output reg rx_valid, output reg rx_error ); // 状态定义 typedef enum { IDLE, START, DATA, PARITY, STOP } state_t; state_t current_state, next_state; reg [3:0] bit_counter; reg [DATA_WIDTH-1:0] data_reg; reg [3:0] sample_counter; reg [7:0] samples; reg parity_bit, parity_error; // 多数表决函数 function majority_vote; input [7:0] samples; begin // 统计1的个数 integer i, count; count 0; for (i 0; i 8; i i 1) if (samples[i]) count count 1; majority_vote (count 4) ? 1b1 : 1b0; end endfunction // 状态寄存器 always (posedge clk or negedge rst_n) begin if (!rst_n) current_state IDLE; else if (baud_tick) current_state next_state; end // 下一状态逻辑 always (*) begin case (current_state) IDLE: next_state (majority_vote(samples) 1b0) ? START : IDLE; START: next_state DATA; DATA: begin if (bit_counter DATA_WIDTH - 1) next_state PARITY_EN ? PARITY : STOP; else next_state DATA; end PARITY: next_state STOP; STOP: next_state IDLE; default: next_state IDLE; endcase end // 采样逻辑 always (posedge clk or negedge rst_n) begin if (!rst_n) begin samples 8hFF; sample_counter 0; end else begin if (sample_counter 15) sample_counter 0; else sample_counter sample_counter 1; // 在采样点附近采集多个样本 if (sample_counter 4 sample_counter 11) samples[sample_counter-4] rx_in; end end // 输出逻辑 always (posedge clk or negedge rst_n) begin if (!rst_n) begin rx_data 0; rx_valid 1b0; rx_error 1b0; bit_counter 0; data_reg 0; parity_bit 0; parity_error 0; end else if (baud_tick sample_counter 15) begin case (next_state) IDLE: begin rx_valid 1b0; rx_error 1b0; end START: begin bit_counter 0; parity_bit 0; end DATA: begin data_reg[bit_counter] majority_vote(samples); bit_counter bit_counter 1; // 更新奇偶校验 if (PARITY_EN) parity_bit parity_bit ^ majority_vote(samples); end PARITY: begin parity_error (majority_vote(samples) ! parity_bit); end STOP: begin if (majority_vote(samples) 1b1) begin rx_data data_reg; rx_valid 1b1; rx_error parity_error; end else begin rx_error 1b1; // 停止位错误 end end endcase end end endmodule5. 验证与调试技巧完成RTL设计后我们需要进行充分的验证。以下是一些实用的验证方法自检测试设计一个回环测试将发送端直接连接到接收端module uart_loopback_test; reg clk 0; reg rst_n 0; reg tx_start 0; reg [7:0] tx_data 0; wire tx_done; // 实例化UART uart_top u_uart ( .clk(clk), .rst_n(rst_n), .tx_start(tx_start), .tx_data(tx_data), .tx_done(tx_done), .rx_in(u_uart.tx_out), // 回环连接 .rx_data(), .rx_valid(), .rx_error() ); // 时钟生成 always #5 clk ~clk; initial begin #100 rst_n 1; #200 tx_data 8hA5; tx_start 1; #10 tx_start 0; (posedge tx_done); #1000 $finish; end endmodule波形分析要点检查波特率时钟是否准确验证起始位、数据位、停止位的时序检查奇偶校验是否正确生成和检测常见问题排查表问题现象可能原因解决方案接收不到数据波特率不匹配检查波特率分频系数计算数据错位起始位检测不准确增加过采样倍数优化多数表决逻辑偶发错误抗干扰不足增加采样点数量优化滤波算法奇偶校验错误校验位计算错误检查发送端和接收端的校验算法是否一致6. 性能优化与扩展思路基础功能实现后可以考虑以下优化和扩展方向FIFO缓冲添加FIFO可以解决数据突发问题典型实现module uart_fifo #( parameter WIDTH 8, parameter DEPTH 16 )( input clk, input rst_n, input wr_en, input [WIDTH-1:0] din, input rd_en, output [WIDTH-1:0] dout, output full, output empty ); reg [WIDTH-1:0] mem [0:DEPTH-1]; reg [4:0] wr_ptr, rd_ptr; reg [4:0] count; assign full (count DEPTH); assign empty (count 0); assign dout mem[rd_ptr[3:0]]; always (posedge clk or negedge rst_n) begin if (!rst_n) begin wr_ptr 0; rd_ptr 0; count 0; end else begin case ({wr_en, rd_en}) 2b01: if (!empty) begin rd_ptr rd_ptr 1; count count - 1; end 2b10: if (!full) begin mem[wr_ptr[3:0]] din; wr_ptr wr_ptr 1; count count 1; end 2b11: begin mem[wr_ptr[3:0]] din; wr_ptr wr_ptr 1; rd_ptr rd_ptr 1; end default: ; endcase end end endmodule自动波特率检测通过测量起始位宽度自动识别波特率多UART通道集成通过时分复用实现多通道支持DMA接口添加DMA支持以减少CPU开销7. 实际应用中的经验分享在真实的项目开发中UART模块往往会遇到各种意料之外的问题。以下是几个实际案例中的经验总结时钟域交叉问题当系统时钟与波特率时钟不同源时需要特别注意跨时钟域同步。一个简单的解决方案是在接收端使用两级触发器同步外部信号reg rx_sync1, rx_sync2; always (posedge clk or negedge rst_n) begin if (!rst_n) begin rx_sync1 1b1; rx_sync2 1b1; end else begin rx_sync1 rx_in; rx_sync2 rx_sync1; end end电磁干扰问题在工业环境中长距离UART通信容易受到干扰。除了硬件滤波外可以在软件层面增加以下处理增加起始位验证连续多个采样点都为低才确认起始位实现简单的CRC校验而不仅是奇偶校验添加超时重传机制低功耗优化对于电池供电设备可以在不通信时关闭波特率时钟使用更深的睡眠模式通过起始位唤醒动态调整波特率以降低功耗

相关文章:

别再只会调库了!手把手教你用Verilog从零实现一个可配置的UART收发器(附完整代码)

从零构建可配置UART收发器的Verilog实战指南 在数字电路设计中,UART(通用异步收发器)作为最基础的串行通信协议之一,其重要性不言而喻。许多工程师虽然能够熟练调用现成的UART IP核,但对底层实现原理却知之甚少。本文将…...

AI Agent编排平台ASDM AgentOrbit:从Docker到Kubernetes的生产级部署与管理

1. 项目概述:一个面向生产环境的AI Agent编排与管理平台如果你正在寻找一个能让你像管理服务器一样,轻松创建、部署和管理成百上千个AI Agent实例的平台,那么ASDM AgentOrbit值得你花时间深入了解。这不是一个简单的聊天机器人前端&#xff0…...

手把手教你将LIO-SAM适配6轴IMU(附UrbanNav数据集实测配置)

从9轴到6轴:LIO-SAM的IMU适配实战与UrbanNav验证 在机器人定位与建图领域,IMU(惯性测量单元)的选择往往让开发者陷入两难:9轴IMU提供更丰富的姿态信息但成本高昂且体积较大,而6轴IMU价格亲民、体积小巧却缺…...

如何快速获取同花顺问财数据:Python自动化抓取终极指南

如何快速获取同花顺问财数据:Python自动化抓取终极指南 【免费下载链接】pywencai 获取同花顺问财数据 项目地址: https://gitcode.com/gh_mirrors/py/pywencai 还在为手动导出股票数据而烦恼吗?想用Python轻松获取A股市场信息却苦于API限制&…...

硕士论文救星:手把手教你用YOLOv5+PyQt5搞定目标检测毕设(附完整代码与模板)

硕士论文实战指南:基于YOLOv5与PyQt5的目标检测系统开发全流程 对于计算机视觉方向的硕士研究生而言,毕业设计往往需要在算法改进、实验验证和系统实现三个维度同时达到学术要求。本文将拆解一个完整的目标检测毕设实现路径,从YOLOv5模型优化…...

告别横屏限制!为你的Arduino/STM32 OLED项目添加竖屏显示功能(SH1107驱动适用)

突破显示边界:SH1107 OLED竖屏显示的工程实践指南 当你在开发智能家居控制面板或便携式传感器设备时,是否曾为横屏OLED显示的文字阅读体验不佳而困扰?传统SH1107驱动芯片仅支持180度旋转,无法满足现代用户对竖屏显示的自然阅读需求…...

在线生成背景:字号层级怎么做才像「正式物料」

🎨 在线生成背景:字号层级怎么做才像「正式物料」在信息爆炸的时代,一份 「看起来就专业」 的物料能迅速赢得信任。当您在线生成报告、海报或演示文稿背景时,文字排版的字号层级是塑造这种正式感与专业度的隐形骨架。它无声地组织…...

背景图设计:两页JPG导出方案,兼顾投屏、打印与快速替换

🎨 背景图设计:两页JPG导出方案,兼顾投屏、打印与快速替换💡 一、方案核心价值与应用场景在快节奏的内容创作与商务演示中,一套即拿即用、专业美观的背景图是提升效率与质感的秘密武器。本文将深入解析 “两页JPG格式背…...

一台电脑,四人同屏:Nucleus Co-Op 分屏游戏神器完全指南

一台电脑,四人同屏:Nucleus Co-Op 分屏游戏神器完全指南 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop 还在为单机游戏无法…...

Arm GICv5架构解析:虚拟化与低延迟中断处理

1. Arm GICv5架构概述中断控制器是现代计算系统中至关重要的基础设施组件,作为处理器核心与外围设备之间的通信枢纽,它负责高效管理和分发各类异步事件。Arm Generic Interrupt Controller (GIC)架构经过多年迭代演进,GICv5版本在原有基础上进…...

AI加速器硬件软件协同设计优化实践

1. 硬件软件协同设计概述在AI加速器领域,硬件软件协同设计已成为突破性能瓶颈的关键策略。传统AI加速器设计往往将硬件和软件视为独立部分,导致计算单元与数据流之间出现严重不匹配。这种割裂的设计方式会造成两个主要问题:计算单元因等待数据…...

3分钟快速指南:MiGPT让小爱音箱秒变AI语音助手完整教程

3分钟快速指南:MiGPT让小爱音箱秒变AI语音助手完整教程 【免费下载链接】mi-gpt 🏠 将小爱音箱接入 ChatGPT 和豆包,改造成你的专属语音助手。 项目地址: https://gitcode.com/GitHub_Trending/mi/mi-gpt 还在为小爱音箱的"人工智…...

RAG 系列(十):混合检索——让召回更全面

向量检索的一个盲区 假设你的知识库里有一篇文档,内容包含这样一句话: “中文场景推荐使用 BAAI/bge-large-zh-v1.5,向量维度为 1024。” 用户问:“BAAI/bge-large-zh-v1.5 的向量维度是多少?” 你以为这是送分题——…...

魔兽争霸3终极兼容指南:5分钟解决所有现代系统问题

魔兽争霸3终极兼容指南:5分钟解决所有现代系统问题 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为魔兽争霸3在现代电脑上的各种&qu…...

Windows系统RacEngn.dll文件丢失无法启动程序解决

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…...

三步解锁网易云音乐NCM格式转换的完整技术方案

三步解锁网易云音乐NCM格式转换的完整技术方案 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾遇到过这样的困境:在网易云音乐下载的歌曲只…...

Git提交记录人性化工具:从代码日志到开发故事的转变

1. 项目概述:从代码到“人”的转变最近在折腾一个很有意思的GitHub项目,叫jehna/humanify。光看名字,你可能会有点摸不着头脑——“Humanify”,让人性化?这到底是个啥玩意儿?简单来说,这是一个能…...

ncmToMp3:打破音乐平台枷锁,让你的网易云音乐真正自由播放

ncmToMp3:打破音乐平台枷锁,让你的网易云音乐真正自由播放 【免费下载链接】ncmToMp3 网易云vip的ncm文件转mp3/flac - ncm file to mp3 or flac 项目地址: https://gitcode.com/gh_mirrors/nc/ncmToMp3 你是否曾为下载的网易云VIP音乐只能在特定…...

Windows PDF处理终极指南:Poppler预编译包零配置解决方案

Windows PDF处理终极指南:Poppler预编译包零配置解决方案 【免费下载链接】poppler-windows Download Poppler binaries packaged for Windows with dependencies 项目地址: https://gitcode.com/gh_mirrors/po/poppler-windows 还在为Windows上的PDF处理工具…...

基于Groq LPU与Llama 3.1的极速AI聊天工具全解析

1. 项目概述:一个跑在浏览器里的极速AI聊天工具 最近在折腾AI应用的时候,发现了一个挺有意思的开源项目,叫 Groq Chat 。这玩意儿本质上是一个基于浏览器的聊天界面,但它背后用的不是我们常见的OpenAI API或者本地部署的大模型…...

AetherFloat浮点架构:AI加速器的硬件革新与优化

1. AetherFloat浮点架构:AI加速器的硬件革新在AI加速器设计中,浮点计算单元一直是性能与能效的关键瓶颈。传统IEEE 754浮点标准虽然已成为通用计算的基石,但其在神经网络处理器(NPU)中的实现却面临诸多挑战:深层的对数移位器消耗大…...

GHelper:华硕笔记本性能调控的终极解决方案

GHelper:华硕笔记本性能调控的终极解决方案 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops with nearly the same functionality. Works with ROG Zephyrus, Flow, TUF, Strix, Scar, ProArt, Vivobook, Zenbook, Expertbook, …...

基于PyAutoGUI的Cursor IDE自动化:解放重复操作,提升编程效率

1. 项目概述:当Cursor遇到AutoGUI,一场效率革命如果你是一名开发者,或者经常和代码打交道,那么Cursor这款AI编程工具大概率已经躺在你的电脑里了。它确实强大,能理解上下文、生成代码、甚至重构函数。但不知道你有没有…...

Xbox成就解锁器终极指南:免费开源工具轻松获取全游戏成就

Xbox成就解锁器终极指南:免费开源工具轻松获取全游戏成就 【免费下载链接】Xbox-Achievement-Unlocker Achievement unlocker for xbox games (barely works but it does) 项目地址: https://gitcode.com/gh_mirrors/xb/Xbox-Achievement-Unlocker 还在为Xbo…...

别再死记硬背了!用XMind搞定数据库绪论,这份保姆级思维导图笔记请收好

用XMind重构数据库绪论:视觉化学习的高效方法论 第一次翻开数据库教材时,那些"三级模式"、"E-R模型"的术语像一堵密不透风的墙。直到我把它们拆解成彩色节点,在XMind里连成知识网络,才发现抽象概念背后清晰的…...

翻转课堂在工程教育中的应用:从理论到实践的范式转变

1. 翻转课堂:工程教育的一场静默革命作为一名在工程领域摸爬滚打了十几年的从业者,我亲眼见证了技术迭代的速度如何让传统的教育模式显得力不从心。最近几年,一个词在工程教育圈里被反复提及——“翻转课堂”。这听起来像是个时髦的新概念&am…...

深度解析NHSE:揭秘《动物森友会》存档编辑器的核心技术架构

深度解析NHSE:揭秘《动物森友会》存档编辑器的核心技术架构 【免费下载链接】NHSE Animal Crossing: New Horizons save editor 项目地址: https://gitcode.com/gh_mirrors/nh/NHSE NHSE(Animal Crossing: New Horizons Save Editor)是…...

5分钟实践指南:用MiGPT将小爱音箱升级为AI语音助手深度配置

5分钟实践指南:用MiGPT将小爱音箱升级为AI语音助手深度配置 【免费下载链接】mi-gpt 🏠 将小爱音箱接入 ChatGPT 和豆包,改造成你的专属语音助手。 项目地址: https://gitcode.com/GitHub_Trending/mi/mi-gpt 智能家居设备正从简单的指…...

3秒解锁百度网盘资源:baidupankey智能提取码获取终极指南

3秒解锁百度网盘资源:baidupankey智能提取码获取终极指南 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 还在为百度网盘分享链接的提取码而烦恼吗?每次遇到需要密码的资源,你是否也在各大论…...

如何在Mac上解锁QQ音乐加密文件:QMCDecode终极解决方案

如何在Mac上解锁QQ音乐加密文件:QMCDecode终极解决方案 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac,qmc0,qmc3转mp3, mflac,mflac0等转flac),仅支持macOS,可自动识别到QQ音乐下载目录,默认…...