【UART异步串口协议及verilog实现】

UART异步串口协议

  • 1 UART
    • 1.1 数据格式
    • 1.2 波特率
  • 2 UART的发送和接收模块
    • 2.1 uart发送模块
    • 2.2 uart的接收模块

【博客首发于微信公众号《 漫谈芯片与编程》】

本篇文章介绍常用的芯片外围低速协议:UART;

1 UART

UART是异步串行传输协议,即在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换到并行数据;
UART串口协议只需要两根信号线来实现即可;一根用于发送,一根用于接收;
数据流:数据以并行形式从数据总线传输到传输UART。在发送UART从数据总线获取并行数据后,它会添加一个起始位、一个奇偶校验位和一个停止位,从而创建数据包。接下来,数据包在Tx引脚上逐位串行输出。接收UART在其Rx引脚上逐位读取数据包。然后,接收的UART将数据转换回并行形式,并删除起始位、奇偶校验位和停止位。最后,接收UART将数据包并行传输到接收端的数据总线:

1.1 数据格式

UART传输的数据格式:通常以一个起始位、若干数据位、一个可选的奇偶校验位和一个或多个停止位组成。

  • 起始位:标志一帧数据的开始;
  • 停止位:标志一帧数据的结束;
  • 数据位:标志一帧数据中的有效数据;可选5~9位,一般选择8位;
  • 校验位:标志一帧数据中的奇偶校验;
  • 停止位:标志一帧数据中的停止;
    在这里插入图片描述

1.2 波特率

波特率:表示每秒传输二进制数据的位数,单位是bps;常见波特率:9600,19200,38400,57600,115200;

2 UART的发送和接收模块

2.1 uart发送模块

//==========================================================
//--Author  : colonel
//--Date    : 11-05
//--Module  : uart_send
//--Function: uart is diviede into uart_send,uart_reciver
//==========================================================
module uart_send(
//==========================< 端口 >=========================input clk,input rst_n,input tx_en,input [8 -1:0] tx_din,output reg uart_txd
);
//==========================< 参数 >=========================
localparam  BAUD_RATE   = 9600;
localparam  CLK_FREQ    = 50000000;
localparam  BAUD_PERIOD = CLK_FREQ / BAUD_RATE;//==========================< 信号 >=========================
reg tx_en_sync0;
reg tx_en_sync1;//=========================================================
//-- tx_en_sync0/1
//=========================================================
always @(posedge clk or rst_n) beginif (!rst_n) begintx_en_sync0 <= 1'b0;tx_en_sync1 <= 1'b0;end else begintx_en_sync0 <= tx_en;tx_en_sync1 <= tx_en_sync0;end
endwire start_flag = tx_en_sync0 && !tx_en_sync1;  //pos pulse//==========================< 信号 >=========================
reg [16 -1:0]   bps_cnt;
reg [4 -1:0]    tx_cnt;//=========================================================
//-- bps_cnt, tx_cnt: 
//=========================================================
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginbps_cnt <= 'b0;end else beginif (bps_cnt < BAUD_PERIOD -1) beginbps_cnt <= bps_cnt + 1'b1;end else beginbps_cnt <= 'b0;endend
endalways @(posedge clk or negedge rst_n) beginif (!rst_n) begintx_cnt <= 'b0;end else beginif (bps_cnt==BAUD_PERIOD-1) begintx_cnt <= tx_cnt + 1'b1;end else if(start_flag)begintx_cnt <= 1'b0;end else begintx_cnt <= tx_cnt;endend
end//==========================< 信号 >=========================
reg             tx_flag;
reg [8 -1:0]    tx_data;    //floped for uart_din//=========================================================
//-- tx_flag,tx_data
//=========================================================
always @(posedge clk or negedge rst_n) beginif (!rst_n) begintx_data <= 'd0;end else beginif (start_flag) begintx_data <= tx_din;end else if (tx_cnt==4'd9 &&(bps_cnt==BAUD_PERIOD/2)) begintx_data <= 0;end else begintx_data <= tx_data;endend
endalways @(posedge clk or negedge rst_n) beginif (!rst_n) begintx_flag <= 1'b0;end else beginif (start_flag) begintx_flag <= 1'b1;end else if(tx_cnt==4'd9) begintx_flag <= 1'b0;end else begintx_flag <= tx_flag;endend
end//=========================================================
//-- uart_txd
//=========================================================always @(posedge clk or negedge rst_n) beginif (!rst_n) beginuart_txd <= 1'b1;end else beginif (tx_flag) begincase (tx_cnt)4'd0: uart_txd  <= 1'b0; 4'd1: uart_txd  <= tx_data[0]; 4'd2: uart_txd  <= tx_data[1]; 4'd3: uart_txd  <= tx_data[2]; 4'd4: uart_txd  <= tx_data[3]; 4'd5: uart_txd  <= tx_data[4]; 4'd6: uart_txd  <= tx_data[5]; 4'd7: uart_txd  <= tx_data[6]; 4'd8: uart_txd  <= tx_data[7]; 4'd9: uart_txd  <= 1'b1; default: uart_txd <= 1'b1;endcaseend else beginuart_txd <= 1'b1;endend
endendmodule

2.2 uart的接收模块

//==========================================================
//--Author  : colonel
//--Date    : 11-05
//--Module  : uart_reci
//--Function: uart is diviede into uart_send,uart_reciver
//==========================================================
module uart_reciver (
//==========================< 端口 >=========================input clk,input rst_n,input uart_rxd,output [8 -1:0] uart_txd,output rx_done
);
//==========================< 参数 >=========================
localparam  BAUD_RATE   = 9600;
localparam  CLK_FREQ    = 50000000;
localparam  BAUD_PERIOD = CLK_FREQ / BAUD_RATE;//==========================< 信号 >=========================
reg uart_rxd_r1;
reg uart_rxd_r2;//=========================================================
//-- uart_rxd_r1/2
//=========================================================
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginuart_rxd_r1 <= 1'b0;uart_rxd_r2 <= 1'b0;end else beginuart_rxd_r1 <= uart_rxd;uart_rxd_r2 <= uart_rxd_r1;end
endwire start_flag_neg = uart_rxd_r2 && !uart_rxd_r1;//==========================< 信号 >=========================
reg [16 -1:0]   bps_cnt;
reg [4 -1:0]    rx_cnt;//=========================================================
//-- bps_cnt, rx_cnt: 
//=========================================================
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginbps_cnt <= 'b0;end else beginif (bps_cnt < BAUD_PERIOD -1) beginbps_cnt <= bps_cnt + 1'b1;end else beginbps_cnt <= 'b0;endend
endalways @(posedge clk or negedge rst_n) beginif (!rst_n) beginrx_cnt <= 'b0;end else beginif (bps_cnt==BAUD_PERIOD-1) beginrx_cnt <= rx_cnt + 1'b1;end else if(start_flag_neg) beginrx_cnt <= 1'b0;end else beginrx_cnt <= rx_cnt;endend
end//==========================< 信号 >=========================
reg rx_flag;//=========================================================
//-- rx_flag
//=========================================================
always @(posedge clk or rst_n) beginif (!rst_n) beginrx_flag <= 1'b0;end else beginif (start_flag_neg) beginrx_flag <= 1'b1;end else if (rx_cnt==4'd9 && (bps_cnt==BAUD_PERIOD/2)) beginrx_flag <= 1'b0;end else beginrx_flag <= rx_flag;endend
end//==========================< 信号 >=========================
reg [8 -1:0] uart_txd_r;
//=========================================================
//-- uart_txd_r
//=========================================================
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginuart_txd_r <= 8'b0;end else beginif (rx_flag && bps_cnt==BAUD_PERIOD/2) begincase (rx_cnt)4'd1: uart_txd_r[0] <= uart_rxd_r1;4'd2: uart_txd_r[1] <= uart_rxd_r1;4'd3: uart_txd_r[2] <= uart_rxd_r1;4'd4: uart_txd_r[3] <= uart_rxd_r1;4'd5: uart_txd_r[4] <= uart_rxd_r1;4'd6: uart_txd_r[5] <= uart_rxd_r1;4'd7: uart_txd_r[6] <= uart_rxd_r1;4'd8: uart_txd_r[7] <= uart_rxd_r1;default:    ; endcaseend else beginuart_txd_r <= uart_txd_r;endend
endendmodule

以上是uart的发送和接收模块,从这里可以看出核心是维护cnt;

【REF】
1.https://www.cnblogs.com/liujinggang/p/9535366.html
2.https://blog.csdn.net/m0_61298445/article/details/125073150

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

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

相关文章

彻底解决idea不识别java项目

需求背景 下载了一个java swing的项目,通过idea导入后,项目无法识别。打开java文件,也不会报错,也不编译。 无法识别效果图 可以看到左侧的菜单,项目是没有被识别。 打开java文件,可以看到没有识别,java的图标也没有出现。 解决方法 1、打开Project Structure 2、修改…

仿真APP助力汽车零部件厂商打造核心竞争力

汽车零部件是汽车工业的基石&#xff0c;是构成车辆的基础元素。一辆汽车通常由上万件零部件组成&#xff0c;包括发动机系统、传动系统、制动系统、电子控制系统等&#xff0c;它们共同确保了汽车的安全、可靠性及高效运行。 在汽车产业快速发展的今天&#xff0c;汽车零部件…

【Nginx】前端项目开启 Gzip 压缩大幅提高页面加载速度

背景 Gzip 是一种文件压缩算法&#xff0c;减少文件大小&#xff0c;节省带宽从而提减少网络传输时间&#xff0c;网站会更快更丝滑。 // nginx roothcss-ecs-1d22:/etc/nginx# nginx -v nginx version: nginx/1.24.0// node ndde v18.20.1// dependencies "vue": …

【Linux】从零开始使用多路转接IO --- epoll

当你偶尔发现语言变得无力时&#xff0c; 不妨安静下来&#xff0c; 让沉默替你发声。 --- 里则林 --- 从零开始认识多路转接 1 epoll的作用和定位2 epoll 的接口3 epoll工作原理4 实现epollserverV1 1 epoll的作用和定位 之前提过的多路转接方案select和poll 都有致命缺点…

CSS中常见的两列布局、三列布局、百分比和多行多列布局!

目录 一、两列布局 1、前言&#xff1a; 2. 两列布局的常见用法 两列布局的元素示例&#xff1a; 代码运行后如下&#xff1a; 二、三列布局 1.前言 2. 三列布局的常见用法 三列布局的元素示例&#xff1a; 代码运行后如下&#xff1a; 三、多行多列 1.前言 2&…

DCRNN解读(论文+代码)

一、引言 作者首先提出&#xff1a;空间结构是非欧几里得且有方向性的&#xff0c;未来的交通速度受下游交通影响大于上游交通。虽然卷积神经网络&#xff08;CNN&#xff09;在部分研究中用于建模空间相关性&#xff0c;但其主要适用于欧几里得空间&#xff08;例如二维图像&a…

StandardThreadExecutor源码解读与使用(tomcat的线程池实现类)

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java源码解读-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 目录 1.前言 2.线程池基础知识回顾 2.1.线程池的组成 2.2.工作流程 2…

Unreal5从入门到精通之如何解决在VR项目在头显中卡顿的问题

前言 以前我们使用Unity开发VR,Unity提供了非常便利的插件和工具来做VR。但是由于Unity的渲染效果不如Unreal,现在我们改用Unreal来做VR了,所有的VR相关的配置和操作都要重新学习。 今天就来总结一下,我在开发VR过程中碰到的所有问题。 1.编辑器,以VR运行 默认运行方式…

centos7 kafka高可用集群安装及测试

前言 用三台虚拟机centos7 搭建高可用集群&#xff0c;及测试方法 高可用搭建的方法&#xff0c;参考&#xff1a;https://blog.csdn.net/u011197085/article/details/134070318 高可用搭建 1、安装配置zookeeper集群 下载zookeeper 注&#xff1a;zookeeper链接如果失效&a…

Redis(2):内存模型

一、Redis内存统计 工欲善其事必先利其器&#xff0c;在说明Redis内存之前首先说明如何统计Redis使用内存的情况。 在客户端通过redis-cli连接服务器后&#xff08;后面如无特殊说明&#xff0c;客户端一律使用redis-cli&#xff09;&#xff0c;通过info命令可以查看内存使用情…

C++笔试题之实现一个定时器

一.定时器&#xff08;timer&#xff09;的需求 1.执行定时任务的时&#xff0c;主线程不阻塞&#xff0c;所以timer必须至少持有一个线程用于执行定时任务 2.考虑到timer线程资源的合理利用&#xff0c;一个timer需要能够管理多个定时任务&#xff0c;所以timer要支持增删任务…

0.STM32F1移植到F0的各种经验总结

1.结构体的声明需放在函数的最前面 源代码&#xff1a; /*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启USART1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启GPIOA的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructu…

在Microsoft Outlook日历中添加多个时区

在Microsoft Outlook日历中添加多个时区 1.单击Outlook中的文件选项卡&#xff0c;单击选项 2.左侧菜单中选择日历 3.向下滚动到时区部分&#xff0c;并标记当前时区&#xff0c;比如China 4.选中“显示第二个时区”框 5.选择第二个时区并给它一个标签&#xff0c;比如Germa…

为啥学习数据结构和算法

基础知识就像是一座大楼的地基&#xff0c;它决定了我们的技术高度。而要想快速做出点事情&#xff0c;前提条件一定是基础能力过硬&#xff0c;“内功”要到位。 想要通关大厂面试&#xff0c;千万别让数据结构和算法拖了后腿 我们学任何知识都是为了“用”的&#xff0c;是为…

爬虫学习4

from threading import Thread#创建任务 def func(name):for i in range(100):print(name,i)if __name__ __main__:#创建线程t1 Thread(targetfunc,args("1"))t2 Thread(targetfunc, args("2"))t1.start()t2.start()print("我是诛仙剑")from …

【Maven】——基础入门,插件安装、配置和简单使用,Maven如何设置国内源

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 引入&#xff1a; 一&#xff1a;Maven插件的安装 1&#xff1a;环境准备 2&#xff1a;创建项目 二…

Vue中使用echarts生成地图步骤详解

1.创建容器元素 <div class"map" id"map" style"width:1000px;height:1000px;"></div> 2.Vue项目引入world.js(我这里的演示是世界地图&#xff0c;不同地图对应js文件不一样) world.js文件包含&#xff1a; 地理坐标数据&#xff…

docker安装低版本的jenkins-2.346.3,在线安装对应版本插件失败的解决方法

提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、网上最多的默认解决方法1、jenkins界面配置清华源2、替换default.json文件 二、解决低版本Jenkins在线安装插件问题1.手动下载插件并导入2.低版本jenkins在…

算法专题:栈

目录 1. 删除字符串中的所有相邻重复项 1.1 算法原理 1.2 算法代码 2. 844. 比较含退格的字符串 2.1 算法原理 2.2 算法原理 3. 基本计算器 II 3.1 算法原理 3.2 算法代码 4. 字符串解码 4.1 算法原理 4.2 算法代码 5. 验证栈序列 5.1 算法原理 5.2 算法代码 1.…

ZDH权限-扩展支持数据权限

目录 项目源码 预览地址 安装包下载地址 ZDH权限模块 ZDH权限扩展更细粒度方案 第一种方案&#xff1a; 第二种方案&#xff1a; ZDH权限扩展支持数据权限-新增属性 总结 感谢支持 项目源码 zdh_web: GitHub - zhaoyachao/zdh_web: 大数据采集,抽取平台 预览地址 后…