FPGA-结合协议时序实现UART收发器(四):串口驱动模块uart_drive、例化uart_rx、uart_tx
FPGA-结合协议时序实现UART收发器(四):串口驱动模块uart_drive、例化uart_rx、uart_tx
串口驱动模块uart_drive、例化uart_rx、uart_tx,功能实现
文章目录
- FPGA-结合协议时序实现UART收发器(四):串口驱动模块uart_drive、例化uart_rx、uart_tx
- 一、功能实现
- 二、uart_drive代码
- 总结
一、功能实现
对照代码,串口发送模块uart_drive实现功能包括:
- CLK_DIV时钟分频,将系统输入时钟分频成串口所需波特率时钟
- rst_gen_module复位产生模块,分频后的波特率时钟复位不稳定,自己产生波特率时钟复位
- r_rx_overvalue 过采样,动态时钟纠正方法,识别获取起始位位置
- r_rx_overlock 过采样锁,控制过采样开关
- r_user_rx_valid 用户接受有效,利用valid来判断valid上升沿从而判断数据接收完毕,用于控制过采样锁r_rx_overlock
- r_uart_rx_clk_rst,处理纠正后的准确时钟复位r_uart_rx_clk_rst,利用准确的复位+系统时钟产生所需要的准确的串口接收时钟
- 统一到同一时钟域中,即波特率时钟域,慢两拍
-r_user_rx_data_1 <= w_user_rx_data;
r_user_rx_data_2 <= r_user_rx_data_1;
r_user_rx_valid_1 <= w_user_rx_valid;
r_user_rx_valid_2 <= r_user_rx_valid_1;
二、uart_drive代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/09/09 13:14:22
// Design Name:
// Module Name: uart_drive
// Project Name:
// Target Devices:
// Tool Versions:
// Description: 串口数据的回环驱动模块
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module uart_drive#(//串口可调参数parameter P_SYSTEM_CLK = 50_000_000, parameter P_UART_BUADRATE = 9600,parameter P_UART_DATA_WIDTH = 8,parameter P_UART_STOP_WIDTH = 1,parameter P_UART_CHECK = 0
)( //串口驱动输入输出input i_clk ,input i_rst ,input i_uart_rx ,output o_uart_tx ,input [P_UART_DATA_WIDTH - 1 : 0] i_user_tx_data ,//用户输出数据,作为驱动的输入,即先输入到驱动处理再输出input i_user_tx_valid ,//握手output o_user_tx_ready ,output [P_UART_DATA_WIDTH - 1 : 0] o_user_rx_data ,//用户输入数据,作为驱动的输出,即先经过驱动输出再输入到用户output o_user_rx_valid ,output o_user_clk,output o_user_rst);localparam P_CLK_DIV_NUMBER = P_SYSTEM_CLK / P_UART_BUADRATE;//分频数wire w_uart_buadclk ;//串口波特率时钟线
wire w_uart_buadclk_rst ;
wire w_uart_rx_clk ;//串口接收时钟线
wire w_uart_rx_rst ;
reg r_uart_rx_clk_rst ;
reg [2:0] r_rx_overvalue ;
reg [2:0] r_rx_overvalue_1d ;//延迟1拍信号
reg r_rx_overlock ;//过采样锁,控制过采样
reg r_user_rx_valid ;//用户接收有效,用于判断可进行再次接收,即再次过采样判断起始位
wire [P_UART_DATA_WIDTH - 1 : 0] w_user_rx_data ;
wire w_user_rx_valid ;reg [P_UART_DATA_WIDTH - 1 : 0] r_user_rx_data_1 ;
reg [P_UART_DATA_WIDTH - 1 : 0] r_user_rx_data_2 ;
reg r_user_rx_valid_1 ;
reg r_user_rx_valid_2 ;//统一到同一时钟域中,即波特率时钟域
assign o_user_clk = w_uart_buadclk;
assign o_user_rst = w_uart_buadclk_rst;
assign o_user_rx_data = r_user_rx_data_2;
assign o_user_rx_valid = r_user_rx_valid_2;//分频模块,将时钟频率分频成串口波特率时钟
CLK_DIV_module#(.P_CLK_DIV_CNT (P_CLK_DIV_NUMBER) //最大为65535
)
CLK_DIV_module_u0(.i_clk (i_clk) ,//输入时钟.i_rst (i_rst) ,//high value,分配时钟的复位不准确,所以需要重新生成复位rst_gen_module.o_clk_div (w_uart_buadclk) //分频后的时钟
);//复位产生模块,因为分频时钟后复位不准确,所以自己来产生复位
rst_gen_module#(.P_RST_CYCLE (10) //复位的周期
)
rst_gen_module_u0
(.i_clk (w_uart_buadclk) ,.o_rst (w_uart_buadclk_rst));//分频模块,用于过采样计数判断起始位下降沿,用于串口接收使用
//产生能够准确获取中间数据的始终
CLK_DIV_module#(.P_CLK_DIV_CNT (P_CLK_DIV_NUMBER) //最大为65535
)
CLK_DIV_module_u1(.i_clk (i_clk) ,//输入时钟.i_rst (r_uart_rx_clk_rst) ,//初始状态高电平.o_clk_div (w_uart_rx_clk) //分频后的时钟
);uart_rx#(//串口可调参数.P_SYSTEM_CLK (P_SYSTEM_CLK ), .P_UART_BUADRATE (P_UART_BUADRATE ),.P_UART_DATA_WIDTH (P_UART_DATA_WIDTH ),.P_UART_STOP_WIDTH (P_UART_STOP_WIDTH ),.P_UART_CHECK (P_UART_CHECK )
)
uart_rx_u0( //串口驱动输入输出.i_clk (w_uart_rx_clk) ,.i_rst (w_uart_buadclk_rst) ,.i_uart_rx (i_uart_rx) , .o_user_rx_data (w_user_rx_data) ,//用户输入数据,作为驱动的输出,即先经过驱动输出再输入到用户.o_user_rx_valid (w_user_rx_valid));uart_tx#(//串口可调参数.P_SYSTEM_CLK (P_SYSTEM_CLK ),.P_UART_BUADRATE (P_UART_BUADRATE ),.P_UART_DATA_WIDTH (P_UART_DATA_WIDTH ),.P_UART_STOP_WIDTH (P_UART_STOP_WIDTH ),.P_UART_CHECK (P_UART_CHECK )
)
uart_tx_u0( //串口驱动输入输出.i_clk (w_uart_buadclk) ,.i_rst (w_uart_buadclk_rst) ,.o_uart_tx (o_uart_tx) ,.i_user_tx_data (i_user_tx_data) ,//用户输出数据,作为驱动的输入,即先输入到驱动处理再输出.i_user_tx_valid (i_user_tx_valid) ,//握手.o_user_tx_ready (o_user_tx_ready));/*
串口接收会存在亚稳态状态,虽然可以使用打两拍的方法解决,但不够稳妥,一样出现较大累计误差
故采用时钟来动态纠正,使用过采样方法来检测起始位的下降沿,产生新的分频后的时钟,使用该时钟可以保证每次读取数据时都在数据上升沿的中间位置
虽然使用时钟动态纠正方法一样会存在累计误差,但因为每次串口传输8bit数据,并且每次都进行了时钟纠正,所以足以稳定满足使用效果
*///处理过采样r_rx_overvalue,不断获取传输值
always @(posedge i_clk or posedge i_rst)
beginif(i_rst) //初始状态r_rx_overvalue <= 'd0;else if(!r_rx_overlock) //变化状态r_rx_overvalue <= {r_rx_overvalue[1:0] , i_uart_rx};//低位获取i_uart_rx再左移,此处先发低位还是先发高位影响不大,主要是进行高低电平判断起始位用else //保持状态r_rx_overvalue <= 3'b111;
end//处理过采样锁r_rx_overlock,控制过采样,因为只需要过采样起始位的位置
//通过读取三位数据来判断当前是否为起始位的位置,当前3拍全为低电平0,前3拍全为高电平1,则判断为起始位下降沿位置
always @(posedge i_clk or posedge i_rst)
beginif(i_rst)r_rx_overlock <= 'd0;else if(!w_user_rx_valid && r_user_rx_valid) //本次传输完成,可以再次进行过采样了,使用vaild判断,同样采用慢一拍来判断上升沿,当前信号r_user_rx_valid为1,前一拍信号w_user_rx_valid为0,即上升沿,表示传输完成r_rx_overlock <= 'd0;else if(r_rx_overvalue == 3'b000 && r_rx_overvalue_1d == 3'b111) //识别到起始位的位置,此时不需要再次过采样了r_rx_overlock <= 'd1;elser_rx_overlock <= r_rx_overlock;
end//处理用户接收有效信号r_user_rx_valid,用于表示本次接收数据完毕,可再次进行接收数据即再次过采样来判断起始位位置
//同样也是采用慢一拍的信号来结合判断vaild的上升沿
always @(posedge i_clk or posedge i_rst)
beginif(i_rst)r_user_rx_valid <= 'd0;elser_user_rx_valid <= w_user_rx_valid; //r_user_rx_valid比w_user_rx_valid慢一拍,即同一时刻,w_user_rx_valid为当前值,r_user_rx_valid为前一拍值
end//处理纠正后的准确时钟复位r_uart_rx_clk_rst,利用准确的复位+系统时钟产生所需要的准确的串口接收时钟
//利用准确的时钟复位作为分频模块的复位输入,输出准确的串口接收时钟,即每次都在数据位中间上升沿
always @(posedge i_clk or posedge i_rst)
beginif(i_rst)r_uart_rx_clk_rst <= 'd1;else if(r_rx_overvalue == 3'b000 && r_rx_overvalue_1d == 3'b111)//起始位时r_uart_rx_clk_rst <= 'd0;elser_uart_rx_clk_rst <= r_uart_rx_clk_rst;
end/*
//uart的rx的output与tx的输入不是同一时钟域的,需要统一到同一时钟域中
//即o_user_rx_data、o_user_rx_vaild统一到w_uart_buadclk波特率时钟域中
//因为他们的时钟频率比较相近,要求不严格,所以打两拍就算统一到波特率时钟域了!!!!!!!我目前也不太理解!!!
*/
//处理统一始终域问题,打两拍
always @(posedge w_uart_buadclk or posedge w_uart_buadclk_rst)
beginif(w_uart_buadclk_rst)beginr_user_rx_data_1 <= 'd0;r_user_rx_data_2 <= 'd0;r_user_rx_valid_1 <= 'd0;r_user_rx_valid_2 <= 'd0;endelsebeginr_user_rx_data_1 <= w_user_rx_data;r_user_rx_data_2 <= r_user_rx_data_1;r_user_rx_valid_1 <= w_user_rx_valid;r_user_rx_valid_2 <= r_user_rx_valid_1;end
endendmodule
总结
串口驱动模块uart_drive实现,功能包含实现,同时例化uart_rx、uart_tx
相关文章:
FPGA-结合协议时序实现UART收发器(四):串口驱动模块uart_drive、例化uart_rx、uart_tx
FPGA-结合协议时序实现UART收发器(四):串口驱动模块uart_drive、例化uart_rx、uart_tx 串口驱动模块uart_drive、例化uart_rx、uart_tx,功能实现 文章目录 FPGA-结合协议时序实现UART收发器(四)࿱…...
Transformers-Bert家族系列算法汇总
🤗 Transformers 提供 API 和工具,可轻松下载和训练最先进的预训练模型。使用预训练模型可以降低计算成本、碳足迹,并节省从头开始训练模型所需的时间和资源。这些模型支持不同形式的常见任务,例如: 📝 自…...
Vulnhub系列靶机---HarryPotter-Fawkes-哈利波特系列靶机-3
文章目录 信息收集主机发现端口扫描dirsearch扫描gobuster扫描 漏洞利用缓冲区溢出edb-debugger工具msf-pattern工具 docker容器内提权tcpdump流量分析容器外- sudo漏洞提权 靶机文档:HarryPotter: Fawkes 下载地址:Download (Mirror) 难易程度ÿ…...
【服务器】ASUS ESC4000-E11 安装系统
ASUS ESC4000-E11说明书 没找到 ASUS ESC4000-E11的说明书,下面是ESC4000A-E11的说明书: https://manualzz.com/doc/65032674/asus-esc4000a-e11-servers-and-workstation-user-manual 下载地址: https://www.manualslib.com/manual/231379…...
创建java文件 自动添加作者、时间等信息 – IDEA 技巧
2023 09 亲测 文章目录 效果修改位置配置信息 效果 每次创建文件的时候,自动加上作者、时间等信息 修改位置 打开:File —> Settings —> Editor —> File and Code Templates —> includes —> FileHeader 配置信息 /*** author : Java…...
第27章_瑞萨MCU零基础入门系列教程之freeRTOS实验
本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写,需要的同学可以在这里获取: https://item.taobao.com/item.htm?id728461040949 配套资料获取:https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总: ht…...
Java学习之--类和对象
💕粗缯大布裹生涯,腹有诗书气自华💕 作者:Mylvzi 文章主要内容:Java学习之--类和对象 类和对象 类的实例化: 1.什么叫做类的实例化 利用类创建一个具体的对象就叫做类的实例化! 当我们创建了…...
Unity技术手册-UGUI零基础详细教程-Canvas详解
点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…...
破天荒呀!小杜微信有名额了
写在前面 小杜粉,众所周知前面加小杜微信为好友的基本都是由名额限制的。一般都是付费进入社群且进行备注,小杜才会长期保留微信好友。主要由于,添加的人数太多了,微信账号人数名额有限。因此,小杜过一段时间…...
领域驱动设计:领域模型与代码模型的一致性
文章目录 领域对象的整理从领域模型到微服务的设计领域层的领域对象应用层的领域对象 领域对象与微服务代码对象的映射典型的领域模型非典型领域模型 DDD 强调先构建领域模型然后设计微服务,以保证领域模型和微服务的一体性,因此我们不能脱离领域模型来谈…...
TypeScript命名空间和模块
🎬 岸边的风:个人主页 🔥 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想,就是为了理想的生活 ! 目录 命名空间(Namespace) 命名空间(Namespace)使用场景 第三方库 兼容…...
C++学习笔记--函数重载(1)
文章目录 序言一、洞悉函数重载决议1.1、重载决议的基本流程1.2、Name Lookup1.2.1、Qualified Name Lookup1.2.1.1、Class Member Lookup1.2.1.2、Namespace Member Lookup 1.2.2、Unqualified Name Lookup1.2.2.1、Usual Unqualified Lookup1.2.2.2、Argument Dependant Look…...
交叉编译poco-1.9.2
目录 一、文件下载二、编译三、可能遇到的问题和解决方法3.1 error "Unknown Hardware Architecture."3.2 error Target architecture was not detected as supported by Double-Conversion一、文件下载 下载地址:poco-1.9.2 二、编译 解压目录后打开build/config/…...
C++中如何处理超长的数字(long long类型的整数都无法存储的)
C中如何处理超长的数字(long long类型的整数都无法存储的) 在 C中,如果数字超出了 long long 类型的范围,可以考虑使用字符串或第三方库(如 Boost.Multiprecision)来表示和处理超长数字。要使用第三方库需…...
RabbitMQ MQTT集群方案官方说明
RabbitMQ MQTT 官方网说明 官方地址: https://www.rabbitmq.com/mqtt.html 从3.8开始,该MQTT插件要求存在一定数量的群集节点。这意味着三分之二,五分之三,依此类推。 该插件也可以在单个节点上使用,但不支持两个节点的集群。 如…...
深圳唯创知音电子将参加IOTE 2023第二十届国际物联网展•深圳站
2023年9月20~22日,深圳唯创知音电子将在 深圳宝安国际会展中心(9号馆9B1)为您全面展示最新的芯片产品及应用方案,助力传感器行业的发展。 作为全球领先的芯片供应商之一,深圳唯创知音电子一直致力于为提供高质量、…...
《TCP/IP网络编程》阅读笔记--I/O复用
目录 1--基于I/O复用的服务器 2--select()函数 3--基于I/O复用的回声服务器端 4--send()和recv()函数的常用可选项 5--readv()和writev()函数 1--基于I/O复用的服务器 多进程服务器端具有以下缺点:当有多个客户端发起连接请求时,就会创建多个进程来…...
[C#] 允许当前应用程序通过防火墙
通常在一台装有防火墙的电脑上运行程序的场合,往往会弹出对话框提示:是否允许执行该应用程序。 我们在开发软件的时候,可以事先在软件里面设置当前软件为防火墙允许通过的软件。这样,用户在使用时就可以避开前面提到的弹框了。 在…...
帆软FineReport决策报表Tab实现方案
最近有个需求是要做首页展示,为了减少前端工作量,利用采购的帆软FineReport来实现,记录过程,方便备查。 需求 做个Tab页,实现多个页切换。 方案一、利用帆软自带切换 帆软自带的有Tab控件,可实现切换&a…...
只打印文名
CMakeLists.txt set(CMAKE_C_FLAGS "-O0 -ggdb -D__NOTDIR_FILE__$(notdir $<)") // set(CMAKE_C_FLAGS "-O0 -ggdb -D__NOTDIR_FILE__$(notdir $<) -D__FILENAME__$(subst $(dir $<),,$<)")C文件 #include <stdio.h>#ifdef __NOTDIR_…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
C++.OpenGL (20/64)混合(Blending)
混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
