FPGA-UART串口通信
目录
前言
1、UART串口的介绍
2、实验开始前一些参数的计算
3、UART通信的时序
4、代码部分
1、接收部分代码
2、发送部分的代码
前言
本篇文章是为了记录自己FPGA的学习过程,不完全正确,仅供参考!!!
1、UART串口的介绍
uart串口是我们常用的一种通讯协议,它的中文名称是通用异步收发传输器,像我们常见的RS232、RS485都是uart串口的一种,只不过是电平不同,通讯时序上都是一样的,像是RS232,只需要用MAX3232芯片进行电平转换就可以,那么uart串口既然是串行的通行协议,我们在使用的时候一般需要将并行数据转换成串行数据,这点需要注意,uart一般有四条线,VCC、GND、RX、TX,在使用的时候通讯双方一定要共地,因为其有tx和rx两根线,所以uart是全双工的通讯,但是uart是通讯速率比较慢的一种。
2、实验开始前一些参数的计算
首先我们需要知道波特率是啥,波特率就是表示uart串口传输速度的一个表示方式,常见的有4800、9600、115200,其实波特率就是uart串口传输一个bit数据所需要的时间,也是uart窗口工作时做基本的时间单位,时间=1/bound,我们在使用uart之前,需要约定好bound和奇偶效验位,本次实验以9600的波特率和无奇偶效验位来做,那么我需要知道约定好波特率之后,我们一个bit的数据需要保持相应的时间啊,那我们来计算下(1/9600)x10*9约等于10416ns,我们系统的时间周期为20ns,那么我们需要进行计数的值为5207(从0开始)
3、UART通信的时序
程序就是按照这个图中的时序写的,其中需要注意的是uart串口的空闲状态是高电平,起始位是一个bit的低电平(实际操作是我们可以去捕获下降沿),然后传输8位数据,先传输的是低位数据 ,然后是高位数据,在八位数据结束后,可以约定奇偶效验位,然后就是停止位和空闲状态,实际上直接拉高电平,就结束传送了,本实验室将接收的数据发送出去。
4、代码部分
1、接收部分代码
module uart_rx
(input wire sys_clk,input wire sys_rst,input wire rx_data,output reg [7:0] out_data,//串转并并输出output reg out_reg//接收完成的标志
);parameter [12:0] UART_MAX = 13'd5207,[3:0] BIT_MAX = 4'd9;reg [12:0] uart_cnt;//利用该计数器来计算不同波特率下传送一bit数据的时间
reg uart_data1; //打三拍的中间变量
reg uart_data2; //打三拍的中间变量
reg uart_data3; //打三拍的中间变量
reg begin_flag;//传输开始标志
reg data_en;//数据有效信号
reg [3:0] bit_cnt;//位数计数
wire data_flag;//该标记主要用于取中中间部分的数据,主要是中间数据较为稳定
reg [7:0] tx_data;
reg rx_end_flag;/*波特率为9600时,当系统时钟为50MHZ的时候,这时每传输一个bit的数据,每个传输周期相当于5208个周期
所以这边需要一个计数器来计算出一个传输的周期(具体计数值为((1/bound)*10*9)/系统周期)这边的单位是ns*/always@(posedge sys_clk)
beginif(sys_rst == 1'b0)uart_cnt <= 13'd0;else if((uart_cnt == UART_MAX)||(data_en == 1'd0))uart_cnt <= 13'd0;else uart_cnt <= uart_cnt +13'd1;
endalways@(posedge sys_clk)
beginif(sys_rst == 1'b0)bit_cnt <= 4'd0;else if((bit_cnt == BIT_MAX)&&(uart_cnt == UART_MAX))bit_cnt <= 4'd0;else if(uart_cnt == UART_MAX)bit_cnt <= bit_cnt + 4'd1;elsebit_cnt <= bit_cnt;
end//对输入的数据打三拍这边一定要注意,uart串口空闲状态为高电平,开始标志为高电平到下降沿的一个下降沿,所以在给初值的时候,需要赋值为高电平
always@(posedge sys_clk)
beginif(sys_rst == 1'b0){uart_data3,uart_data2,uart_data1} <= 3'b111;else{uart_data3,uart_data2,uart_data1} <= {uart_data2,uart_data1,uart_data};
end //因为空闲状态到开始的状态是一个下降沿,这边判断是下降沿就把开始标志置一
always@(posedge sys_clk)
beginif(sys_rst == 1'b0)begin_flag <= 1'b0;else if((uart_data2 == 1'b0)&&(uart_data3 == 1'b1)&&(data_en == 1'b0))begin_flag <= 1'b1;else begin_flag <= 1'b0;
end/*数据使能信号,因为我们判断开始信号是用下降沿来判断的,但是这可能产生一个误判,
因为串行数据传输的时候,也会产生下降沿,所以这里我们用data_en变量来辅助判断*/
always@(posedge sys_clk)
beginif(sys_rst == 1'b0)data_en <= 1'b0;else if(begin_flag == 1'b1)data_en <= 1'b1;else if((bit_cnt == 4'd9)&&(data_flag == 1'b1))data_en <= 1'b0;else data_en <= data_en;
endassign data_flag = ((bit_cnt >= 4'd1)&&(bit_cnt < 4'd9)&&(uart_cnt == 13'd2603))? 1'b1 : 1'b0; always@(posedge sys_clk)
begin if(sys_rst == 1'b0)tx_data <= 8'b0;else if((data_flag == 1'b1))tx_data <= {uart_data3,tx_data[7:1]};elsetx_data <= tx_data;
endalways@(posedge sys_clk)
beginif(sys_rst == 1'b0)rx_end_flag <= 1'b0;else if((bit_cnt == 4'd8)&&(data_flag == 1'b1))rx_end_flag <= 1'b1;elserx_end_flag <= 1'b0;
end/*开始我以为代码写到这里就结束了,但其实我还是太年轻了,为了使我们的输出的数据和输出的接收完成的标志信号同步(这样在标志有效的时候,读的数据才对)
其实上面的数据也是对齐的,但是为了养成一个良好的习惯,下面还是在同一条件下对数据和标志信号进行输出*/always@(posedge sys_clk)
beginif(sys_rst == 1'b0)out_data <= 8'b0;else if(rx_end_flag == 1)out_data <= tx_data;else out_data <= out_data;
endalways@(posedge sys_clk)
beginif(sys_rst == 1'b0)out_reg <= 1'b0;else if(rx_end_flag == 1)out_reg <= rx_end_flag;else out_reg <= 1'b0;
endendmodule
2、发送部分的代码
module uart_tx
(input wire sys_clk,input wire sys_rst,input wire [7:0] in_data,input wire in_flag,//这个是rx模块输出的标志信号output reg [7:0] tx_data
);parameter [12:0] UART_MAX = 13'd5207,[3:0] BIT_MAX = 4'd9;reg [12:0] uart_cnt;//利用该计数器来计算不同波特率下传送一bit数据的时间
reg data_en;//数据有效信号
reg [3:0] bit_cnt;//位数计数
wire data_flag;//always@(posedge sys_clk)
beginif(sys_rst == 1'b0)uart_cnt <= 13'd0;else if((uart_cnt <= UART_MAX)||(data_en == 1'b0))uart_cnt <= 13'd0;else uart_cnt <= uart_cnt + 13'd1;
endalways@(posedge sys_clk)
beginif(sys_rst == 1'b0)bit_cnt <= 4'd0;else if((uart_cnt == UART_MAX)&&(bit_cnt == BIT_MAX))bit_cnt <= 4'd0;else bit_cnt <= bit_cnt +4'd1;
endalways@(posedge sys_clk)
beginif(sys_rst == 1'b0)data_en <= 1'b0;else if(in_flag == 1'b1)data_en <= 1'b1;else if((bit_cnt == 4'd9) && (data_flag == 1'b1))data_en <= 1'b0; else data_en <= data_en;
endalways@(posedge sys_clk)
beginif(sys_rst == 1'b0)data_flag <= 1'b0;else if(uart_cnt == 13'd2605)data_flag <= 1'b1;else data_flag <= 1'b0;
endalways@(posedge sys_clk)
beginif(sys_rst == 1'b0)data_flag <= 1'b0;else if(data_flag == 1'b1)case(bit_cnt)4'd0 : tx_data <= 1'b0;4'd1 : tx_data <= in_data[0];4'd2 : tx_data <= in_data[1];4'd3 : tx_data <= in_data[2];4'd4 : tx_data <= in_data[3];4'd5 : tx_data <= in_data[4];4'd6 : tx_data <= in_data[5];4'd7 : tx_data <= in_data[6];4'd8 : tx_data <= in_data[7];4'd9 : tx_data <= 1'b1;default: tx_data <= 1'b1;endcase
endendmodule
FPGA-UART串口通信相关推荐
- 基于FPGA Uart串口通信实验
基于FPGA Uart串口通信实验 首先需要了解uart串口通信协议,根据个人专业需求不同,了解的层面可以不同. UART简介 通用异步收发传输器(Universal Asynchronous Rec ...
- 基于FPGA的UART串口通信实验(VHDL语言实现)
一.前言: 最近在做UART串口通信的相关实验时,在网上查了很多资料,发现网上的大部分文章只注重理论,不注重代码,很多代码有错误不说,而且难以理解.故在完成此实验后,起了写一篇博客的心思,以供有想做相 ...
- 【FPGA】八、UART串口通信
文章目录 前言 一.UART简介 1.基本概念 2.UART协议 3.波特率简介 二.UART串口回环实验 1.设计思路 2.程序代码 ① 串口接收模块 ② 串口发送模块 ③ 串口顶层模块 ④ 串口仿 ...
- 【FPGA练习】(一): UART串口通信实验
由于之前学习FPGA的过程中,没有做一个良好的记录,以及已学知识的扩展,所以从今天开始每一个实验例程和扩展应用,都要做文档记录.本实验,是基于正点原子达芬奇xc7a35tfgg484-2开发板.开发板 ...
- (一)FPGA之串口通信(UART)
(一)FPGA之串口通信(UART) 回到梦开始的地方,如今回过头来看串口协议,确实清晰了很多,但是奈何好记性不如烂笔头,我还是要重新记录一下学习的知识点,方便查找和学习. 波特率(Band Rate ...
- 【FPGA】UART串口通信
目录 前言 一丶通信方式 1.串行通信 2.并行通信 二丶UART 串口通信 三丶模块设计 四丶发送模块 1.代码 2.仿真 五丶接收模块 1.代码 2.仿真 六丶顶层模块 1.代码 2.模块原理图 ...
- 【正点原子MP157连载】 第十六章 UART串口通信实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...
- [FPGA] UART串口回环
文章目录 前言 一.UART是什么? 二.UART协议 1.内容 2.系统模块划分 2.1.接收模块 2.2.发送模块 2.3.控制模块 2.4.顶层模块 3.仿真 前言 上期介绍了串行通信的基本概念 ...
- UART串口通信(回环测试)
一 UART串口通信简介 UART(Universal Asynchronous Receiver-Transmitter)是采用异步串行通信方式的通用异步收发传输器,在发送数据时将并行数据转换为串行 ...
- UART 串口通信实验
串口是"串行接口"的简称,即采用串行通信方式的接口.串行通信将数据字节分成一位一位的形式在一条数据线上逐个传送,其特点是通信线路简单,但传输速度较慢.因此串口广泛应 ...
最新文章
- linux shell 得到当前时间
- 关于HTML加密混淆、源码保护、代码安全,防止解压直接看源码
- python开发框架 代码生成_500 行 Python 代码构建一个轻量级爬虫框架
- linux-压缩和解压类
- 深度学习基础(三)loss函数
- 使用git时报错出现vim.exe.stackdump
- sql:MySQL 6.7 表,视图,存储过程结构查询
- parzen窗估计如何进行结果分析_Parzen窗方法的分析和研究
- MEF体验使用接口导出的优越性
- What is “Deploy applications configured in Tomcat instance” in IntelliJidea
- 管理感悟:学会推论及验证
- 为什么苏联打下了如此强的数学基础,俄罗斯却至今无法成为AI强国?
- threejs学习笔记:贴图实现木地板效果
- 网络操作系统 Linux配置与管理,网络操作系统—Linux配置与管理
- Python 中 ‘unicodeescape’ codec can’t decode bytes in position XXX: trun错误原因分析及解决方案
- SCRM升级--企业微信数字营销解决方案
- 什么是CVE?常见漏洞和暴露列表概述
- 自媒体:我为什么要写一篇关于睡眠的文章?
- 动态规划DP模板题汇总
- matlab csp详解,内容安全策略(CSP)详解