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

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

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

相关文章

蓝桥杯官网练习题(灌溉)

题目描述 小蓝负责花园的灌溉工作。 花园可以看成一个 n 行 m 列的方格图形。中间有一部分位置上安装有出水管。 小蓝可以控制一个按钮同时打开所有的出水管&#xff0c;打开时&#xff0c;有出水管的位置可以被认为已经灌溉好。 每经过一分钟&#xff0c;水就会向四面扩展…

【MySQL系列】MySQL的用户管理

「前言」文章内容大致是MySQL的用户管理。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、用户管理1.1 用户信息1.2 创建新用户1.3 删除用户1.4 修改用户密码 二、数据库的权限2.1 给用户授权2.2 回收用户权限 一、用户管理 MySQL与Linux类似&#x…

NAT(网络地址转换)

文章目录 一、产生背景二、公有地址和私有地址三、定义四、分类五、常用命令 首先可以看下思维导图&#xff0c;以便更好的理解接下来的内容。 一、产生背景 IPv4公网地址资源耗尽&#xff1a; 由于IPv4地址空间有限&#xff0c;公网IPv4地址资源逐渐耗尽&#xff0c;导致难以分…

基于Android的生鲜农产品商城交易设计与实现

摘 要 人们生活水平随着发展不断的提升&#xff0c;人们对生鲜产品消费比越来越依赖&#xff0c;都希望吃到新鲜的食品。消费的加大给生鲜了全新的供应链及销售模式&#xff0c;那种传统的生鲜配送模式也在发生着变化。生鲜系统电商平台在我国目前是属于盛行的电商行业&#x…

分布式锁的3种实现!附代码

分布式锁是一种用于保证分布式系统中多个进程或线程同步访问共享资源的技术。同时它又是面试中的常见问题&#xff0c;所以我们本文就重点来看分布式锁的具体实现&#xff08;含实现代码&#xff09;。 在分布式系统中&#xff0c;由于各个节点之间的网络通信延迟、故障等原因…

如何将pdf文件变小?三招学会pdf文件压缩

在日常工作和生活中&#xff0c;我们常常需要处理大量的PDF文件&#xff0c;然而&#xff0c;有时候这些文件的大小会成为问题&#xff0c;比如文件太大无法通过邮件发送、在线上传&#xff0c;或者在手机上打开时读取缓慢等&#xff0c;为了解决这些问题&#xff0c;我们需要将…

PN结解释

基本原理 PN结由P和N组成 硅掺杂硼&#xff0c;缺少电子&#xff0c;显正电&#xff0c;就是P&#xff08;Positive&#xff09; 硅掺杂磷&#xff0c;多出电子&#xff0c;显负电&#xff0c;就是N&#xff08;Negative&#xff09; 将P和N拼接 左边代表游离的电子&#xf…

flex布局学习笔记

flex布局 推荐网址&#xff1a;弹性框完整指南 |CSS-Tricks - CSS-Tricks 基础知识和术语 由于flexbox是一个完整的模块&#xff0c;而不是一个单一的属性&#xff0c;它涉及很多事情&#xff0c;包括它的整套属性。其中一些应该在容器&#xff08;父元素&#xff0c;称为“…

这些嵌入式系统安全性的知识你需要了解

这可能是 工程师在面对嵌入式系统应用程序的安全性时可能提出的第一个问题。 不幸的是&#xff0c;有大量的“安全软件包”可用&#xff0c;并且对安全性不熟悉的嵌入式工程师可能只将安全性称为加密或病毒防护。尽管加密是安全性的一种工具&#xff0c;而病毒扫描程序从技术上…

Python爬虫实现(requests、BeautifulSoup和selenium)

Python爬虫实现&#xff08;requests、BeautifulSoup和selenium&#xff09; requests实现 Python requests 是一个常用的 HTTP 请求库&#xff0c;可以方便地向网站发送 HTTP 请求&#xff0c;并获取响应结果。 下载requests库 pip install requests 实例&#xff1a; # 导…

基于Android系统图书管理系统

摘要 随着移动终端使用率的快速增加&#xff0c;Android智能产品已日益成为越来越多的人们选择的移动终端产品。伴随着Android智能手机与平板电脑已经在我们生活大量的使用&#xff0c;越来越多的基于Android开发平台的应用也随之产生。 便捷的图书检索和借阅&#xff1a;用户可…

ACL(访问控制列表)

文章目录 一、ACL定义常见功能 二、基于ACL的包过滤定义包过滤的方向包过滤的工作流程注意事项 三、ACL分类四、常用命令 首先可以看下思维导图&#xff0c;以便更好的理解接下来的内容。 一、ACL 定义 ACL&#xff0c;也称为访问控制列表&#xff0c;是一种网络安全工具&…

【爬虫】8.1. 深度使用tesseract-OCR技术识别图形验证码

深度使用tesseract-OCR技术识别图形验证码 文章目录 深度使用tesseract-OCR技术识别图形验证码1. OCR技术2. 准备工作3. 简单作用了解3.1. 验证码图片爬取-screenshot_as_png3.2. 识别测试-image_to_string3.2.1. 正确识别3.2.2. 错误识别3.2.3. 灰度调节 3.3. 识别实战-使用im…

卫星地图-航拍影像-叠加配准套合(ArcGIS版)

卫星地图-航拍影像-叠加配准套合(ArcGIS版) 发布时间&#xff1a;2018-01-17 版权&#xff1a;BIGEMAP 第一步 工具准备 BIGEMAP地图下载器&#xff1a;Bigemap系列产品-GIS行业基础软件kml\shp 相关教程&#xff1a;CAD文件直接导入BIGEMAP进行套合配准&#xff08;推荐&am…

TC测试自动化Shell脚本

在使用TC测试的发现手动进行丢包延迟抖动等场景的组合以及TC命令的切换效率很低&#xff0c;写了一个脚本可以提升效率&#xff0c;也可以根据自己的需求进行脚本更改&#xff01; 使用方法&#xff1a; 1&#xff09;运行sh脚本 2&#xff09;输入TC想要限制的网卡名和服务器…

IDEA 快捷键大全

目录 一、文本编辑 二、光标操作 三、文本选择 四、代码折叠 五、辅助编码 六、上下文导航 七、查找操作 八、符号导航 九、代码分析 十、运行和调试 十一、代码重构 一、文本编辑 Ctrl Shift V&#xff1a;从历史选择粘贴 Ctrl D&#xff1a;复制光标所在行 …

数字信封技术概论

数字信封技术是一种通过加密手段实现信息保密性和验证的技术&#xff0c;它在保护敏感信息传输过程中得到了广泛应用。本文将详细介绍数字信封技术的原理、实现和应用场景。 一、数字信封技术的原理 数字信封技术是一种将对称密钥通过非对称加密手段分发的方法。在数字信封中…

【Fiddler】mac m1 机器上使用 fiddler 抓取接口

mac m1 机器上使用 fiddler 抓取接口&#xff08;非虚拟机模式&#xff09; author: jwensh date:2023.09.12 文章目录 mac m1 机器上使用 fiddler 抓取接口&#xff08;非虚拟机模式&#xff09;1. 环境准备2. 进行配置3. 使用情况 1. 环境准备 想要抓取 mac 上浏览器的接口&a…

JAVA8接口使用问题

JAVA8接口使用问题 文章目录 JAVA8接口使用问题1、默认方法冲突问题&#xff08;1&#xff09;亲爹优先原则&#xff08;2&#xff09;左右为难 2、常量冲突问题 1、默认方法冲突问题 &#xff08;1&#xff09;亲爹优先原则 当一个类&#xff0c;既继承一个父类&#xff0c;…

Android10 SystemUI系列 问题合集(一)开机后发现控制中心无法全部展开,控制中心tile长按无响应

一、前言 这个问题是在笔者偶然的一次情况下遇到的,前前后后花了几个小时才找到问题根源,优化了一些时间找到了哪个改动导致了原因。下面记录一下分析过程 二、准备工作 首先需要知道,在Android10 中有一个 StatusBar 类很重要 代码路径frameworks\base\packages\System…