下冰雹 · 2022年03月06日

【安路 EG4S20 版本】综合性实验设计与实现:实验14 UART串行通信

实验14.1 UART串口接收实验

实验设计目标

  1. 在FPGA中实现串口协议,通过Anlogic_FPGA开发板上的“UART2USB”口接收从计算机发来的数据。

实验设计思路

UART串口是一种类似于USB、VGA的接口,有固定的引脚和通信协议。使用FPGA实现串口通信,可分为“计算机发送数据给FPGA”和“FPGA发送数据给计算机”两部分。本节为串口接收实验,使用FPGA接收从计算机发来的数据。
进行串口接收实验首先需要了解串口的接收时序,图4.1为接收一帧数据时的简单示意图。串口接收只使用一条数据线RX,特点如下:
image.png
图4.1 串口接收时序示意图

  1. 当RX产生了一个下降沿后才开始一帧数据的接收,接收到的第一位为开始位。
  2. 一帧周期内有11个时钟,第一个时钟是开始位,2~9个时钟为数据位,并且数据是从低位到高位的接收的。
  3. 串口的接收时钟频率取决于它的波特率,常用的波特率是有几个固定值的。本实验的波特率选用9600bps,表明1秒内传送9600位数据,则一位数据的周期为:
    image.png
    可以看出,进行串口接收实验的关键在于准确读取RX上的数据,需做到以下两点:①判断什么时候RX开始接收一帧数据,即判断开始位;②判断什么时候读取D0~D7上的数据,即判断数据位。
    为实现第①点,借鉴实验一PWM实验中的“消抖程序”的思想检测RX线上的信号,在RX信号产生了一个下降沿后才启动一帧数据的接收;并且,为保证每一次检测到的都是开始位,必须确定在一次接收中经过了11个时钟后才开始下一帧数据的接收,这可以通过编程实现。
    对于第②点,为保证数据的准确,应在数据位的正中间读取数据。图4.2为读取数据的简单示意图,当BPS_CLK信号为高时,读取RX线上的数据,BPS_CLK信号的高电平出现的频率应为9600Hz。本实验首先将50MHz时钟通过计数器分频到500KHz,然后设计一个计数器Count_BPS,将500KHz的系统基准时钟进行分频,分频数为:
    500000/9600 = 52 (4.2)
    因此,当Count_BPS计数到26时,令BPS_CLK信号为高电平,其他计数值置低,这样使用500KHz时钟在BPS_CLK的高电平时读取数据,就可以在每一位数据的正中间读取数据,确保数据已完整建立。
    image.png
    图4.2 数据读取示意图

    功能模块图与输入输出引脚说明

    图4.3是本实验设计的串口接收系统的示意图,包含开始位检测模块U1、波特率控制模块U2、接收控制模块U3和LED显示模块U4。
    image.png
    图4.3 串口接收系统示意图
    开始位检测模块用于检测一帧数据的开始位,功能如前所述。RX_In与串口的RX线相连,在没有数据传输时,RX线上为高电平;neg_sig为“下降沿标志位”,当检测到RX_In的下降沿时,neg_sig信号被置为1,其他时刻为0。
    波特率控制模块内包含一个计数器Count_BPS,功能如前文所述。BPS_CLK为使能时钟信号,控制何时读取数据。Count_Sig为计数标志位,当一帧数据开始时,Count_Sig被置为1,此时计数器Count_BPS才能开始计数;当一帧数据接收完毕后,Count_Sig被置为0,计数器Count_BPS停止工作。
    接收控制模块从RX_En_Sig信号上的数据帧中读取出数据位,将串行数据转换为并行8位数据并存储于RX_Data中。当一帧数据接收完毕时,“接收完成标志位”RX_Done_Sig被置为1。
    LED显示模块将接收到的八位数据输送到LED灯上。
    在FPGA中实现此系统,工程包含顶层模块DA与底层模块detect_module、rx_bps_module、rx_control_module、LED_display_module,底层模块从左至右依次对应于图4.3中的U1~U4。下面介绍一下顶层模块输入输出引脚的功能:

  4. CLK:50MHz的时钟信号输入。
  5. RSTn:复位输入信号,低电平有效。当RSTn信号为0时,LED_Out全为0。
  6. RX_In:接收输入信号。连接到串口的RX线。
  7. LED_Out:输送到LED灯,共有八位。LED_Out[7:0]存储了一帧数据的MSB至LSB位。

    程序设计

    串口接收程序中的大部分代码功能已在前面的实验中使用过,容易理解,此处仅简单说明。

  8. 图4.4是截取自底层模块rx_control_module的部分代码:
    image.png
    图4.4 rx_control_module核心代码
    ○ 49-54:数据位存储。计算机发送数据时,是先发(最低有效位)LSB的,53行代码依次将RX_In信号的值存储于rData[0]~rData[7]中,rData的值最终将赋给RX_Data。
  9. 图4.6是根据rx_control_module模块中的代码并结合图4.2画出的过程示意图,State信号内寄存当前状态值,最后的“12→13→0”的状态改变是在500KHz时钟上升沿立刻发生的,与前面不同,请结合程序理解。时序设计满足串口通信协议。
    image.png
    图4.6 接收过程示意图

    FPGA管脚配置

    以下是Anlogic FPGA的IO Constraint,CLK信号与开发板上的50MHz的晶振时钟相连;RSTn信号与SWO相连;LED_Out[7:0]分别与LED7~LED0相连;RX_En_Sig信号与SW1相连;RX_In信号与T5管脚相连。
    set_pin_assignment { CLK } { LOCATION = R7; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { LED_Out[0] } { LOCATION = B14; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { LED_Out[1] } { LOCATION = B15; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { LED_Out[2] } { LOCATION = B16; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { LED_Out[3] } { LOCATION = C15; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { LED_Out[4] } { LOCATION = C16; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { LED_Out[5] } { LOCATION = E13; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { LED_Out[6] } { LOCATION = E16; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { LED_Out[7] } { LOCATION = F16; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { RSTn } { LOCATION = A9; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { RX_En_Sig } { LOCATION = A10; IOSTANDARD = LVCMOS33; }
    set_pin_assignment { RX_Pin_In } { LOCATION = F12; IOSTANDARD = LVCMOS33; }
    串口接收实验IO Constraint

    实验结果

    串口通信实验需要通过Anlogic_FPGA开发板上的USB转串口接口完成,因此,直接使用2根USB数据线分别将开发板上的JTAG接口和UART2USB接口与计算机相连,并在电脑上使用串口调试助手,按照以下参数配置:
    image.png
    图4.8 硬件连接和“串口助手”参数设置
    图4.8是使用“串口调试助手”发送数据“AA”的参数界面,实验前需下载串口的驱动程序并安装,插拔UART2USB口的线缆,观察在串口号内是否出现和消失COMx,选择COMx,配置波特率为9600,数据位8位,停止位1位,无校验位和流控制。点击开启串口,选择HEX发送,键入“AA”,(设置ChipWatcher的捕获触发条件为RX引脚的下降沿,并点击)然后点击发送按钮。
    为了更好的理解程序,我们使用ChipWatcher来捕获关键信号,加以诠释,设置ChipWatcher时,关键是设置RX的下降沿为捕获的触发条件,点击Single Trigger,软件会等待RX的下降沿到来才会抓取完整的数据并显示出来:
    image.png
    图4.9 Chipwatcher设置
    image.png
    图4.10 Chipwatcher进入等待触发条件状态
    image.png
    图4.11 这时在串口助手上点击发送,Chipwatcher捕获到完整的一帧RX时序
    我们可以看到关键信号的产生和相互关系:

  10. 当RX的下降沿到来时,利用neg1和neg2产生确定起始条件的neg_sig,neg_sig的产生方法在detect_module.v中描述;
    image.png
  11. 在State=0时,在500K时钟的上升沿采到neg_sig为1就将isCount即Count_Sig赋值为1,同时将State值自加1,进入起始位状态,这在rx_control_module.v里描述;
    image.png
  12. 当Count_Sig为1时,Count_BPS开始计数,仅当Count_BPS =26时,BPS_CLK被赋值为1,时序如下图:
    image.png
    这在rx_bps_module.v里描述:
    image.png
  13. 随后就是关键的状态转换,当Count_Sig为1时,Count_BPS以500K时钟频率在0-52循环计数,每到26,BPS_CLK就为高,此时State信号自加1,当State=2,3,4,5,6,7,8,9时,把RX_Pin_In的值移位存到RX_DATA里(可以看到起始状态下RX_DATA里存的是上一次的数据8’h55,随着State的递增,RX_Pin的值依次赋值给对应的位,最终输出这一次的数据。注意是先发低位,后发高位,最终RX_DATA=8‘b10101010),对应ChipWatcher的图更容易理解如下程序:
    image.png
    image.png
  14. State = 10和11,是校验位和停止位状态;
  15. State=12,isDone信号置1,Count_Sig归零;State=13,State和isDone信号归零;注意State = 12和13没有判断条件,只要500KHz上升沿到来就跳转,因此对UART连续接收的时序没有影响。
    image.png

    思考与拓展

  16. 图4.6中,State的值在发生“12→13→0”的变化时,是随着基准时钟CLK的上升沿而变化的,也就是说,停止位的持续时间只有半个周期,但依然得到了正确的实验结果,请结合程序从“实际有用数据”的角度解释其原因。
  17. 在使用“串口调试助手”时,若选择“无校验位”,实验现象是怎样的?请结合程序及“一帧数据”的格式解释其原因。

实验14.2 UART串口发送实验

实验设计目标

  1. 在FPGA中实现串口协议,通过Anlogic_FPGA开发板上的“UART2USB”口向计算机发送数据。

实验设计思路

在学习了实验4.1中UART串口接收实验的基础上,理解UART串口发送实验就较为简单了。本实验设计使用FPGA向计算机重复发送六个数据“0A、0B、0C、0D、0E、0F”,每隔0.5秒发送一个,在计算机上使用“串口助手”接收数据并验证是否正确。
图4.10为发送一帧数据时的简单示意图。可以看出,串口的发送时序和接收时序是一样的,而串口接收和发送的不同点就在于,接收是把数据从时序中提取出来,发送是把数据添加到时序中去。
image.png
图4.10 串口发送时序示意图
同串口接收一样,进行串口发送实验首先需要产生一个BPS_CLK信号,然后根据BPS_CLK实现TX的时序即可。以下为串口发送的简单步骤:

  1. 由TX产生一个下降沿变化,作为一帧数据的开始,“开始位”时,TX信号置为0。
  2. 把要发送的数据按照先低位后高位的顺序一位一位送给TX。
  3. “校验位”和“停止位”无操作,TX信号置为1。
  4. 一帧数据发送完毕,等到下一次发送开始时,回到步骤(1)。
    图4.11是本实验设计的串口发送系统的示意图,包含数据控制模块U1、波特率控制模块U2和发送控制模块U3。
    image.png
    图4.11 串口发送系统示意图
    数据控制模块内有一个计数器Count,控制系统每隔0.5秒发送一次数据。TX_Data为要发送的8位并行数据;TX_En_Sig为发送使能标志位,它的上升沿将驱动模块U2开始产生BPS_CLK信号,同时驱动U3模块开始发送数据;TX_Done_Sig为发送完成标志位,当一帧数据发送完毕后,TX_Done_Sig信号被置
    为1,这将驱动TX_En_Sig信号变为0 直到开始发送下一组数据。
    波特率控制模块与实验4.1节串口接收实验中模块功能相同,U2模块的输入信号Count_Sig即为U1模块的输出信号TX_En_Sig。
    发送控制模块将TX_Data的值一位一位(LSB先导)的送给TX_Out信号,当一帧数据发送完毕时,TX_Done_Sig被置为1。

    功能模块图与输入输出引脚说明

    在FPGA中实现此系统,顶层模块为tx_top,底层模块data_control_module、tx_bps_module、tx_control_module从左至右依次对应于图4.11中的U1~U3。下面介绍一下顶层模块输入输出引脚的功能:

  5. CLK:50MHz的时钟信号输入。
  6. RSTn:复位输入信号,低电平有效。当RSTn信号为0时,TX_Out恒为1。
  7. TX_In:发送输出信号。连接到串口的TX线。

程序设计

串口发送程序中的大部分代码功能都已在实验4.1节串口接收实验中使用过,容易理解,此处仅简单说明。图4.12是截取自底层模块data_control_module的部分代码:
image.png
图4.12 data_control_module核心代码
○ 28-32:isTX是一个寄存器型信号,最终将赋给TX_En_Sig。当一帧数据发送完毕后,将isTX信号置为0,禁止系统发送数据。
○ 33-35:分频数T05S的值为25000000,当距离上一次发送数据过去0.5秒后,将isTX信号置为1,开始新一轮数据的发送。
○ 37-40:i的取值范围是0~5,用于从六组数据中选择一组发送。

FPGA管脚配置

以下是使用Anlogic的IO Constraint,CLK信号与开发板上的50MHz的晶振时钟相连;RSTn信号与SW0相连;TX_Pin_Out信号与R6管脚相连。
set_pin_assignment { CLK } { LOCATION = R7; IOSTANDARD = LVCMOS33; }
set_pin_assignment { RSTn } { LOCATION = A9; IOSTANDARD = LVCMOS33; }
set_pin_assignment { TX_Pin_Out } { LOCATION = D12; IOSTANDARD = LVCMOS33; }

实验结果

类似于串口接收实验,直接使用2根USB数据线分别将开发板上的JTAG接口和UART2USB接口与计算机相连,在计算机上安装一个“串口调试助手”,即可进行实验。
图4.13是使用“串口调试助手”接收数据“0A、0B、0C、0D、0E、0F”的结果。波特率选择9600,选择8位数据位,1位校验位和1位停止位。实验结果与程序设计相符。
image.png
图4.13 串口发送实验结果
同样的,下面我们使用ChipWatcher来观察时序关系,加深对程序的理解:
image.png
图4.14 串口发送实验ChipWatcher设置
设置ChipWatcher,采样时钟为500KHz,触发条件为TX的下降沿到来且i==4’b0000,也就是我们要看发8’h0A的时序,如果要观察8’h0C的发送时序,需要设置触发条件为TX的下降沿到来且i==4’b0010;
设置完成后点击Single Trigger我们可以看到发送“0A”的完整时序:
image.png
图4.15 发送0A的完整时序
下面我们按照发送流程依次解读程序:

  1. (21-43)每0.5秒拉高一次isTX(也即TX_EN_Sig),发送完毕后再拉低TX_EN_Sig;(33-52)每发送一次,i自加1,i在0-5里循环,从而在0A - 0F里切换发送数据。
    image.png
    图4.16 产生TX_EN_Sig和数据循环发送控制
  2. 当TX_EN_Sig为高时,Count_BPS计数,当Count_BPS=26时,BPS_CLK置1;注意跟UART收数不同的地方在于,收数时Count_BPS是在RX_EN_Sig为高且起始条件到来时(neg_sig==1)才开始计数。
    image.png
    图4.17 产生BPS_CLK
  3. 当BPS_CLK为高时,State自加1,同时拉低TX,发出起始位:
    image.png
    图4.18 产生TX开始标志(TX由高到低)
    第一步到第三步的时序解释如下:
    image.png
    图4.19 使能发送数据并发送起始位的时序
  4. State=1到8,从低位到高位发送TX_Data的数据:
    image.png
    图4.20 由低位到高位发送TX_Data
    image.png
    图4.21 由低位到高位发送TX_Data
  5. State=9到10,发送校验位和停止位
    image.png
  6. State=11,发出TX_Done_Sig标志,State=12,拉低TX_Done_Sig,State归零
    image.png
    image.png

    思考与拓展

  7. 仔细阅读tx_control_module模块的程序,并参考图4.6绘出本实验中发送过程的简单示意图。
  8. 目前是发送完一组数据等待计时到达0.5秒再发送下一组数据,更改程序,实现发送完一组数据后立刻发送下一组数据的功能,并使用ChipWatcher验证从0A发到0F的完整过程。
  9. 建立一个工程,将接收到计算机发来的数据立即返还给计算机。

实验小结

实验14.1与实验14.2节分别描述了串口接收实验与串口发送实验,但仍存在部分限制。例如,当计算机使用UART连续向FPGA写入100个数据时,缺少一个存储区域把这100个数据有效存储起来。

END

文章来源:https://www.yuque.com/yingmuketang/01/gzzqn5

推荐内容

更多内容请关注走进FPGA专栏
推荐阅读
关注数
1615
内容数
27
本专栏将以【安路EG4S开发板】为例,从基础板卡信息及使用教程,基础实验设计与实现及综合性实验设计与实现带大家学习FPGA。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息