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

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收发器&#xff08;四&#xff09;&#xff1a;串口驱动模块uart_drive、例化uart_rx、uart_tx 串口驱动模块uart_drive、例化uart_rx、uart_tx&#xff0c;功能实现 文章目录 FPGA-结合协议时序实现UART收发器&#xff08;四&#xff09;&#xff1…...

Transformers-Bert家族系列算法汇总

&#x1f917; Transformers 提供 API 和工具&#xff0c;可轻松下载和训练最先进的预训练模型。使用预训练模型可以降低计算成本、碳足迹&#xff0c;并节省从头开始训练模型所需的时间和资源。这些模型支持不同形式的常见任务&#xff0c;例如&#xff1a; &#x1f4dd; 自…...

Vulnhub系列靶机---HarryPotter-Fawkes-哈利波特系列靶机-3

文章目录 信息收集主机发现端口扫描dirsearch扫描gobuster扫描 漏洞利用缓冲区溢出edb-debugger工具msf-pattern工具 docker容器内提权tcpdump流量分析容器外- sudo漏洞提权 靶机文档&#xff1a;HarryPotter: Fawkes 下载地址&#xff1a;Download (Mirror) 难易程度&#xff…...

【服务器】ASUS ESC4000-E11 安装系统

ASUS ESC4000-E11说明书 没找到 ASUS ESC4000-E11的说明书&#xff0c;下面是ESC4000A-E11的说明书&#xff1a; https://manualzz.com/doc/65032674/asus-esc4000a-e11-servers-and-workstation-user-manual 下载地址&#xff1a; https://www.manualslib.com/manual/231379…...

创建java文件 自动添加作者、时间等信息 – IDEA 技巧

2023 09 亲测 文章目录 效果修改位置配置信息 效果 每次创建文件的时候&#xff0c;自动加上作者、时间等信息 修改位置 打开&#xff1a;File —> Settings —> Editor —> File and Code Templates —> includes —> FileHeader 配置信息 /*** author : Java…...

第27章_瑞萨MCU零基础入门系列教程之freeRTOS实验

本教程基于韦东山百问网出的 DShanMCU-RA6M5开发板 进行编写&#xff0c;需要的同学可以在这里获取&#xff1a; https://item.taobao.com/item.htm?id728461040949 配套资料获取&#xff1a;https://renesas-docs.100ask.net 瑞萨MCU零基础入门系列教程汇总&#xff1a; ht…...

Java学习之--类和对象

&#x1f495;粗缯大布裹生涯&#xff0c;腹有诗书气自华&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;Java学习之--类和对象 类和对象 类的实例化&#xff1a; 1.什么叫做类的实例化 利用类创建一个具体的对象就叫做类的实例化&#xff01; 当我们创建了…...

Unity技术手册-UGUI零基础详细教程-Canvas详解

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…...

破天荒呀!小杜微信有名额了

写在前面 小杜粉&#xff0c;众所周知前面加小杜微信为好友的基本都是由名额限制的。一般都是付费进入社群且进行备注&#xff0c;小杜才会长期保留微信好友。主要由于&#xff0c;添加的人数太多了&#xff0c;微信账号人数名额有限。因此&#xff0c;小杜过一段时间&#xf…...

领域驱动设计:领域模型与代码模型的一致性

文章目录 领域对象的整理从领域模型到微服务的设计领域层的领域对象应用层的领域对象 领域对象与微服务代码对象的映射典型的领域模型非典型领域模型 DDD 强调先构建领域模型然后设计微服务&#xff0c;以保证领域模型和微服务的一体性&#xff0c;因此我们不能脱离领域模型来谈…...

TypeScript命名空间和模块

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 命名空间&#xff08;Namespace&#xff09; 命名空间&#xff08;Namespace&#xff09;使用场景 第三方库 兼容…...

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中如何处理超长的数字&#xff08;long long类型的整数都无法存储的&#xff09; 在 C中&#xff0c;如果数字超出了 long long 类型的范围&#xff0c;可以考虑使用字符串或第三方库&#xff08;如 Boost.Multiprecision&#xff09;来表示和处理超长数字。要使用第三方库需…...

RabbitMQ MQTT集群方案官方说明

RabbitMQ MQTT 官方网说明 官方地址: https://www.rabbitmq.com/mqtt.html 从3.8开始&#xff0c;该MQTT插件要求存在一定数量的群集节点。这意味着三分之二&#xff0c;五分之三&#xff0c;依此类推。 该插件也可以在单个节点上使用&#xff0c;但不支持两个节点的集群。 如…...

深圳唯创知音电子将参加IOTE 2023第二十届国际物联网展•深圳站

​ 2023年9月20~22日&#xff0c;深圳唯创知音电子将在 深圳宝安国际会展中心&#xff08;9号馆9B1&#xff09;为您全面展示最新的芯片产品及应用方案&#xff0c;助力传感器行业的发展。 作为全球领先的芯片供应商之一&#xff0c;深圳唯创知音电子一直致力于为提供高质量、…...

《TCP/IP网络编程》阅读笔记--I/O复用

目录 1--基于I/O复用的服务器 2--select()函数 3--基于I/O复用的回声服务器端 4--send()和recv()函数的常用可选项 5--readv()和writev()函数 1--基于I/O复用的服务器 多进程服务器端具有以下缺点&#xff1a;当有多个客户端发起连接请求时&#xff0c;就会创建多个进程来…...

[C#] 允许当前应用程序通过防火墙

通常在一台装有防火墙的电脑上运行程序的场合&#xff0c;往往会弹出对话框提示&#xff1a;是否允许执行该应用程序。 我们在开发软件的时候&#xff0c;可以事先在软件里面设置当前软件为防火墙允许通过的软件。这样&#xff0c;用户在使用时就可以避开前面提到的弹框了。 在…...

帆软FineReport决策报表Tab实现方案

最近有个需求是要做首页展示&#xff0c;为了减少前端工作量&#xff0c;利用采购的帆软FineReport来实现&#xff0c;记录过程&#xff0c;方便备查。 需求 做个Tab页&#xff0c;实现多个页切换。 方案一、利用帆软自带切换 帆软自带的有Tab控件&#xff0c;可实现切换&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_…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...