FPGA_UART

1.UART 概述 (通用异步收发传输器)


1. 基本定义

UART(Universal Asynchronous Receiver/Transmitter)是一种常见的串行通信协议,用于在设备间通过异步串行通信传输数据。它不依赖独立的时钟信号,而是通过预定义的波特率(Baud Rate) 同步数据的收发。 核心特点

  • 异步通信:无需共享时钟信号,仅通过数据线传输。
  • 全双工模式:收发双方可同时发送和接收数据(需独立TX、RX线)。
  • 灵活配置:支持自定义波特率、数据位长度、校验位、停止位等。

2. 工作原理

(1) 数据传输格式

每一帧数据包含以下部分(以典型8N1格式为例):

起始位数据位(8位)校验位(可选)停止位(1位)
1位,低电平LSB先发奇偶校验(可选)1位,高电平
  • 起始位:低电平(0)表示数据传输开始。
  • 数据位:传输的有效数据(5~9位),通常低位(LSB)先发送(如用户之前的案例)。
  • 校验位:用于简单错误检测(奇校验/偶校验/无校验)。
  • 停止位:高电平(1)表示一帧数据结束,并允许接收端校准时序。

(2) 异步同步机制

  • 波特率校准:收发双方必须使用相同的波特率(如115200、9600)。 例如:

复制

波特率115200 → 每位持续时间 ≈ 1/115200 ≈ 8.68μs

  • 数据采样:接收端在起始位下降沿触发,并在数据位中间点采样,抵消时钟偏移影响。

3. 典型应用场景

  • 微控制器与外围模块通信:如ESP8266(Wi-Fi)、GPS模块、传感器(温湿度)。
  • 调试接口:通过UART输出调试信息(常见于嵌入式开发板)。
  • 有线设备互联:旧式打印机、工业设备(如Modbus RTU协议)。
  • 信号转换:结合电平转换芯片(如MAX232)实现RS232、RS485等长距离通信。

4. 优缺点分析

优点缺点
硬件简单(仅需两根数据线)传输距离短(通常<1米)
成本低(无需复杂协议栈)无硬件错误恢复机制(需软件纠错)
广泛兼容性(几乎所有MCU支持)需严格匹配波特率(误差<3%)

5. 硬件实现关键点

  • 发送端(TX)
    • 将并行数据转为串行,按波特率逐位发送。
    • 使用分频器生成波特率时钟(如50MHz主频 → 115200波特率需分频系数:50e6 / 115200 ≈ 434)。
  • 接收端(RX)
    • 检测起始位下降沿,启动同步采样。
    • 通过移位寄存器重组串行数据为并行数据。

6. 常见问题与解决方案

  • 波特率失配: 若收发波特率差超过3%,会导致采样偏移,需重新校准。
  • 电磁干扰: 长距离使用需加屏蔽线或转换为差分信号(如RS485)。
  • 数据冲突: 全双工通信需避免同时发送,可通过流控信号(RTS/CTS)解决。

7. 主流扩展协议

  • RS-232:电平标准(±3~15V),支持更长距离(<15米)。
  • RS-485:差分信号,可多点通信(工业现场总线)。
  • USB转UART:通过芯片(如CH340、CP2102)实现USB与串口无缝衔接。

2.verilog编写

   这里需要讲解下,这里使用到50mhz的时钟, 波特率为115200,这里的50mhz的时钟是在1秒内有50_000_000个周期的数据,波特率115200是在1秒内有115200bit的传输。

   50_000_000/115200  指的是传输1bit需要传输多少个时钟周期

在写测试代码的时候,#8680 是因为 在 50_000_000/115200= 434 个时钟周期传输1bit, 而434个时钟周期每个时钟周期为20ns 434*20= 8680.

1,波形图

接收和发送都根据这个图编写就行

2.1接收模块代码

module uart_rx (
input          clk,
input          rst,
input          rx_en,
input          data_in,
output reg [7:0]  data_out,
output         uart_rx_done
);localparam   CLK   =  50_000_000,BOTE  = 115200,CNT   = CLK / BOTE ;reg             rx_en_d1;
reg             rx_en_d2;
reg             rx_flag ;
reg             rx_valid;
reg   [3:0]     rx_cnt  ;
reg  [15:0]     clk_cnt ;
reg  [7:0]      data_out_r;
reg             uart_rx_done_r;assign       uart_rx_done = uart_rx_done_r;always @(posedge clk or negedge rst )beginif (rst == 1'b1)beginrx_en_d1 <= 1'b0;rx_en_d2 <= 1'b0;endelse beginrx_en_d1 <= rx_en;rx_en_d2 <= rx_en_d1;end
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)rx_flag <= 1'b0;else if (rx_en_d1 == 1'b1 && rx_en_d2 == 1'b0)rx_flag <= 1'b1;else rx_flag <= 1'b0;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)rx_valid <= 1'b0;else if (rx_cnt == 4'd9 && clk_cnt == CNT /2 )rx_valid <= 1'b0;else if (rx_flag == 1'b1)rx_valid <= 1'b1;else;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)clk_cnt <= 16'd0;else if (clk_cnt == CNT )clk_cnt <= 16'd0;else if (rx_valid == 1'b1)clk_cnt <= clk_cnt +1'b1;else clk_cnt <= 16'd0;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)rx_cnt <= 4'd0;else if (rx_en_d1 == 1'b1 && rx_en_d2 == 1'b0)rx_cnt <= 4'd0;else if (clk_cnt == CNT) rx_cnt <= rx_cnt +1'b1;else;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)uart_rx_done_r <= 1'b0;else if (rx_valid == 1'b1) beginif (rx_cnt == 4'd9)uart_rx_done_r <= 1'b1;else uart_rx_done_r <= 4'd0;endelseuart_rx_done_r <= 1'b0;
endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)data_out_r <= 8'd0;else if (rx_valid == 1'b1   ) beginif (clk_cnt == CNT /4) case (rx_cnt )4'd1  : data_out_r[0] = data_in ; 4'd2  : data_out_r[1] = data_in ; 4'd3  : data_out_r[2] = data_in ; 4'd4  : data_out_r[3] = data_in ; 4'd5  : data_out_r[4] = data_in ; 4'd6  : data_out_r[5] = data_in ; 4'd7  : data_out_r[6] = data_in ; 4'd8  : data_out_r[7] = data_in ; default : ;endcaseelse data_out_r <= data_out_r;endelse data_out_r <= 8'd0;  endalways @ (posedge clk or negedge rst )beginif (rst == 1'b1)data_out <= 8'd0;else if (rx_cnt == 4'd9)data_out <= data_out_r;else data_out <= 8'd0;
endendmodule 

 2.2发送模块代码

module uart_tx(
input           clk,
input           rst,input           tx_en,
input   [7:0]   data_din,
output          data_out,
output          uart_tx_done );
localparam  CLK  = 50_000_000, //时钟 50_000_000 一秒 50000000个时钟周期 数据 波特率 9600 一秒9600个数据bit  5000000/9600 一个bit需要多少时钟周期 BOTE =115200,  CNT  = CLK /BOTE ;reg          tx_en_d1;
reg          tx_en_d2;
reg          start_flag;
reg          tx_valid;
reg [3:0]    tx_cnt;
reg [15:0]   clk_cnt;
reg          uart_done_r;
reg          uart_dout_r;
reg  [7:0]   data_din_r;assign     data_out  = uart_dout_r;
assign     uart_tx_done = uart_done_r;always @ (posedge clk or negedge rst) beginif (rst == 1'b1) begintx_en_d1 <= 1'b0;tx_en_d2 <= 1'b0;endelse begintx_en_d1 <=tx_en;tx_en_d2 <= tx_en_d1;end
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)data_din_r <= 8'd0;else if (tx_cnt ==4'd9 && clk_cnt == CNT /2)data_din_r <= 8'd0;else if ( tx_en_d1 == 1'b1 && tx_en_d2 == 1'b0 ) data_din_r <= data_din;else;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)start_flag <= 1'b0;else if ( tx_en_d1 == 1'b1 && tx_en_d2 == 1'b0 ) start_flag <= 1'b1;else start_flag <= 1'b0;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)tx_valid <= 1'b0;else if (start_flag == 1'b1)tx_valid <= 1'b1;else if (tx_cnt ==4'd9 && clk_cnt == CNT /2 )tx_valid <= 1'b0;else;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)clk_cnt <= 16'd0;else if (clk_cnt == CNT )clk_cnt <= 16'd0;else if (tx_valid == 1'b1)clk_cnt <= clk_cnt +1'b1;else clk_cnt <= 16'd0;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)tx_cnt <= 4'd0;else if (tx_en_d1 == 1'b1 && tx_en_d2 == 1'b0)tx_cnt <= 4'd0;else if (clk_cnt == CNT)tx_cnt <= tx_cnt +1'b1;else;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)uart_done_r <= 1'b0;else if (tx_valid == 1'b1) beginif (tx_cnt == 4'd9) uart_done_r <= 1'b1;elseuart_done_r <= 1'b0;  endelseuart_done_r <= 1'b0;
endalways @ (posedge clk or negedge rst) beginif (rst == 1'b1)uart_dout_r <= 1'b0;  else if (tx_valid == 1'b1) begincase (tx_cnt)4'd0  : uart_dout_r <= 1'b0;4'd1  : uart_dout_r <=data_din_r[0];    4'd2  : uart_dout_r <=data_din_r[1];4'd3  : uart_dout_r <=data_din_r[2];4'd4  : uart_dout_r <=data_din_r[3];4'd5  : uart_dout_r <=data_din_r[4];4'd6  : uart_dout_r <=data_din_r[5];4'd7  : uart_dout_r <=data_din_r[6];4'd8  : uart_dout_r <=data_din_r[7];       4'd9  : uart_dout_r <=1'b1;default  : ;endcaseendelseuart_dout_r <= 1'b1;  
endendmodule 

2.3顶层模块代码

module uart_top (
input          clk,
input          rst,
input          uart_data_rx,
input          rx_en,
output         uart_data_out
);wire       uart_tx_done;
wire       uart_rx_done;
wire [7:0] data_out;uart_rx uart_rx (
.clk          (clk           ),      //input                      
.rst          ( rst          ),      //input                      
.rx_en        ( rx_en ),      //input                        
.data_in      ( uart_data_rx      ),      //input                          
.data_out     ( data_out ),      //output reg [7:0]                
.uart_rx_done ( uart_rx_done )       //output                             
);uart_tx uart_tx(
.clk          ( clk           ),  //input                      
.rst          ( rst           ),  //input                             
.tx_en        ( uart_rx_done  ),  //input                        
.data_din     ( data_out      ),  //input   [7:0]                    
.data_out     ( uart_data_out ),  //output                          
.uart_tx_done ( uart_tx_done  )  //output                              );endmodule 

2.4仿真模块代码

module uart_tb();reg clk;
reg rst;
reg  rx_en;
reg uart_data_rx;
wire uart_data_out;initial beginrst = 1'b1;clk = 1'b1;uart_data_rx = 1'b1;rx_en = 1'b0;#20rst = 1'b0;#4340uart_data_rx = 1'b0;rx_en = 1'b1;#20rx_en = 1'b0;#8680  uart_data_rx = 1'b1;#8680  uart_data_rx = 1'b0;#8680  uart_data_rx = 1'b1;#8680  uart_data_rx = 1'b0;#8680  uart_data_rx = 1'b1;#8680  uart_data_rx = 1'b0;#8680  uart_data_rx = 1'b1;#8680  uart_data_rx = 1'b0;#8680  uart_data_rx = 1'b1;endalways #10 clk = !clk;uart_top  uart_top_inst (.clk(clk),.rst(rst),.rx_en(rx_en),.uart_data_rx(uart_data_rx),.uart_data_out(uart_data_out)
);endmodule

3.仿真波形

3.1 接收模块仿真波形

 数据输入先放到低位依次传入

 

3.2 发送模块仿真波形

 发送的时候,把需要发送的数据低位先发

 

3.3 顶层模块仿真波形

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/76779.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openwrt软路由配置4--文件共享

1.安装samba opkg update opkg install luci-app-samba4安装好之后重启设备&#xff0c;系统界面服务下面会多一个network shares 2.创建磁盘分区并挂载到共享目录 openwrt刚刚安装的时候空间都是很小的&#xff0c;共享目录我是打算用来存放一些电影视频之类的大文件。所以我…

Vue ‘v-model‘ directives require the attribute value which is valid as LHS.

1、问题描述 在项目开发中&#xff0c;如果将el-checkbox组件的v-model指令改为使用三元表达式时&#xff0c;会报出【vue/valid-v-model】的错误&#xff0c;如下图所示&#xff1a; 2、分析原因 根据错误提示&#xff0c;是因为v-model指令始终把Vue实例的data视为数据真实…

基于 Qt 的 BMP 图像数据存取至 SQLite 数据库的实现

基于 Qt 的 BMP 图像数据存取至 SQLite 数据库的实现说明 本项目通过 Qt 框架实现了将 BMP 图像文件以二进制形式存入 SQLite 数据库&#xff0c;并可从数据库中读取还原为 BMP 图像文件的功能&#xff0c;适用于需要图像与结构化数据统一管理的场景。 整个流程分为两个主要部…

嵌入式基础(三)基础外设

嵌入式基础&#xff08;三&#xff09;基础外设 1.什么是UART&#xff1f;与USART有什么区别⭐⭐⭐ (1)什么是UART 通用异步收发传输器&#xff08;Universal Asynchronous Receiver/Transmitter)&#xff0c;通常称作UART。是一种异步全双工串行通信协议&#xff0c;它将要…

人力资源管理方向论文怎么写?

目录 一、人力资源管理方向论文选题 二、人力资源管理方向论文参考资料 随着经济的蓬勃发展&#xff0c;企业日益意识到引才、善用人才、留住人才对于业务发展的至关重要性。人力资源管理逐渐成为企业管理中的核心职能&#xff0c;其角色日益凸显。近年来&#xff0c;“人力资…

机器学习 从入门到精通 day_05

1. 线性回归 前面介绍了很多分类算法&#xff0c;分类的目标变量是标称型数据&#xff0c;回归是对连续型的数据做出预测。 标称型数据&#xff08;Nominal Data&#xff09;是统计学和数据分析中的一种数据类型&#xff0c;它用于分类或标记不同的类别或组别,数据点之间并没有…

神经子图同构计数

摘要 本文研究了一个新的图学习问题&#xff1a;学习计算子图同构。与其他传统的图学习问题&#xff0c;如节点分类和链接预测不同&#xff0c;子图同构计数是NP完全的&#xff0c;需要更多的全局推理来监督整个图。为了使其可扩展为大规模的图形和模式&#xff0c;我们提出了一…

开源模型应用落地-模型上下文协议(MCP)-第三方MCP Server实战指南(五)

一、前言 在AI技术高速发展的2025年,如何让大语言模型(LLM)更灵活地调用外部工具与数据,成为开发者关注的焦点。​模型上下文协议(MCP)​作为AI与外部资源的“万能接口”,通过标准化交互框架解决了传统集成中的碎片化问题。而第三方MCP Server的引入,进一步降低了开发门…

【2025年认证杯数学中国数学建模网络挑战赛】C题 数据预处理与问题一二求解

目录 【2025年认证杯数学建模挑战赛】C题数据预处理与问题一求解三、数据预处理及分析3.1 数据可视化3.2 滑动窗口相关系数统计与动态置信区间耦合分析模型3.3 耦合关系分析结果 四、问题一代码数据预处理问题一 【2025年认证杯数学建模挑战赛】C题 数据预处理与问题一求解 三…

AI Agent开发大全第二十八课-MCP实现本地命令调用怎么做的?

开篇 MCP很强大,Client端一旦实现了稳定的连接和执行流程后任Server端随意改动都可兼容,这就是热插拨功能。 如果我们仅仅满足于MCP查点网上资料、读点图片即文字型的功能肯定是不能充分发挥MCP的强大之处的,正应了Google以及Anthropic最近的研究报告上说的:不要再在chat…

AJAX原理与XMLHttpRequest

目录 一、XMLHttpRequest使用步骤 基本语法 步骤 1&#xff1a;创建 XHR 对象 步骤 2&#xff1a;调用 open() 方法 步骤 3&#xff1a;监听 loadend 事件 步骤 4&#xff1a;调用 send() 方法 二、完整示例 1. GET 请求&#xff08;带查询参数&#xff09; 2. POST 请…

python写个0~12个月宝宝喂养规划表

下载字体&#xff1a;https://github.com/adobe-fonts/source-han-sans/releases 下载fpdf2 pip uninstall fpdf pip install fpdf2运行代码 ​from fpdf import FPDF from fpdf.enums import XPos, YPos# 创建 PDF 类 class BabyFeedingPDF(FPDF):def header(self):self.s…

集中趋势描述

一、集中趋势的定义与核心目标 集中趋势指数据向其中心值聚集的倾向,反映数据的典型水平或分布中心。其核心是通过统计指标(如众数、中位数、均值)概括数据的核心特征,帮助快速理解数据分布的核心位置。 核心作用:简化复杂数据、指导业务决策(如确定用户平均消费水平)、…

【NLP】Attention机制

1.模型对比 RNN(马尔科夫链式编码) 通过递归计算逐个处理 token,当前编码结果 h t h_t ht​仅依赖前一步的隐藏状态 h t − 1 h_{t-1} ht−1​和当前输入 x t x_t xt​局限性:序列建模需严格串行,无法并行;长距离依赖易丢失(梯度消失/爆炸)例:双向 LSTM 需正向+反向两…

基于OpenCV与PyTorch的智能相册分类器全栈实现教程

引言&#xff1a;为什么需要智能相册分类器&#xff1f; 在数字影像爆炸的时代&#xff0c;每个人的相册都存储着数千张未整理的照片。手动分类不仅耗时&#xff0c;还容易遗漏重要瞬间。本文将手把手教你构建一个基于深度学习的智能相册分类系统&#xff0c;实现&#xff1a;…

活动安排问题 之 前缀和与差分

文章目录 D. Robert Hood and Mrs Hood 考虑到一个活动开始时间和结束时间s,e&#xff0c;那么可以影响到的范围就是 s-d1,e,所以我们只需对这个每一个活动可以影响到的区域进行标记即可&#xff0c;当然为了降低时间复杂度&#xff0c;我们将使用前缀和与差分 t int(input()…

C++之 多继承

在学校里有老师和学生&#xff0c;他们都是人&#xff0c;我么应该创建一个名为 Person 的基类和两个名为 Teacher 和Student 的子类&#xff0c;后两者是从前者继承来的 有一部分学生还教课挣钱&#xff08;助教&#xff09;&#xff0c;也就是同时存在着两个”是一个”关系&…

大数据学习栈记——Redis安装及其使用

本文介绍NoSQL技术&#xff1a;Redis的安装及其使用。操作系统&#xff1a;Ubuntu24.04 Redis介绍 Redis是一个键值&#xff08;key-value&#xff09;存储系统&#xff0c;即键值对非关系型数据库&#xff0c;和Memcached类似&#xff0c;目前正在被越来越多的互联网公司采用…

2024团体程序设计天梯赛L3-1 夺宝大赛

L3-037 夺宝大赛 分数 30 作者 陈越 单位 浙江大学 夺宝大赛的地图是一个由 nm 个方格子组成的长方形&#xff0c;主办方在地图上标明了所有障碍、以及大本营宝藏的位置。参赛的队伍一开始被随机投放在地图的各个方格里&#xff0c;同时开始向大本营进发。所有参赛队从一个方格…

JMeter的高并发和高频率和分布式

性能测试 模拟各种正常的、峰值的测试环境&#xff0c;检测程序的各项性能指标是否能够达标 高并发 JMeter中内置了定时器&#xff0c;可以实现时间模式相关的性能测试 需求1:同一时刻100个同学去访问学生管理系统的查询所有学院信息功能&#xff0c;统计高并发情况下平均响…