基于FPGA通用异步收发器UART设计

摘要

通用异步收发器(UART)是一种能同时支持近距离和远距离传输的异步串行接口,具有传输速率较高、传输距离长、抗干扰性能好、电路结构简单以及节省布线资源等优点。然而,随着社会的发展,信息传输容量越来越大,传统的 UART 成为信息传输中的瓶颈。因此,提升 UART 的传输速率具有重大的意义。FPGA 芯片拥有数量众多的 LE(逻辑单元),再加上数量众多的布线资源,使它具有非常强的灵活性。因此,使用 FPGA 实现的 UART 在传输速率使用灵活性以及性价比方面具有很大的优势。
本文对 UART 芯片采用 FPGA 自顶向下的方法进行设计,所设计的 UART 模块主要包括三大模块,分别是 UART 接收模块,UART 发送模块和 OLED 显示模块。其中, UART 模块按照传统的 UART 协议进行设计,其波特率为9600 baud/s,且波特率可调。另外,为了验证 UART 的正确性,利用串口调试助手,双方之间按照 UART 通信协议进行通信,并利用 OLED 进行发送接收数据及波特率显示。在具体的设计过程中,将结合 FPGA 的最新技术并利用 Quartus II 11.0,Modelsim 等 EDA 软件对各个模块进行综合优化、功能仿真及下载实现。验证结果表明, UART 模块和串口调试助手之间能正常进行通信,OLED 模块可正常显示发送和接收数据以及波特率。

关键词 UART;FPGA;OLED;自顶向下;RS232

第一章 绪 论

1.1 本课题的应用背景及研究的意义

UART(Universal Asynchronous Receiver Transmitter,通用异步收发器)是一种能同时支持近距离和远距离传输的异步串行接口,是计算机中最普遍通用的一部分,被广泛应用于微机和外设的数据交换,例如和鼠标、调制解调器、打印机之间以及微机与微机之间的串行数据传输[1]。因为异步串行通信接口具有传输线少、成本低、 可靠性高、实现简单等优点。因此,在 PC 和外设之间的串行通信中得到了广泛的应用[2-3]。与此同时,异步串行通信接口广泛应用在当今的嵌入式微处理芯片的设计中,另外,UART 总线标准广泛应用在工控领域及家用电器领域。
现场可编程门阵列(Field-Programmable Gate Array,FPGA)诞生于上个世纪 90 年代,经过几十年的飞快发展,显然已成为近几年来电子通信行业的一个热门名词,有取代专用集成电路的趋势[4-6]。一般的 FPGA 芯片是基于 4-LUT 的 SRAM 结 构,带有丰富的 D 触发器和布线资源,除此之外,具有功能丰富、操作灵活的 Quartus II 软件等,这些特点促使了 FPGA 的飞速发展,使其具有先天的灵活性以及高的性能与价格比[6]。FPGA 可广泛应用于协议易于改变的通信领域、集成电路制造及验证领域、仪器领域甚至是家用电器等领域,促进了这些领域的快速发展。
目前市场上国外的中高端 FPGA 芯片,不仅拥有传统 FPGA 芯片的查找表+触发器+布线资源结构,还加入了一定数量的锁相环路(PLL/DLL)、数字信号处理器 (DSP)核、ARM 核等等,甚至还加入了高速串行总线收发器模块,这些额外的模 块为 FPGA 在高性能通信系统中的应用提供了现实的、廉价的解决方案,也为高性能、小体积、低功耗的航空航天设备,个人便携数字多媒体设备提供了可能。
虽然目前市场上主流嵌入式 CPU 片上都包含 1 或 2 个 UART 控制器,但是对于低端嵌入式控制器,尤其是 8 位甚至是 4 位机,鉴于成本的考虑,往往不带有 UART 控制器,而且有时候嵌入式 CPU 本身的 UART 也不够用,而市场上往往又没有这样的 UART 芯片,让 IC 公司定制的话,成本往往很高。
因此,一种比较流行的方法是用硬件描述语言(HDL)对 UART 控制器电路进行建模、编译、综合、前后仿真、布局布线后,最后在 FPGA 芯片上实现。优点有 很多:1) 便于日后对控制器的少许电路进行修改,而不必像定制芯片那样进行很大幅度的包括布局、版图等等的修改;2) 设计过程中的很多关键而复杂繁琐的步骤, 由 EDA 工具(如 Altera 的 Quartus Ⅱ,Xilinx 的 ISE 等等),为设计人员节省很多时间而又提升了设计准确度;3) 相对于定制芯片来说,大幅度节约制造成本。

1.2 本课题研究现状

1.2.1 UART 芯片研究现状

一般情况下,UART 芯片主要集成在主板上,比较常见的 UART 有 National Semiconductor Inc 生产的 INS 8250 系列(8250、16450 等)和 Zilog Inc 生产的 Z80SIO[7]。由于数据在计算机的内部采用的是并行传输方式,因此不能直接将并行数据发送到Modem。在进行数据传输之前必须经过UART的转换才能进行异步传输。 就目前的发展来看,随着集成电路的飞速发展,UART 产品已标准化,并且已经集成到了更大的电路中,但一些寄存器定义、接口等仍与 INS 8250 兼容[7]。
但是,有些速度比较慢的 UART 芯片,它很难实现一些应用所需求的高速的数据传输[8],虽然有些比较先进的 UART 芯片,例如 16550、16750 等,能达到高速通信的要求,但难免会存在一些问题,比如电路比较复杂、引脚较多、和其他器件的接口太复杂、成本比较高等,进而降低了系统的可靠性以及稳定性。随着 FPGA 技 术的发展,设计者常常使用 FPGA 来实现 UART 接口,这样不仅电路简单,而且具有可移植性,能增加系统的稳定性和可靠性。

1.2.2 FPGA 器件研究现状

在 80 年代,Xilinx 公司提出了一种半定制器件,即 FPGA(Field Programmable Gate Array),它以 PAL、GAL、EPLD、CPLD 等可编程通用器件为基础,并经历了一系列的发展,是一种半定制的通用可编程器件[9-12]。它的到来,一方面优化了 ASIC 电路中的不足,另一方面也解决了之前的可编程通用器件的逻辑门数目比较少的问 题[13]。设计者可以根据项目目标需求,通过对 FPGA 器件进行编程设计以及进行相应配置来完成所需实现的逻辑功能。
在很久以前,FPGA 只是用作 ASIC 设计,或者是被认为是 ASIC 设计的验证平台。但是,目前,随着 FPGA 技术的不断发展和创新,越来越多的设计者看到了基于 FPGA 设计的众多优点,因此越来越喜欢使用它来设计产品。基于 FPGA 的可编程设计在通信、航天和医疗电子等领域得到了广泛的应用[14]。随着 FPGA 芯片飞速的发展,它会具有越来越丰富的资源[15-17],可以用它来实现越来越多的电路功能。 与此同时,它又具有其他器件所没有的特点。为此,FPGA 在数字系统设计中的地位越来越重要。使用 FPGA 来实现电路设计,不仅电路会比较简单,所占用的逻辑资源也会减少[18],能满足设计需求。
世界上目前制造 FPGA 芯片并且提供 EDA 软件(综合、仿真、IDE)以及技术性服务的厂商主要有:Altera、Xilinx、Latice、Mentor Graphics、Synopsys 等等,其中以 Altera、Xinlinx 的全系列 FPGA 以及 CPLD 芯片配套的集成开发环境(IDE)以及 Mentor Graphics 的 Modelsim 很受工程师的欢迎。

1.3 本课题主要研究内容

本课题研究的是基于 FPGA 的通用异步收发器设计,主要包含 UART 模块和PC串口调试助手部分。UART 模块分 UART 发送模块和 UART 接收模块。UART 模块选择 Altera 公司的 Cyclone IV EP4CE6E22C8 芯片,并采用 Altera 公司的 Quartus II 11.0 IDE 进行综合设计,采用软件自带仿真工具进行仿真,硬件描述语言采用 Verilog HDL。另外,为了 UART 模块逻辑的正确性,采用PC串口调试助手对其进行设计验证。根据 FPGA 的逻辑功能, UART 模块与串口调试助手之间进行互相发送数据,并在 OLED 屏幕显示收发数据及波特率,从而完成对 UART 的校验。

第二章 基于 FPGA 的 UART 总体设计

2.1 UART 相关知识

2.1.1 异步串行通信基本概念

串行通信的通信方式是将传输的数据按照顺序一位一位地进行传送[8]。它具有传送距离长、可靠性高、需要的数据线少等特点,因此外设和计算机之间的通信广泛用串行通信[8]。串行通信的数据传输方式包括单工方式,半双工方式和全双工方式。
(1) 单工方式 单工方式最大的特点是只允许按一个固定的方向进行数据传送。这种通信方式的前提是已经规定了一端为发送方,另一端为接收方,并且传输方向不可以改变。比如常见的遥控、遥测等采用的单工通信方式。
(2) 半双工方式 这种通信方式下 A 和 B 都具有发送和接收的功能,但是只有一条通信线。因此,在特定的时间只能一方发送,另一方接收。或者一方为接收端, 另一方为发送端。在此种通信方式下不允许双方同时发送或者同时接收。例如日常生活中常用的对讲机。
(3) 全双工方式 全双工通信方式具有 2 条独立的通信线路[19],一条为 txd 用来发送,一条为 rxd 用来接收。因此解决了单工或半双工带来的双方不能同时发送和接收的缺点。但是,为了保证全双工通信,双方的串行接口必须具备一套完全独立 的发送器和接收器。
在串口通信中,异步通信方式是以字符为单位进行传送的,传送的字符之间的间隔是没有规律的,这样可能使接收设备不能正确接收数据,因为每接收完一个字符之后都不能确切的判断下一个将被接收的字符将从何时开始[7]。因此就需要在每个字符的开始和结束处各加一个比特位[20],用来表示一个字符的开始以及结束。这些额外的位叫做起始位和停止位,为了判断传输的正确性,通常会加上一个奇偶校验位。

2.1.2 UART 通信基础

UART 是一种在通信领域、计算机领域、工控领域及家用电器领域中广泛使用的一种接口设备[21]。它的工作方式为:1) 采用全双工通信方式,允许控制器同时进 行数据的发送与接收。其中 TXD 信号线为数据发送信号线,即控制器由此信号线向外发送数据,RXD 信号线为数据接收信号线,即控制器由此信号线从外部接收数据。 2) 采用异步通信方式,即收发器双方没有统一的同步时钟线或在接收器方没有采用时钟提取电路,它的信号同步方式是靠信号帧的首尾定界符,其中电路空闲状态为高电平,当电路状态由高电平转变为低电平且保持一定的时间后,则认定为起始信号,接下来开始传输数据及校验位。而当电路的状态变为高电平且保持一定的时间后,则认定为终止电平,数据传输结束。3) 采用串行通信方式,发送数据之前,控 制器把来自 CPU 的并行数据转换成串行数据,接收数据之后,控制器把串行数据转 换成并行数据[21]。因此,UART 接口具有较高的数据传输速率、传输距离长、抗干 扰性能好、电路结构简单以及节省布线资源等优点。
UART 要想实现全双工异步串行通信[22],3 个主要部分是必不可少的:控制电路部分、发送电路部分和接收电路部分。其中,控制电路部分主要负责产生接收或发送的时钟以及产生一些和 CPU 进行通信的控制信号[23];发送电路部分包括发送缓冲 器和发送移位寄存器;接收电路部分包括接收缓冲器和接收移位寄存器。在实际的工程实现中,发送和接收缓冲器通常有两种实现方法,即:寄存器组法和 FIFO 法。 寄存器组法简单方便,但是其缓存容量有限,因此它会限制 UART 的波特率;FIFO 法有较高的存储深度,可方便实现高波特率的 UART,但是其电路实现较复杂,但可以使用现成的 FIFO IP Core,实际的 UART 芯片,也几乎均使用 FIFO 作为缓冲区。 鉴于本设计的复杂性,本设计在 UART 模块采用 8bit 寄存器组法来实现缓冲区。其内部结构如图 2-1 所示。
在这里插入图片描述

图 2-1 UART 内部结构
通常,在一个通信系统中,一个典型的 UART 的帧格式如图 2-2 所示。
在这里插入图片描述
图 2-2 UART 数据帧
按照 UART 的通信原理,本论文中所设计的 UART 模块数据帧由 11 位数据构成。第 1 位是数据帧的起始位,低电平有效,标志着一帧数据的开始;接下来的第 2 位至第 9 位是数据帧的串行数据部分,共 8 位,低位在前,高位在后;第 10 位和第 11 位 是数据帧的停止位,高电平有效,标志着一帧数据的结束。

2.2 FPGA 芯片结构

一般的 FPGA 芯片内部包括可配置逻辑模块 CLB、输入输出模块 IOB 和内部布线资源三个部分。其中,一个 CLB 一般包括 8 个或 10 个逻辑单元 LE,一个 LE 包 括一个 4 输入查找表和一个 D 触发器;每一个 IOB 一般由一个 IO buffer 和一个 D 触发器构成;布线资源有全局时钟布线资源、长线资源和短线资源[25]。除此之外, 目前的 FPGA 内部一般还包括 RAM、PLL、DSP 核,有的甚至有 ARM 核和高速串行总线收发器等模块。FPGA 的芯片内部资源布局如图 2-3 所示。
在这里插入图片描述
图 2-3 FPGA 的芯片内部资源布局
在本课题的设计中,选择的 FPGA 芯片为 Altera Cyclone IV EP4CE6E22C8 芯片,开发板的型号为 RZ-EasyFPGA A2.1。
(1) Altera Cyclone IV EP4CE6E22C8 芯片 Altera Cyclone IV EP4CE6E22C8 是 Altera 公司针对工业廉价解决方案这种应用场合推出的小规模 FPGA 芯片。该芯片拥有6272 LEs,92 User I/Os,276480 Memory Bits,30 Embedded multiplier 9-bit elements, 2 PLLs,10 Global Clocks。其中内核电压为 1.2V,IO 电压可提供包括 3.3V LVCMOS 和 LVTTL、3.0V LVCMOS 和 LVTTL、default 2.5V、3.0V PCI 和 PCI-X、差分 HSTL 和差分 SSTL 各类电平标准、LVDS、差分 LPECL 等等多种电平标准,为基于混合电平标准的大型电子系统模块之间的互联提供了极大的便利性。本设计综合成的逻辑电路预计使用 150 个 LEs 左右。因此,采用这款芯片是绰绰有余。
(2) FPGA 开发板 由于考虑到整个过程需耗费一定的资金,况且本设计的重点不在于硬件设计,关键在于 UART 代码的编写、编译、综合、时序约束及时序仿真等过程的正确实现。因此,本文作者使用现成的开发板,省去了硬件电路设计的 麻烦,把精力放在了程序设计上。本开发板的型号是 RZ-EasyFPGA A2.1,采用 Altera 公司的小规模、低价位的 FPGA 芯片 Cyclone IV EP4CE6E22C8 为核心,并配以 hynix HY57V641620E 4Banks1Mbits16 的 SDRAM 颗粒以及各种时钟、测温、红外、显示、各种规格的 IO 接口等丰富的外设资源。开发板如图 2-4 所示。

在这里插入图片描述
图 2-4 FPGA 开发板

2.3 总体功能框图及各部分的作用

本设计中采用 FPGA 的自顶向下的方法进行设计[26]。自顶向下(top-down)指的是先将一个大型系统自上而下分解成许多基本的小模块,然后寻求每个小模块的 设计思路,最后将这种思路用某种精确的方式去描述出来。它的实质是逐步分解。自顶向下的设计方法可用于绝大多数设计的建模,设计人员或者开发人员通常将一个大型系统划分为若干层模块,首先对划分出来的每个子模块分别进行描述,最后采用实例化的方法来将每个模块组成一个完整正确的系统。因此,自顶向下的设计方法是一种层次化的设计思想。
对于采用自顶向下的设计方法来说,编写完各个模块之后,在编写顶层模块时,需要把各个子模块例化在顶层模块中。常见的端口映射方法有两种:基于名称的映射方法和基于位置的映射方法。本设计采用基于位置映射的方法。
可见,大型系统分模块化的设计方法将使整个设计结构清晰、层次分明,便于各个设计人员的分工合作、也便于后期的时序约束。在实际工程中,划分模块的原则是:高内聚、低耦合[27]。也就是说,模块之间的接口联络信号越少越好,这样能降低时序分析时接口时序分析的难度。此外,模块的划分也要适度,不能划分的太粗,也不能划分的太细,视情况而定。一般情况下,大型设计划分 4-5 层就足够了。
本论文中设计的 UART 模块主要包括三大模块,分别为 UART 发送模块, UART 接收模块和 OLED 显示模块。设计的整体 UART 框图如图 2-5 所示。

图 2-5 整体 UART 框图

2.4 本章小结

本章主要介绍了 UART 的相关知识,详细介绍了本设计中 UART 数据帧格式。介绍了 UART 的总体功能框图及各部分的作用,以及本设计中所采用的 FPGA 芯片。整体设计对于大型系统的设计来说是至关重要的。它的核心思想是采用自顶向下的设计方法进行多层模块的划分,划分好模块后,单独设计每一个子模块,最后进行封装即可。它的关键要点是如何恰到好处的划分好每一个模块,使每一个模块的之 间的耦合度最低,方便后期的接口设计。因此,好的系统整体设计的基础为系统的设计成功奠定了基础。

第三章 各功能模块设计

3.1 OLED 模块设计

OLED 模块用于显示UART发送和接收的数据,其 IO 管脚如图 3-1 所示。
在这里插入图片描述
图 3-1 OLED 模块的 IO 管脚图
各个 IO 管脚的具体功能如下:
█ clk:全局时钟信号;
█ rst_n:全局异步复位信号,低电平有效;
█ key_123:按键调试信号;
█ rx_data[7…0]:接收数据寄存器,保存直至下一个数据来到 ;
█ rx_int:接收数据中断信号,接收到数据期间始终为高电平;

3.2 波特率选择 模块设计

波特率产生模块负责生成发送模块和接收模块的波特率时钟信号,然后利用这 个信号对发送模块发送数据和接收模块接收数据进行控制。它生成的波特率时钟信 号周期为外部时钟的 16 倍。波特率选择 模块的 IO 管脚如图 3-2 所示。
在这里插入图片描述
图 3-2 波特率选择模块的 IO 管脚图
各个 IO 管脚的具体功能如下:
█ clk:全局时钟信号;
█ rst_n:全局异步复位信号,低电平有效;
█ key_123:按键调试信号;
█ bps_start:波特率起始信号 ;

3.3 串口接收 模块设计

接收模块是 UART 电路的重要组成部分。它负责利用接收波特率时钟信号, 来控制接收电路接收串行输入总线上的一帧数据,然后将其转换为 8 位并行数据并 在恰当时刻将其送入接收缓冲区中。由于大量使用数据选择器链,造成组合逻辑延时很长,因此它也是 UART 电路的关键路径。串口接收 模块的 IO 管脚如图 3-3 所示。
在这里插入图片描述
图 3-3 串口接收 模块的 IO 管脚图
各个 IO 管脚的具体功能如下:
█ clk:全局时钟信号;
█ rst_n:全局异步复位信号,低电平有效;
█ rx_data[7…0]:接收数据寄存器,保存直至下一个数据来到;
█ clk_bps:波特率时钟信号;
█ rx_int:接收数据中断信号,接收到数据期间始终为高电平;
当接收波特率时钟信号开始工作且接收移位寄存器为空时,接收数据帧计数器 开始工作。此时接收的数据并不包括起始位,对于异步通信方式来说,起始位只起 到数据帧检测标志信号的作用。

3.4 串口发送 模块设计

发送模块是 UART 电路的重要组成部分。它负责将发送移位寄存器中的 8 位并行数据按照 UART 数据帧的帧格式转换成串行发送数据,然后利用发送波特 率时钟信号将其送上串行发送总线上。 当发送波特率时钟开始工作时,发送数据帧计数器也同时工作。如果发送移位寄存器中的数据是有效的,那么接下来将进行数据的移位发送。 当数据发送完毕时,接下来发送奇偶校验位和停止位;待停止位发送完毕后, 电路又回到空闲状态,等待下一帧数据的发送。发送 模块的 IO 管脚如图 3-4 所示。
在这里插入图片描述
图 3-4串口发送 模块的 IO 管脚图
各个 IO 管脚的具体功能如下:
█ clk:全局时钟信号;
█ rst_n:全局异步复位信号,低电平有效;
█ rx_data[7…0]:接收数据寄存器,保存直至下一个数据来到;
█ clk_bps:波特率时钟信号;
█ rx_int:接收数据中断信号,接收到数据期间始终为高电平;

顶层模块设计

UART 模块一共包括六个子模块,分别为发送模块,接收模块,时钟分频模块,波特率产生模块,起始位检测模块,和液晶显示模块。顶层模块的 IO 管脚如图 3-5 所示。
在这里插入图片描述

第四章 总体仿真及调试

引脚分配

在这里插入图片描述

仿真时序图

OLED模块时序图:在这里插入图片描述在这里插入图片描述
UART发送、接收仿真图:在这里插入图片描述

串口助手调试

在这里插入图片描述

总体调试图

在这里插入图片描述

总电路图

在这里插入图片描述

第五章 Verilog代码部分

module my_uart_top(			
clk,rst_n,				
rs232_rx,rs232_tx,				
key_1,key_2,key_3,			
oled_rst_n_out,oled_cs_n_out,			  
oled_dc_out,oled_clk_out,				
oled_data_out 				
);
input clk;			// 50MHz主时钟
input rst_n;		//低电平复位信号
input key_1,key_2,key_3;
input rs232_rx;		// RS232接收数据信号
output rs232_tx;	//	RS232发送数据信号
output wire oled_rst_n_out;  //nokia5110 reset, active low
output wire oled_cs_n_out;  //nokia5110 chip select, active low
output wire oled_dc_out;  //nokia5110 data or command control
output wire oled_clk_out;  //nokia5110 clock
output wire oled_data_out;  //nokia5110 data 
wire key1,key2; 
wire bps_start1,bps_start2;	//接收到数据后,波特率时钟启动信号置位
wire clk_bps1,clk_bps2;		// clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据的数据改变点
wire[7:0] rx_data;	//接收数据寄存器,保存直至下一个数据来到
wire rx_int;		//接收数据中断信号,接收到数据期间始终为高电平
speed_select		speed_rx(								
.clk(clk),							
.rst_n(rst_n),							
.key_1(key_1),					     
.key_2(key_2),							
.key_3(key_3),							
.bps_start(bps_start1),							
.clk_bps(clk_bps1)						
);
my_uart_rx			my_uart_rx(
.clk(clk),	//接收数据模块
.rst_n(rst_n),
.rs232_rx(rs232_rx),
.rx_data(rx_data),
.rx_int(rx_int),
.clk_bps(clk_bps1),
.bps_start(bps_start1)						
);
speed_select		speed_tx(
.clk(clk),	//波特率选择模块
.rst_n(rst_n),
.key_1(key_1),
.key_2(key_2),
.key_3(key_3),
.bps_start(bps_start2),
.clk_bps(clk_bps2)
);
my_uart_tx			my_uart_tx(
.clk(clk),	//发送数据模块							
.rst_n(rst_n),							
.rx_data(rx_data),							
.rx_int(rx_int),							
.rs232_tx(rs232_tx),							
.clk_bps(clk_bps2),							
.bps_start(bps_start2)						
);
OLED				OLED(                  .clk(clk),//OLED显示						
.rst_n(rst_n), 						
.rx_data(rx_data),						
.rx_int(rx_int),						
.oled_rst_n_out(oled_rst_n_out),						
.oled_cs_n_out(oled_cs_n_out),						
.oled_dc_out(oled_dc_out),						
.oled_clk_out(oled_clk_out),						
.oled_data_out(oled_data_out)                 );	

代码不全,完整代码整理好将上传此博客,供大家学习。

分享决定高度,学习拉开差距

作为学习者给大家分享自己完成的此作品,希望对大家有帮助,当然上文若有不妥之处,欢迎指正。

欢迎大家留言,批评指正!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章