FPGA课程设计方案FPGA器件设计方案与实现UART.docx
《FPGA课程设计方案FPGA器件设计方案与实现UART.docx》由会员分享,可在线阅读,更多相关《FPGA课程设计方案FPGA器件设计方案与实现UART.docx(18页珍藏版)》请在冰点文库上搜索。
![FPGA课程设计方案FPGA器件设计方案与实现UART.docx](https://file1.bingdoc.com/fileroot1/2023-5/5/9f16c8bd-418e-4fef-9b5d-3e4b92976fb7/9f16c8bd-418e-4fef-9b5d-3e4b92976fb71.gif)
FPGA课程设计方案FPGA器件设计方案与实现UART
封面
作者:
PanHongliang
仅供个人学习
目录
摘要II
AbstractIII
引言1
1工程构成的基本原理2
1.1、UART简介2
1.2、UART的基本特点2
2工程实现的基本原则4
2.1、FPGAUART系统组成如图2所示:
4
2.2、波特率发生器4
2.3、UART接收器4
2.4、UART发送器6
2.5芯片的选择7
3程序设计8
3.1顶层程序8
3.2UART发送器程序10
3.3UART接收器程序12
3.4整体电路图14
4仿真15
4.1顶层仿真15
4.2波特率发生器仿真15
4.3UART发送器仿真16
4.4UART接收器仿真16
5总结17
6参考文献18
摘要
基于FPGA设计和实现UART,可以用片上很少的逻辑单元实现UART的基本功能。
与传统设计相比,能有效减少系统的PCB面积,降低系统的功耗,提高设计的稳定性和可靠性,并可方便地进行系统升级和移植。
采用有限状态机模型形式化描述了UART的功能,在此基础上用硬件描述语言VHDL编程实现了UART,并使用QuartusⅡ软件中的嵌入式逻辑分析仪SignalTap对数据传输进行了检测,验证了设计的正确性。
本设计具有较大的灵活性,通过调整波特率发生器的分频参数,就可以使其工作在不同的频率。
采用16倍波特率的采样时钟,可以实时有效探测数据的起始位,并可对数据位进行“对准”中央采样,保证了所采样数据的正确性。
该模块可以作为一个完整的IP核移植进各种FPGA中,在实际应用时可嵌入到其他系统中,很容易实现和远端上位机的异步通信。
关键字:
FPGA;UART;有限状态机;SignalTap
Abstract
DesignandimplementationbasedonFPGAUART,canbeusedonafewlogicalunitrealizesthebasicfunctionofUART.Comparedwiththetraditionaldesign,caneffectivelyreducethePCBareasystem,reducethepowerconsumptionofthesystem,andimprovethedesignofthestabilityandreliability,andeasysystemupgradesandmigration.
ThefunctionsofUARTaredescribedformallybyusingthefinitestatemachinemodel,bytheway,UARTisrealizedonthebasisofVHDL.Moreover,thedatatransmissionisdetectedwithSignalTapwhichisanembeddedlogicanalyzerinQuartusⅡ.Theresultprovesthevalidityofthedesign.
Thisdesignhasgreatflexibility,byadjustingthefrequencydivisionbaudrategeneratorparameters,youcanmakeitworkonadifferentfrequency.Using16timesthebaudrateofthesamplingclock,caneffectivelydetectreal-timedataofthestartbit,andto"on"thecentralsamplingofdatabits,ensuresthecorrectnessofthesampleddata.ThemodulecanbeusedasacompleteIPnucleartransplantationintovariouskindsofFPGA,intheactualapplicationcanbeembeddedintoothersystems,iseasytoimplementandtheremotePCasynchronouscommunication.
Keyword:
FPGA;UART;finitestatemachine;SignalTap
引言
随着电子设备功能的不断增强,复杂度也在不断提高,对这些系统的测试要求也越来越高,因而促进了自动测试系统的发展。
而数字I/O模块作为自动测试系统重要的测试模块,它既可以作为信号源激励被测系统,也可以检测被测系统的输出,在很多领域得到了非常广泛的应用。
当今社会是数字化的社会,是数字集成电路广泛应用的社会。
数字集成电路本身在不断地进行更新换代。
它由早期的电子管、晶体管、小中规模集成电路、发展到超大规模集成电路(VLSIC几万门以上)以及许多具有特定功能的专用集成电路。
但是,随着微电子技术的发展,设计与制造集成电路的任务已不完全由半导体厂商来独立承担。
系统设计师们更愿意自己设计专用集成电路(ASIC)芯片,而且希望ASIC的设计周期尽可能短,最好是在实验室里就能设计出合适的ASIC芯片,并且立即投入实际应用之中,因而出现了现场可编程逻辑器件(FPLD),其中应用最广泛的当属现场可编程门阵列(FPGA)和复杂可编程逻辑器件(CPLD)。
1工程构成的基本原理
1.1、UART简介
UART(UniversalAsynchronousReceiverTransmitter通用异步收发器)是一种应用广泛的短距离串行传输接口。
常常用于短距离、低速、低成本的通讯中。
8250、8251、NS16450等芯片都是常见的UART器件。
基本的UART通信只需要两条信号线(RXD、TXD)就可以完成数据的相互通信,接收与发送是全双工形式。
TXD是UART发送端,为输出;RXD是UART接收端,为输入。
1.2、UART的基本特点
(1)在信号线上共有两种状态,可分别用逻辑1(高电平)和逻辑0(低电平)来区分。
在发送器空闲时,数据线应该保持在逻辑高电平状态。
(2)起始位(StartBit):
发送器是通过发送起始位而开始一个字符传送,起始位使数据线处于逻辑0状态,提示接受器数据传输即将开始。
(3)数据位(DataBits):
起始位之后就是传送数据位。
数据位一般为8位一个字节的数据(也有6位、7位的情况),低位(LSB)在前,高位(MSB)在后。
(4)校验位(parityBit):
可以认为是一个特殊的数据位。
校验位一般用来判断接收的数据位有无错误,一般是奇偶校验。
在使用中,该位常常取消。
(5)停止位:
停止位在最后,用以标志一个字符传送的结束,它对应于逻辑1状态。
(6)位时间:
即每个位的时间宽度。
起始位、数据位、校验位的位宽度是一致的,停止位有0.5位、1位、1.5位格式,一般为1位。
(7)帧:
从起始位开始到停止位结束的时间间隔称之为一帧。
8)波特率:
UART的传送速率,用于说明数据传送的快慢。
在串行通信中,数据是按位进行传送的,因此传送速率用每秒钟传送数据位的数目来表示,称之为波特率。
如波特率9600=9600bps(位/秒)。
UART的数据帧格式为如图1所示
图1:
UART的数据帧格式
2工程实现的基本原则
2.1、FPGAUART系统组成如图2所示:
图2:
FPGAUART系统组成
FPGAUART由三个子模块组成:
(1)波特率发生器;
(2)接收模块;
(3)发送模块;
2.2、波特率发生器
波特率发生器实际上就是一个分频器。
可以根据给定的系统时钟频率(晶振时钟)和要求的波特率算出波特率分频因子,算出的波特率分频因子作为分频器的分频数。
波特率分频因子可以根据不同的应用需要更改。
2.3、UART接收器
由于串行数据帧和接收时钟是异步的,由逻辑1转为逻辑0可以被视为一个数据帧的起始位。
然而,为了避免毛刺影响,能够得到正确的起始位信号,必须要求接收到的起始位在波特率时钟采样的过程中至少有一半都是属于逻辑0才可认定接收到的是起始位。
由于内部采样时钟bclk周期(由波特率发生器产生)是发送或接收波特率时钟频率的16倍,所以起始位需要至少8个连续bclk周期的逻辑0被接收到,才认为起始位接收到,接着数据位和奇偶校验位将每隔16个bclk周期被采样一次(即每一个波特率时钟被采样一次)。
如果起始位的确是16个bclk周期长,那么接下来的数据将在每个位的中点处被采样。
图3:
UART接收器的接收状态机
R_START状态:
当UART接收器复位后,接收状态机将处于这一个状态。
在此状态,状态机一直在等待RXD的电平跳转,从逻辑1变为逻辑0,即起始位,这意味着新的一帧UART数据帧的开始,一旦起始位被确定,状态机将转入R_CENTER状态。
状态图中的RXD_SYNC信号是RXD的同步信号,因为在进行逻辑1或逻辑0判断时,不希望检测的信号是不稳定的,所以不直接检测RXD信号,而是检测经过同步后的RXD_SYNC信号。
R_CENTER状态:
对于异步串行信号,为了使每一次都检测到正确的位信号,而且在较后的数据位检测时累计误差较小,显然在每位的中点检测是最为理想的。
在本状态,就是由起始位求出每位的中点,通过对bclk的个数进行计数(RCNT16),但计数值不是想当然的“1000”,要考虑经过一个状态,也即经过了一个bclk周期,所希望得到的是在采样时1/2位。
另外,可能在R_START状态检测到的起始位不是真正的起始位,可能是一个偶然出现的干扰尖脉冲(负脉冲)。
这种干扰脉冲的周期是很短的,所以可以认为保持逻辑0超过1/4个位时间的信号一定是起始位。
R_WAIT状态:
当状态机处于这一状态,等待计满15个bclk,在第16个bclk是进入R_SAMPLE状态进行数据位的采样检测,同时也判断是否采集的数据位长度已达到数据帧的长度(FRAMELEN),如果到来,就说明停止位来临了。
FRAMELEN在设计时是可更改的(使用了Generic),在本设计中默认为8,即对应的UART工作在8位数据位、无校验位格式。
R_SAMPLE状态:
即数据位采样检测,完成后无条件状态机转入R_WAIT状态,等待下次数据位的到来。
R_STOP状态:
无论停止位是1还是1.5位,或是2位,状态机在R_STOP不具体检测RXD,只是输出帧接收完毕信号(REC_DONE<=‘1’),停止位后状态机转回到R_START状态,等待下一个帧的起始位
2.4、UART发送器
发送器只要每隔16个bclk周期输出1个数据即可,次序遵循第1位是起始位,第8位是停止位。
在本设计中没有校验位,但只要改变Generic参数FrameLen,也可以加入校验位,停止位是固定的1位格式。
图4:
发送状态机的状态图
X_IDLE状态:
当UART被复位信号复位后,状态机将立刻进入这一状态。
在这个状态下,UART的发送器一直在等待一个数据帧发送命令XMIT_CMD。
XMIT_CMD_P信号是对XMIT_CMD的处理,XMIT_CMD_P是一个短脉冲信号。
这时由于XMIT_CMD是一个外加信号,在FPGA之外,不可能对XMIT_CMD的脉冲宽度进行限制,如果XMIT_CMD有效在UART发完一个数据帧后仍然有效,那么就会错误地被认为,一个新的数据发送命令又到来了,UART发送器就会再次启动UART帧的发送,显然该帧的发送是错误的。
在此对XMIT_CMD进行了脉冲宽度的限定,XMIT_CMD_P就是一个处理后的信号。
当XMIT_CMD_P=‘1’,状态机转入X_START,准备发送起始位。
X_START状态:
在这个状态下,UART的发送器一个位时间宽度的逻辑0信号至TXD,即起始位。
紧接着状态机转入X_WAIT状态。
XCNT16是bclk的计数器
X_WAIT状态:
同UART接收状态机中的R_WAIT状态类似。
X_SHIFT状态:
当状态机处于这一状态时,实现待发数据的并串转换。
转换完成立即回到X_WAIT状态。
X_STOP:
停止位发送状态,当数据帧发送完毕,状态机转入该状态,并发送16个bclk周期的逻辑1信号,即1位停止位。
状态机送完停止位后回到X_IDLE状态,并等待另一个数据帧的发送命令。
2.5芯片的选择
1.QuartusII软件
2.AlteraCycloneⅡEP2C8Q208C8N
3.EM1715A稳压电源
3程序设计
3.1顶层程序
libraryIEEE。
useIEEE.STD_LOGIC_1164.ALL。
useIEEE.STD_LOGIC_ARITH.ALL。
useIEEE.STD_LOGIC_UNSIGNED.ALL。
entitytopis
Port(clk32mhz,reset,rxd,xmit_cmd_p_in:
instd_logic。
--总的输入输出信号的定义
rec_ready,txd_out,txd_done_out:
outstd_logic。
txdbuf_in:
instd_logic_vector(7downto0)。
--待发送数据输入
rec_buf:
outstd_logic_vector(7downto0))。
--接收数据缓冲
endtop。
architectureBehavioraloftopis
componentreciever
Port(bclkr,resetr,rxdr:
instd_logic。
r_ready:
outstd_logic。
rbuf:
outstd_logic_vector(7downto0))。
endcomponent。
componenttransfer
Port(bclkt,resett,xmit_cmd_p:
instd_logic。
txdbuf:
instd_logic_vector(7downto0)。
txd:
outstd_logic。
txd_done:
outstd_logic)。
endcomponent。
componentbaud
Port(clk,resetb:
instd_logic。
bclk:
outstd_logic)。
endcomponent。
signalb:
std_logic。
begin
u00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001:
baudportmap(clk=>clk32mhz,resetb=>reset,bclk=>b)。
--顶层映射
u2:
recieverportmap(bclkr=>b,resetr=>reset,rxdr=>rxd,r_ready=>rec_ready,
rbuf=>rec_buf)。
u3:
transferportmap(bclkt=>b,resett=>reset,xmit_cmd_p=>xmit_cmd_p_in,
txdbuf=>txdbuf_in,txd=>txd_out,txd_done=>txd_done_out)。
endBehavioral。
3.2波特率发生器程序
libraryIEEE。
useIEEE.STD_LOGIC_1164.ALL。
useIEEE.STD_LOGIC_ARITH.ALL。
useIEEE.STD_LOGIC_UNSIGNED.ALL。
entitybaudis
Port(clk,resetb:
instd_logic。
bclk:
outstd_logic)。
endbaud。
architectureBehavioralofbaudis
begin
process(clk,resetb)
variablecnt:
integer。
begin
ifresetb='1'thencnt:
=0。
bclk<='0'。
--复位
elsifrising_edge(clk)then
ifcnt>=208thencnt:
=0。
bclk<='1'。
--设置分频系数
elsecnt:
=cnt+1。
bclk<='0'。
endif。
endif。
endprocess。
endBehavioral。
3.2UART发送器程序
libraryIEEE。
useIEEE.STD_LOGIC_1164.ALL。
useIEEE.STD_LOGIC_ARITH.ALL。
useIEEE.STD_LOGIC_UNSIGNED.ALL。
entitytransferis
generic(framlent:
integer:
=8)。
Port(bclkt,resett,xmit_cmd_p:
instd_logic。
--定义输入输出信号
txdbuf:
instd_logic_vector(7downto0):
="11001010"。
txd:
outstd_logic。
txd_done:
outstd_logic)。
endtransfer。
architectureBehavioraloftransferis
typestatesis(x_idle,x_start,x_wait,x_shift,x_stop)。
--定义个子状态
signalstate:
states:
=x_idle。
signaltcnt:
integer:
=0。
begin
process(bclkt,resett,xmit_cmd_p,txdbuf)--主控时序、组合进程
variablexcnt16:
std_logic_vector(4downto0):
="00000"。
--定义中间变量
variablexbitcnt:
integer:
=0。
variabletxds:
std_logic。
begin
ifresett='1'thenstate<=x_idle。
txd_done<='0'。
txds:
='1'。
--复位
elsifrising_edge(bclkt)then
casestateis
whenx_idle=>--状态1,等待数据帧发送命令
ifxmit_cmd_p='1'thenstate<=x_start。
txd_done<='0'。
elsestate<=x_idle。
endif。
whenx_start=>--状态2,发送信号至起始位
ifxcnt16>="01111"thenstate<=x_wait。
xcnt16:
="00000"。
elsexcnt16:
=xcnt16+1。
txds:
='0'。
state<=x_start。
endif。
whenx_wait=>--状态3,等待状态
ifxcnt16>="01110"then
ifxbitcnt=framlentthenstate<=x_stop。
xbitcnt:
=0。
elsestate<=x_shift。
endif。
xcnt16:
="00000"。
elsexcnt16:
=xcnt16+1。
state<=x_wait。
endif。
whenx_shift=>txds:
=txdbuf(xbitcnt)。
xbitcnt:
=xbitcnt+1。
state<=x_wait。
--状态4,将待发数据进行并串转换
whenx_stop=>--状态5,停止位发送状态
ifxcnt16>="01111"then
ifxmit_cmd_p='0'thenstate<=x_idle。
xcnt16:
="00000"。
elsexcnt16:
=xcnt16。
state<=x_stop。
endif。
txd_done<='1'。
elsexcnt16:
=xcnt16+1。
txds:
='1'。
state<=x_stop。
endif。
whenothers=>state<=x_idle。
endcase。
endif。
txd<=txds。
endprocess。
endBehavioral。
3.3UART接收器程序
libraryIEEE。
useIEEE.STD_LOGIC_1164.ALL。
useIEEE.STD_LOGIC_ARITH.ALL。
useIEEE.STD_LOGIC_UNSIGNED.ALL。
entityrecieveris
generic(framlenr:
integer:
=8)。
Port(bclkr,resetr,rxdr:
instd_logic。
--定义输入输出信号
r_ready:
outstd_logic。
rbuf:
outstd_logic_vector(7downto0))。
endreciever。
architectureBehavioralofrecieveris
typestatesis(r_start,r_center,r_wait,r_sample,r_stop)。
--定义各子状态
signalstate:
states:
=r_start。
signalrxd_sync:
std_logic。
begin
pro1:
process(rxdr)
begin
ifrxdr='0'thenrxd_sync<='0'。
elserxd_sync<='1'。
endif。
endprocess。
pro2:
process(bclkr,resetr,rxd_sync)--主控时序、组合进程
variablecount:
std_logic_vector(3downto0)。
--定义中间变量
variablercnt:
integer:
=0。
variablerbufs:
std_logic_vector(7downto0)。
begin
ifresetr='1'thenstate<=r_start。
count:
="0000"。
--复位
elsifrising_edge(bclkr)then
casestateis
whenr_start=>--状态1,等待起始位
ifrxd_sync='0'thenstate<=r_center。
r_ready<='0'。