UART 串口收发模块设计及Verilog实现

您所在的位置:网站首页 verilog实现fibonacci UART 串口收发模块设计及Verilog实现

UART 串口收发模块设计及Verilog实现

2024-01-25 15:18| 来源: 网络整理| 查看: 265

文章目录 一、UART协议介绍1.1 UART协议层1.2.1 UART的帧格式1.2.2 UART的波特率 1.2 UART物理层1.3.1 物理连接1.3.2 接口标准1.3.3 硬件设计1. USB转串口电路2. RS232转串口电路 二、UART设计及Verilog实现2.1 UART设计概述2.2 UART详细设计2.2.1 UART发送模块设计1. 波特率时钟分频模块2. 发送模块3. testbench4. 结果 2.2.2 UART接收模块设计1. 波特率时钟分频模块2. 接收模块3. testbench4. 结果

一、UART协议介绍

UART的全称是通用异步收发器(Universal Asynchronous Receiver/Transmitter)。

Universal 通用性: 体现在UART使用范围广上,作为一个通用的接口协议,UART广泛的应用在各类MCU和SOC产品上。 Asynchronous 异步性: 体现在”不需要额外的时钟线进行数据的同步传输”即只要信号拉低,即可开始传送数据,而另一些通讯协议,需要引入时钟信号来进行操作,如AMBA,需要在时钟的上升沿发送数据。 Receiver/Transmitter收发器:则更好理解,即一个数据的发送方和一个数据的接收方,也意味着在数字IC设计中需要分别设计Receiver和Transmitter。

发送端的UART将来自控制设备(如CPU)的并行数据转换为串行数据,以串行方式将其发送到接收端的UART,然后由接收端的UART将串行数据转换为并行数据以用于接收设备的正常处理。

这里只需要两条线RX/TX即可在两个UART之间传输数据。具体如下图所示;

1.1 UART协议层 1.2.1 UART的帧格式

UART的一帧由1位起始位 、5~9个​ 数据位 、一个可选的奇偶校验位 和 ​停止位 组成。数据逐位传输,如下图所示。 在这里插入图片描述

为什么UART的传输需要起始位?

因为UART没有控制线,要让接收方知道什么时候开始接收数据,需要一些手段。

在发送数据之前,先发一位逻辑“0”作为数据发送的起始标志,接收方在空闲时,当检测到有一个低电平,则开始以波特率的频率接逐位接收数据。

在具体设计UART的过程中,如何检测低电平,使用到了电平检测电路。很显然这里使用的是下降沿检测电路。

UART基本的数据形式

默认无传输数据时,为高电平。

当信号拉低,传输线上的电平拉低,意味着开始进行数据传输

紧接着起始位的是数据位,它可以是5、6、7或8位。

UART的“校验位”紧挨着“数据位”,采用奇偶校验​ 方式,根据设置,校验位可以存在也可以不存在。

UART将停止位作为停止标志,是在数据位(没有校验位)和校验位(有校验位)之后发送1~2位的逻辑“1”高电平。当发送完停止位之后,UART总线进入空闲。

为什么UART的数据位可变?

数据位包含正在传输的实际数据。如果使用奇偶校验位,则可以是5位,最多8位。如果不使用奇偶校验位,则数据帧的长度可以为9位。

因为UART是一种低速总线,每多发一位都占用不少的时间(由传输波特率决定),所以可以根据传输数据的特点,采用不同位宽以节约数据传输的时间。

1.2.2 UART的波特率

如果从更高的level审视UART传输协议,如嵌入式开发者的角度,我们会发现,在使用具体的UART协议前,我们需要对发送端和接收端进行波特率的同步,以此来确保发射端的数据可以在接收端得到正确的采集。常用的波特率可以是300,1200,2400,9600,19200,38400,115200,这些数意味着什么呢?别着急,我们接下来要讨论这个内容。

什么是波特率

波特率等于每秒钟传输的数据位数,即Bit/s。 假如波特率设置为9600,那么意味着每秒该UART传输协议可以传输9600bits的数据,换句话说传输1比特需时间约为:10^9(ns)/9600=104166(ns)。

下表是各个波特率下数据位时间宽度。 在这里插入图片描述

如何换算波特率

时钟频率假如为100MHz,这意味着我们的时钟周期为10ns,因此10416个时钟周期我们就可以传输1bit数据,换言之我们需要一个大小为10416的分频电路来对100MHz时钟进行处理,因此在设计UART的过程中,我们需要使用分频电路依据波特率处理全局时钟,依据分频后的时钟节奏来发送数据和接收数据。

同样的,参考作者之前的文章,我们可以获知分频电路的设计方法

波特率和采样频率是一样的吗?

按照前文所说,好像波特率和采样频率是一个意思,即9600波特率对应接收端1s进行9600次采样,也对应发射端1s进行9600bit的发射,那么请读者思考,真的是这样吗? 答案其实是否定的 这是因为:在数据的传输中,信号可能受到一些干扰而产生一些抖动(比如说电磁兼容性设计中的近端串扰),如果接收端只对这些信号进行一次采样,那么它有可能采样到的是不准确的数据,所以接收端在采样时,通常都要采样多次,然后通过处理获得准确的数据,比如说,我们可以用多数表决的方法来在接收端进行多次采样,得到准确值。

1.2 UART物理层 1.3.1 物理连接

在这里插入图片描述

1.3.2 接口标准

UART、RS232、RS485在串口通信中,主要区别是电平的不同,其中UART通常使用TTL电平,下面介绍这几个存在的差异;

TTL

TTL全名是晶体管-晶体管逻辑集成电路(Transistor-Transistor Logic)

输入高电平最小2V,输出高电平最小2.4V,典型值3.4V;

输入低电平最大0.8V,输出低电平最大0.4V,典型值0.2V。

RS232

RS232 逻辑1电平(MARK)=-3V~-15V,逻辑0电平(SPACE)=+3~+15V;

同样的,对于传输数据0x55,即二进制的01010101,RS232和TTL的区别如下;(LSB:最低位,MSB:最高位) [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WP8Evw5R-1682070990015)(assets/image-20230417144644-ke2ksdg.png)]

RS485

RS485是差分信号进行串行传输;

逻辑1以两线间的电压差为+(2 ~ 6)V表示 ; ​逻辑 "0"以两线间的电压差为-(2 ~ 6)V表示 ; 在工业通信中,使用RS485比较多,因为RS485是差分信号,可以抑制共模干扰,因此在恶劣的环境中拥有很好的抗干扰性,比较稳定;

1.3.3 硬件设计

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NvE0gMS7-1682070990015)(assets/image-20230417163754-syblf26.png)]

FPGA采用TTL电平:3.3V(1)、0V(0)。而PC采用的是负逻辑电平:-15~-5为逻辑1,+5 ~ +15为逻辑0。

因此,PC与FPGA之间通信时,需要进行电平转换。

老早以前的台式机和笔记本可都是有串口的,虽然现在很多台式机串口没有了,笔记本也没有串口了,但是串口从来没有被丢弃,只是以另外一种形式存在,这就是 USB 转串口芯片。串口只需要 2 根线就可以实现一

收一发,使用简单,可靠方便,在低速场合大量使用。

1. USB转串口电路 CH340G

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fSm2Oh1A-1682070990016)(assets/image-20230417171151-b44eajn.png)]

CP2104

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ly88fsAo-1682070990017)(assets/cp2104-20230417171240-6htj5gk.png)]

2. RS232转串口电路

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8qYaRhaf-1682070990017)(assets/image-20230417171130-yq2a170.png)]

二、UART设计及Verilog实现 2.1 UART设计概述

本实例设计的UART特性:

并没有支持奇偶检验,故没有奇偶校验位。并不支持数据位宽可配,数据位位宽固定为8bit。支持输入时钟与波特率可配。

原理图如下,分两个大模块,一个==数据接收控制模块(Receive_Control)==,一个数据发送控制模块(Send_Control)。

模块启动后,

接收模块一直在接收数据uart_rx。每当有新数据发送过来时,将新的8位数据放置于rx_data中,接收完成信号rx_data会置高。发送模块发送数据需要发送使能tx_en有效后,才能将要发送的数据tx_data发送到uart_tx端口,发送完成后tx_finish会置高,之后可以使能tx_en发送新的数据。

图片

各模块详细设计图示 在这里插入图片描述

端口说明:

图片

接收控制模块与发送控制模块内部都有一个波特率时钟产生模块(BuadRate_set),用于将电路输入时钟(clk)进行分频产生波特率时钟,用于接收和发送数据控制。

图片

可以看到,BuadRate_set模块有一个enable控制信号,只有当enable信号为高时,BuadRate_set模块才工作。 在发送控制模块里面,只有发送数据的时候才拉高其相应的enable;在接收控制模块里面,只有检测到有数据发送进来的时候才拉高其相应的enable。这是为了降低功耗。

2.2 UART详细设计 2.2.1 UART发送模块设计

数据发送模块的时序如下所示。 在这里插入图片描述

当发送使能tx_en有效时,启动波特率时钟分频模块开始计数。状态由IDLE转为EN_TX。波特率时钟分频模块用于生成发送数据的时钟,并控制数据移位。当波特率时钟到来时将此刻要发送的数据送出。 1. 波特率时钟分频模块 `timescale 1ns / 1ps module BuadRate_set #( parameter CLK_Period=50000000,//the unit is Hz parameter Buad_Rate=9600 //the unit is bits/s )( input clk, //原始系统时钟 input rst_n, //复位 input enable, //模块使能信号 output Buad_clk //输出的分频 ); localparam DIV_PEREM=CLK_Period/Buad_Rate/2; //计数器最大值 reg[15:0] cnt; always @( posedge clk ) if( !rst_n ) cnt 1'b1,data_to_send[8:1]}; assign uart_tx = (Buad_en)?data_to_send[0]:1'b1; assign tx_finish = (state == END_BIT)? 1'b1:1'b0; endmodule 3. testbench `timescale 1ns / 1ps module tb_send(); reg clk; reg rst_n; reg tx_en; reg [7:0] tx_data; wire tx_finish; wire uart_tx; // 50MHz,9600bps Send_Control my_Send_Control(clk, rst_n, tx_en, tx_data, tx_finish, uart_tx); initial begin clk=0;rst_n=0; tx_en=0; //复位信号不能太短。 #100 rst_n=1; tx_en=1; tx_data=8'b11001100; # 100000000 $stop; end //50Mhz的时钟 always #10 clk=~clk; endmodule 4. 结果

在这里插入图片描述

2.2.2 UART接收模块设计

数据接收模块的时序如下所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZLx4c0r-1682071409104)(assets/image-20230421174441-y6ba21m.png)]

当检测到输入数据从高位跳转到低位时,启动波特率时钟分频模块开始计数。状态由IDLE转为GET_DATA。波特率时钟分频模块用于生成接收数据的使能信号,并控制数据移位。当波特率时钟到来时将此刻接口上的数据保存到接收数据数组rx_data_tmp中。该设计中每bit的数据都会检测8次。取平均值作为最终的检测结果。 1. 波特率时钟分频模块 // 公众号: 小鱼FPGA // Engineer: littlefish module BuadRate_set_multi #( parameter CLK_Period=50000000,//the unit is Hz parameter Buad_Rate=9600 //the unit is bits/s )( input clk, //原始系统时钟 input rst_n, //复位 input enable, //模块使能信号 output reg Buad_en, //输出的分频 output reg Cap_en ); localparam DIV_PEREM=CLK_Period/Buad_Rate; //计数器最大值 localparam Cap_DIV_PEREM=DIV_PEREM/8; //计数器最大值 reg[15:0] cnt; //波特率分频 always @( posedge clk ) if( !rst_n ) cnt 'b1,rx_data_tmp[8:1]}; else rx_data_tmp


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3