Verilog 学习第五节(串口发送部分)

news/2024/4/27 10:17:41/文章来源:https://blog.csdn.net/weixin_46741734/article/details/129105310

小梅哥串口部分学习part1

  • 串口通信发送原理
  • 串口通信发送的Verilog设计与调试
  • 串口发送应用之发送数据
  • 串口发送应用之采用状态机实现多字节数据发送

串口通信发送原理

1:串口通信模块设计的目的是用来发送数据的,因此需要有一个数据输入端口
2:串口通信,支持不同的波特率,所以需要一个波特率设置端口
3:串口通信的本质就是将8位并行数据通过一根信号线,在不同的时刻传输并行数据的不同位,通过多个时刻,最终将8位并行数据全部传出
4:串口通信以1位的低电平标志串行传输的开始,待8位数据传输完成之后,在1位的高电平标志传输的结束
5:控制信号,控制并转串模块什么时候开始工作;什么时候一个数据发送完成?须有一个发送开始信号,以及一个发送完成信号
在这里插入图片描述
注:图中少了一个波特率设置端口

串口通信发送的Verilog设计与调试

1:波特率为300起对应的计算公式为1000 000 000/300=3 333 333ns
3 333 333ns/20=166 666次 对应的是18位,所以一般有关波特率设置的端口设置的最大值为18位计数
在这里插入图片描述
源代码


module uart_byte_tx(input [7:0]Data,input Send_en,input Clk,input Reset_n,input [2:0]Baud_set,output reg uart_tx,output reg Tx_done);//Baud_set=0  就让波特率=9600//Baud_set=1  就让波特率=19200//Baud_set=2  就让波特率=38400//Baud_set=3  就让波特率=57600//Baud_set=4  就让波特率=115200reg [17:0]bps_DR;always@(*)begincase(Baud_set)0:bps_DR=1000000000/9600/20;1:bps_DR=1000000000/19200/20;2:bps_DR=1000000000/38400/20;3:bps_DR=1000000000/57600/20;4:bps_DR=1000000000/115200/20;default:bps_DR=1000000000/9600/20;endcaseendwire bps_clk;assign bps_clk = (div_cnt == 1);reg [17:0]div_cnt;always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)div_cnt<=0;else if(Send_en)beginif(div_cnt==bps_DR-1)div_cnt<=0;elsediv_cnt<=div_cnt+1'b1;endelsediv_cnt<=0;endreg [3:0]bps_cnt;always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)bps_cnt<=0;else if(Send_en)beginif(bps_clk)beginif(bps_cnt==11)bps_cnt<=0;elsebps_cnt<=bps_cnt+1;endendelsebps_cnt<=1'b1;end//并串转换always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)beginuart_tx<=1'b0;Tx_done<=1'b0;endelse begincase(bps_cnt)1:begin uart_tx<=1'b0;Tx_done=1'b0;end2:uart_tx<=Data[0];3:uart_tx<=Data[1];4:uart_tx<=Data[2];5:uart_tx<=Data[3];6:uart_tx<=Data[4];7:uart_tx<=Data[5];8:uart_tx<=Data[6];9:uart_tx<=Data[7];10:uart_tx<=1'b1;11:begin uart_tx<=1'b1;Tx_done=1'b1; end default: uart_tx<=1'b1;endcaseendendendmodule

测试文件

`timescale 1ns / 1ns
module uart_byte_tx_tb();reg [7:0]Data;reg Send_en;reg Clk;reg Reset_n;reg [2:0]Baud_set;wire uart_tx;wire Tx_done;uart_byte_tx uart_byte_tx(.Data(Data),.Send_en(Send_en),.Clk(Clk),.Reset_n(Reset_n),.Baud_set(Baud_set),.uart_tx(uart_tx),.Tx_done(Tx_done));initial Clk=0;always#10 Clk=!Clk;initial beginReset_n=0;Send_en=0;Data=0;Baud_set=4;#201;Reset_n=1;Data=8'h57;Send_en=1;#20;//下面的意思是一直在等待Tx_done变量,没有等到的话就不往下进行@(posedge Tx_done);Send_en=0;#20000;Data=8'h75;Send_en=1;#20;@(posedge Tx_done);Send_en=0;#20000;$stop;endendmodule

仿真截图
在这里插入图片描述

收获:
1:在有多级if else的时候要记得加上begin end 否则可能造成识别不出来,导致结果错误~
2:在主代码中为了模拟实际电路中的赋值情况,可以设置#10代表延时时间,上面记得加`timescale 1ns/1ns,因为在下载到电路板上以及vivado识别的时候会自动略去这里的延时,但是这么写对实际电路仿真的时候却又非常有用

串口发送应用之发送数据

题目:使用上面的串口发送模块,设计一个数据发送器,每10ms以115200的波特率发送一个数据,每次发送的数据比前一个数据大一(计数器)
在这里插入图片描述
在这里插入图片描述
uart_byte_tx代码


module uart_byte_tx(input [7:0]Data,input Send_Go,input Clk,input Reset_n,input [2:0]Baud_set,output reg uart_tx,output reg Tx_done);reg Send_en;always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)Send_en<=0;else if(Send_Go)Send_en<=1;else if(Tx_done)Send_en <= 0;endreg [7:0]r_Data;always@(posedge Clk)beginif(Send_Go)r_Data<=Data;elser_Data<=r_Data;end//Baud_set=0  就让波特率=9600//Baud_set=1  就让波特率=19200//Baud_set=2  就让波特率=38400//Baud_set=3  就让波特率=57600//Baud_set=4  就让波特率=115200reg [17:0]bps_DR;always@(*)begincase(Baud_set)0:bps_DR=1000000000/9600/20;1:bps_DR=1000000000/19200/20;2:bps_DR=1000000000/38400/20;3:bps_DR=1000000000/57600/20;4:bps_DR=1000000000/115200/20;default:bps_DR=1000000000/9600/20;endcaseendwire bps_clk;assign bps_clk = (div_cnt == 1);reg [17:0]div_cnt;always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)div_cnt<=0;else if(Send_en)beginif(div_cnt==bps_DR-1)div_cnt<=0;elsediv_cnt<=div_cnt+1'b1;endelsediv_cnt<=0;endreg [3:0]bps_cnt;always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)bps_cnt<=0;else if(Send_en)beginif(bps_clk)beginif(bps_cnt==11)bps_cnt<=0;elsebps_cnt<=bps_cnt+1;endendelsebps_cnt<=1'b0;end//并串转换always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)beginuart_tx<=1'b0;endelse begincase(bps_cnt)1:uart_tx<=1'b0;2:uart_tx<=r_Data[0];3:uart_tx<=r_Data[1];4:uart_tx<=r_Data[2];5:uart_tx<=r_Data[3];6:uart_tx<=r_Data[4];7:uart_tx<=r_Data[5];8:uart_tx<=r_Data[6];9:uart_tx<=r_Data[7];10:uart_tx<=1'b1;11: uart_tx<=1'b1;default: uart_tx<=1'b1;endcaseendendalways@(posedge Clk or negedge Reset_n)beginif(!Reset_n)Tx_done<=1'b0;else if((bps_cnt==10)&&(bps_clk==1))Tx_done<=1'b1;else Tx_done<=1'b0;end
endmodule

uart_tx_test代码顶层模块


module uart_tx_test(input Clk,input Reset_n,output uart_tx);reg [7:0]Data;reg Send_Go;wire Tx_done;uart_byte_tx uart_byte_tx(.Data(Data),.Send_Go(Send_Go),.Clk(Clk),.Reset_n(Reset_n),.Baud_set(3'd4),.uart_tx(uart_tx),.Tx_done(Tx_done));//首先计时10msreg [18:0] cnt;always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)cnt<=0;else if(cnt==499999)cnt<=0;elsecnt<=cnt+1'b1;end//接着设计何时Send_Go开始发送数据always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)Send_Go<=0;else if(cnt==1)Send_Go<=1;//这里需要注意本来的Send_en是一段时间的信号,比较长,但是Send_Go属于脉冲信号就一下else Send_Go<=0;end//接着设计数据变化always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)Data<=0;else if(Tx_done)Data<=Data+1;endendmodule

uart_tx_test_tb测试文件

`timescale 1ns / 1ns
module uart_tx_test_tb();reg Clk;reg Reset_n;wire uart_tx;
uart_tx_test uart_tx_test(.Clk(Clk),.Reset_n(Reset_n),.uart_tx(uart_tx));initial Clk=0;always #10 Clk=!Clk;initial begin Reset_n=0;#201;Reset_n=1;#50000000;$stop;endendmodule

仿真截图
在这里插入图片描述

收获
1:对于一些很重要的控制信号最好单独拿出来写,参杂在一些其他功能中很可能会产生其他的影响,例如Tx_done
2:Go一般是单脉冲信号,en是电平信号

串口发送应用之采用状态机实现多字节数据发送

有些人会了8位的串口传送数据但是总会有一些问题例如,
1.ADC,采样的结果是12位的,怎么使用串口发送
2.16位的数据,怎样通过串口发送
3.有多个字节的数据通过串口发送
不能直接将8位改成12位、16位,因为UART规定了,发送的数据位只能有6、7、8位所以应该把大于8位的字节分成多个字节进行发送

三种情况:
1:没有开始发送(上一次的已经发送完成,新的40位数据的发送请求没有出现)
2:来了发送40位数据的请求信号
3:依次发送数据的状态

第一个状态:第一种情况的时候,咱干什么事情?等待传输请求(Trans_Go)的到来,Data40[7:0]给到uart_byte_tx的Data,并同时产生Send_Go信号,启动第一个字节的发送
接着应该等待,等待Tx_Done信号的到来
40位数据是否发完了?发完了,回到第一个状态继续等Trans_Go,没发完,启动下一个8位数据的发送

源代码:

//该模块完成的功能是采用状态机实现多字节数据发送
module uart_tx_data(input Clk,input Reset_n,input [39:0]Data40,input Trans_Go,//表示合适开始发送数据,即传输请求output reg Trans_Down,//表示一次40位的数据传输完成output  uart_tx);reg [7:0]Data;reg Send_Go;wire Tx_done;uart_byte_tx uart_byte_tx(.Data(Data),.Send_Go(Send_Go),.Clk(Clk),.Reset_n(Reset_n),.Baud_set(3'h4),.uart_tx(uart_tx),.Tx_done(Tx_done));reg [2:0]state;always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)beginstate<=0;Data<=0;Send_Go<=0;Trans_Down<=0;end//下面部分也可以用case语句实现,记得加default~else if(state==0)beginTrans_Down<=0;if(Trans_Go)beginData<=Data40[7:0];state<=1;Send_Go<=1;endelse beginData<=Data;state<=0;Send_Go<=0;endendelse if(state==1)beginif(Tx_done)beginData<=Data40[15:8];state<=2;Send_Go<=1;endelse beginData<=Data;state<=1;Send_Go<=0;endendelse if(state==2)beginif(Tx_done)beginData<=Data40[23:16];state<=3;Send_Go<=1;endelse beginData<=Data;state<=2;Send_Go<=0;endendelse if(state==3)beginif(Tx_done)beginData<=Data40[31:24];state<=4;Send_Go<=1;endelse beginData<=Data;state<=3;Send_Go<=0;endendelse if(state==4)beginif(Tx_done)beginData<=Data40[39:32];state<=5;Send_Go<=1;endelse beginData<=Data;state<=4;Send_Go<=0;endend        else if(state==5)beginif(Tx_done)beginstate<=0;Trans_Down<=1;Send_Go<=0;endelse beginData<=Data;state<=5;Send_Go<=0;endend                               endendmodule

测试文件:

`timescale 1ns / 1nsmodule uart_tx_data_tb();reg Clk;reg Reset_n;reg [39:0]Data40;reg Trans_Go;wire Trans_Down;wire uart_tx;uart_tx_data uart_tx_data(Clk,Reset_n,Data40,Trans_Go,//表示合适开始发送数据,即传输请求Trans_Down,//表示一次40位的数据传输完成uart_tx);initial Clk=0;always #10 Clk=!Clk;initial beginReset_n=0;Data40=0;Trans_Go=0;#201Reset_n=1;#201Data40=40'h123456789a;Trans_Go=1;@(posedge Trans_Down);Trans_Go=0;#201Data40=40'ha987654321;Trans_Go=1;@(posedge Trans_Down);#200000$stop;end
endmodule

仿真截图:
在这里插入图片描述

任务:
1:优化状态机,实现只要2个或3个状态实现发送的功能,并易于修改为发送任意个字节的数据(加个计数器进行二级验证~)
2:思考不使用状态机实现的方法

任务一代码(已进行仿真)

//该模块完成的功能是采用状态机实现多字节数据发送
module uart_tx_data2(input Clk,input Reset_n,input [39:0]Data40,input Trans_Go,//表示合适开始发送数据,即传输请求output reg Trans_Down,//表示一次40位的数据传输完成output  uart_tx);reg [7:0]Data;reg Send_Go;wire Tx_done;uart_byte_tx uart_byte_tx(.Data(Data),.Send_Go(Send_Go),.Clk(Clk),.Reset_n(Reset_n),.Baud_set(3'h4),.uart_tx(uart_tx),.Tx_done(Tx_done));reg [2:0]state;//用来记录当前发送到第几个字节了reg [2:0]cnt;always@(posedge Clk or negedge Reset_n)beginif(!Reset_n)begincnt<=0;end else if(Tx_done) beginif(cnt==4)cnt<=0;elsecnt<=cnt+1;endendalways@(posedge Clk or negedge Reset_n)beginif(!Reset_n)beginstate<=0;Data<=0;Send_Go<=0;Trans_Down<=0;end//下面部分也可以用case语句实现,记得加default~else if(state==0)beginTrans_Down<=0;if(Trans_Go)beginTrans_Down<=0;if(Tx_done)begincase(cnt)0:begin Data<=Data40[7:0]; state<=0;end 1:begin Data<=Data40[15:8];state<=0;end2:begin Data<=Data40[23:16];state<=0;end3:begin Data<=Data40[31:24];state<=0;end4:begin Data<=Data40[39:32];state<=1;enddefault:Data<=Data;endcaseSend_Go<=1;endelse beginData<=Data;state<=0;Send_Go<=0;endendend      else if(state==1)beginif(Tx_done)beginstate<=0;Trans_Down<=1;Send_Go<=0;endelse beginData<=Data;state<=1;Send_Go<=0;endend                               endendmodule

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

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

相关文章

Qt中修改界面类的类名时需要注意的几个修改点

有些时候因为一些原因&#xff0c;需要修改Qt中创建的界面类&#xff0c;需要特别注意几个修改点。 比如将test类修改为test2类 修改test.h名称为test2.h文件&#xff1b;修改test.cpp名称为test2.cpp文件&#xff1b;修改test.ui名称为test2.ui文件&#xff1b;修改pro文件中…

多层感知机的区间随机初始化方法

摘要&#xff1a; 训练是构建神经网络模型的一个关键环节&#xff0c;该过程对网络中的参数不断进行微调&#xff0c;优化模型在训练数据集上的损失函数。参数初始化是训练之前的一个重要步骤&#xff0c;决定了训练过程的起点&#xff0c;对模型训练的收敛速度和收敛结果有重要…

Java基础43 异常(Exception)

异常&#xff08;Exception&#xff09;Exception1.1 异常的概念1.2 异常体系图&#xff08;☆&#xff09;1.3 异常处理分类1.3.1 运行时异常&#xff08;☆&#xff09;1.3.2 编译时异常&#xff08;☆&#xff09;1.4 异常处理&#xff08;☆&#xff09;1.4.1 try-catch异常…

【Git】Git下载安装与使用(一)

目录 1. 前言 1.1 什么是Git 1.2 使用Git能做什么 2. Git概述 2.1 Git简介 2.2 Git下载与安装 3. Git代码托管服务 3.1 常用的Git代码托管服务 3.2 码云代码托管服务 1. 前言 1.1 什么是Git Git是一个分布式版本控制工具&#xff0c;主要用于管理开发过程中的源代码…

Cookies与Session会话技术详解

引言:日常生活中&#xff0c;人和人之间沟通交流&#xff0c;涉及到一个词----会话&#xff0c;软件中一样存在会话&#xff0c;如&#xff1a;网购登录&#xff0c;访问公司OA系统也是不断的会话&#xff0c;软件中如何管理浏览器客户端和服务端之间会话过程中的会话数据呢&am…

盘点四种自动化测试模型实例及优缺点

一&#xff0c;线性测试 1.概念&#xff1a; 通过录制或编写对应应用程序的操作步骤产生的线性脚本。单纯的来模拟用户完整的操作场景。 &#xff08;操作&#xff0c;重复操作&#xff0c;数据&#xff09;都混合在一起。 2.优点&#xff1a; 每个脚本相对独立&#xff0…

【java】java sftp传输 ,java smb传输访问共享文件夹 集成springboot

文章目录java的sftp传输sftp注意事项java smb传输smb注意事项tips: 集成springboot与不集成springboot区别不大&#xff0c;springboot中无非是引入一个maven依赖 加一个Component注解 &#xff0c; 默认是单例&#xff1b; 复制代码前 请先认真看注意事项 java的sftp传输 依赖…

网络安全态势感知研究综述

摘要&#xff1a;随着物联网、云计算和数字化的迅速发展&#xff0c;传统网络安全防护技术无法应对复杂的网络威胁。网络安全态势感知能够全面的对网络中各种活动进行辨识、理解和预测。首先分别对态势感知和网络安全态势感知的定义进行了归纳整理&#xff0c;介绍了网络安全态…

从0探索NLP——导航帖

从0探索NLP——导航帖 人工智能是一个定义宽泛、知识组成复杂的领域&#xff0c;而NLP是人工智能领域中的一类任务&#xff0c;他在哪呢&#xff1f;Emmmmm~不能说都有涉猎只能说全都都沾点&#xff1a; 每次想要针对NLP的某一点进行讲解时&#xff0c;不讲那写细枝末节&…

全链路压力测试

压力测试的目标&#xff1a; 探索线上系统流量承载极限&#xff0c;保障线上系统具备抗压能力 复制代码 如何做全链路压力测试&#xff1a; 全链路压力测试&#xff1a;整体步骤 容量洪峰 -》 容量评估 -》 问题发现 -》 容量规划 全链路压力测试&#xff1a;细化过程 整体目…

YOLOv6-3.0-目标检测论文解读

文章目录摘要算法2.1网络设计2.2Anchor辅助训练2.3自蒸馏实验消融实验结论论文&#xff1a; 《YOLOv6 v3.0: A Full-Scale Reloading 》github&#xff1a; https://github.com/meituan/YOLOv6上版本参考 YOLOv6摘要 YOLOv6 v3.0中YOLOv6-N达到37.5AP&#xff0c;1187FPS&…

linux下安装minio

获取 MinIO 下载 URL:访问&#xff1a;https://docs.min.io/ 一&#xff0c;进入/opt 目录&#xff0c;创建minio文件夹 cd /optmkdir minio二&#xff0c;wget下载安装包 wget https://dl.minio.io/server/minio/release/linux-amd64/minio三&#xff0c;进入minio文件夹创建…

如何使用 API 工具做 Websocket 测试

在 API 测试中&#xff0c;对 Websocket 协议的支持呼声越来越高&#xff0c;今天给大家推荐一款 开源的 API 管理工具——Postcat&#xff0c;以及教教大家&#xff0c;如何利用 API 管理工具做 Websocket 测试。 在线 Demo 链接&#xff1a;Postcat - Open Source API Ecosys…

广域网技术(PAP和CHAP)

第十六章&#xff1a;广域网技术 随着经济全球化与数字化变革加速&#xff0c;企业规模不断扩大&#xff0c;越来越多的分支机构出现在不同的地域。每个分支的网络被认为一个LAN&#xff08;Local Area Network&#xff0c;局域网&#xff09;&#xff0c;总部和各分支机构之间…

音频(九)——I2S 输出正弦波

I2S 输出正弦波 PC 端&#xff1a;先生成一个正弦波数组MCU 端&#xff1a;将正弦波数组使用 I2S 输出AP 端&#xff1a;接受从 MCU I2S 端口出来的正弦波数据并测量 THDN 等数据 PC 端生成正弦波数组 原理 三角函数的公式 yAsinxy AsinxyAsinx A 表示幅值 代码实现 源…

深入浅出C++ ——容器适配器

文章目录一、容器适配器二、deque类简介1. deque的原理2. deque迭代器3. deque的优点和缺陷4. 为什么选择deque作为stack和queue的底层默认容器一、容器适配器 适配器的概念 适配器是STL六大核心组件之一&#xff0c;它是一种设计模式&#xff0c;该种模式是将一个类的接口转换…

国家级高新区企业主要经济指标(2012-2021年)

数据来源&#xff1a;国家统计局 时间跨度&#xff1a;2012-2021 区域范围&#xff1a;全国&#xff08;及各分类统计指标&#xff09; 指标说明&#xff1a;手工提取最新的中国统计年鉴数据中各个excel指标表&#xff0c;形成各个指标文件的多年度数据&#xff0c;便于多年…

SpringBoot整合Spring Security过滤器链加载执行流程源码分析

文章目录1.引言2.Spring Security过滤器链加载1.2.注册名为 springSecurityFilterChain的过滤器2、查看 DelegatingFilterProxy类3.查看 FilterChainProxy类3.1 查看 doFilterInternal方法。3.2 查看 getFilters方法。4 查看 SecurityFilterChain接口5 查看 SpringBootWebSecur…

90%的人都理解错了HTTP中GET与POST的区别

Get和Post是HTTP请求的两种基本方法&#xff0c;要说它们的区别&#xff0c;接触过WEB开发的人都能说出一二。 最直观的区别就是Get把参数包含在URL中&#xff0c;Post通过request body传递参数。 你可能自己写过无数个Get和Post请求&#xff0c;或者已经看过很多权威网站总结…

制造企业为何要上数字化工厂系统?

以目前形势来看&#xff0c;数字化转型是制造企业生存的关键&#xff0c;而数字化工厂管理系统是一个综合性、系统性的工程&#xff0c;波及整个企业及其供应链生态系统。数字化工厂系统所要实现的互联互通系统集成、数据信息融合和产品全生命周期集成&#xff0c;将方方面面的…