实验4 UART 实验
实验4:UART串口实验
计算机内部数据通常以字或字节为单位并行进行访问,但与外部设备进行数据交互或与其他计算机进行通信时,也经常需要串行数据通信。串行接口是一类使用相对简单的接口,THINPAD-Cloud教学计算机上也配置了基本的串口,作为连接终端设备的接口。本实验主要完成串行接口的访问。
串口实验目的
-
熟悉THINPAD-Cloud教学计算机串行接口的配置及与总线的连接方式;
-
掌握教学机串口UART的访问时序和方法;
-
理解总线数据传输的基本原理。
实验环境
-
硬件环境:PC计算机,Windows10或者Linux操作系统;THINPAD-Cloud教学计算机或者云实验平台;
-
软件环境:FPGA开发工具软件Vivado;串口调试精灵或THINPAD-Cloud远程实验平台。
实验内容
使用教学计算机上的FPGA芯片,编写代码完成对教学机UART的访问,实现和PC机上运行的串口程序(例如putty)的通信。要求分别实现如下功能:
-
将拨码开关设置为起始地址 Addr,地址单位为 32 位 word。
-
单击复位按钮。
-
测试程序向 FPGA 的串口发送 10 个字节的随机数,FPGA 将随机数存储到 BaseRAM 地址从 Addr 的连续 10 个 word 上(存储进最低 8 位,高 24 位不使用)。
-
程序从 FPGA 的串口接收 10 个字节(若超过 200ms 未收到记为超时)。
-
程序读取 BaseRAM 中对应位置的数据,并将 SRAM 中数据、串口接收到的数据与初始随机数进行对比,对比时只考虑 SRAM 数据的最低 8 位。
实验原理
THINPAD-Cloud教学计算机的FPGA芯片通过基本总线连接了存储器芯片Base_RAM以及控制模块中的UART串口模块。UART模块连接到教学机的Micro USB接口,可作为串口与其他设备连接。本实验中,该Micro USB接口将连接PC机的USB口后虚拟了一个串口RS-232接口,从而完成与PC机上运行的串口通信软件进行通信。
由于UART和Base_RAM共享基本总线,因此,需要有控制信号来区分在一个总线周期内是Base_RAM工作还是UART工作,是进行读操作还是写操作。在THINPAD-Cloud教学计算机中,给出了3位控制信号Base_RAM_EN、Base_RAM_OE、Base_RAM_WE来实现这个功能。
和普通的串口芯片8251不同,教学机上的UART不具备可编程的性质(它本身就是由控制模块编程实现的)。下面简单介绍一下串口收发的原理。
异步接收/发送器(UART),可完成并行数据和串行数据之间的相互转换,还能检测串行通信在传送过程中可能发生的错误。UART主要由数据总线接口、控制逻辑、波特率发生器、发送部分和接收部分等组成。本实验主要涉及UART中最重要的发送部分和接收部分, 其功能包括发送缓冲器(tbr)、发送移位寄存器(tsr)、帧产生、奇偶校验、并转串、数据接收缓冲器(rbr)、接收移位寄存器(rsr)、帧产生、奇偶校验、串转并等。
数据的发送由UART中的微处理器控制,微处理器给出wrn信号,发送器根据此信号将并行数据din[7..0]锁存进发送缓冲器tbr[7..0],并通过发送移位寄存器tsr[7..0]发送串行数据至串行数据输出端sdo。在数据发送过程中用输出信号tbre、tsre作为标志信号,当一帧数据由发送缓冲器tbr[7..0]送到发送移位寄存器tsr[7..0]时,tbre信号为1,而数据由发送移位寄存器tsr[7..0]串行发送完毕时,tsre信号为1,通知CPU在下个时钟装入新数据。发送器结构下图所示。
UART发送器结构
串行数据帧和接收时钟是异步的,发送来的数据由逻辑1变为逻辑0可以视为一个数据帧的开始。接收器先要捕捉起始位,确定rxd输入由1到0,逻辑0要8个CLK16时钟周期,才是正常的起始位,然后在每隔16个CLK16时钟周期采样接收数据,移位输入接收移位寄存器rsr,最后输出数据dout。还要输出一个数据接收标志信号标志数据接收完。接收器结构如下图所示。
UART接收器结构
另外需要注意的是,UART和Base_RAM都是通过基本总线和FPGA相连,本实验仅仅是完成UART的访问,请一定通过控制信号让Base_RAM不工作(不往总线上发送数据)。
实验中要使用的主要芯片的连接关系下图所示。
实验主要芯片连接关系。
主要实验步骤
本实验的操作比较复杂,首先要将教学机和PC机通过Micro-USB线连接好,并正确配置串口的参数(端口、波特率等),然后,在编写Verilog代码时,要正确理解UART的工作原理,设计好UART发送和接收数据的状态转换关系,以及各状态与对应的信号之间的关系。如果使用Thinpad-Cloud云平台的话,上述的设置已经在平台中预置完成,只需要打开串口使用即可。在此基础上,设计好实现的代码,再将代码下载到FPGA中,进行调试。因为是读写串口,所以始终要保持Base_RAM_EN为1(即内存处于禁用状态)。
- 写串口:用Verilog语言编写往串口发送数据的代码,将拨码开关上的数据发送到串口,并在PC端显示。
提示:在reset的时候进行初始化,把wrn置为1,以及把Base_RAM_EN、Base_RAM_OE、Base_RAM_WE置为1,为发送数据做好准备;具体写串口可设计4个状态:
-
第1个状态给Base_RAM数据总线赋要发送的值,置wrn为0,wrn的下降沿UART将待发送数据送入到发送器tbr[7..0]并锁存;
-
第2个状态为置wrn为1,使UART能够把读入的数据串行输出到串口;
-
第3个状态等待被发送数据进入移位寄存器tsr[7..0],即等待tbre信号变为1;
-
最后1个状态等待数据发送完毕tsre信号变为1。
状态转移如下图所示:
串口控制器写操作状态图
- 读串口:用Verilog语言编写读串口数据的代码,将从PC端发送过来的数据读出,并显示到LED灯上。
提示:可设计3个状态。
-
第1个状态位为初始化,置rdn为1,并让接收串口数据的变量赋为高阻态,准备接收数据;
-
状态2,检查data_ready信号量,判断UART是否准备好数据,若果data_ready为1,则说明UART已经准备好数据,此时置rdn为0,使移位寄存器rsr中的数据输出到数据总线dout,进入状态3,否则回到状态1,继续准备接收数据;
-
状态3,从数据总线读取数据,输出到LED灯,回到状态1继续准备接收数据。
状态机如下图所示:
串口控制器读操作状态图
③ 综合上面两个操作,以及上一张的内容,利用一个大的状态机,控制读串口、写RAM、读RAM、写串口等状态,将从PC发送过来的10字节数据,顺序存入BaseRAM中,再从BaseRAM依次读出,送回到PC。具体步骤如下:
-
系统复位后,从拨码开关获得初始内存地址,保存到自己定义的寄存器中(以下称为Addr);
-
读串口,将收到的数据保存到自己定义的寄存器中(以下称为Data);
-
将Data写入到BaseRAM中,地址为Addr的字上。为了简化实现,只使用32位中的低8位存储数据,高24位空间不使用。写入完成后把Addr加一;
-
重复读串口、写内存的步骤10次,也就是说总共从串口接收10个字节,保存到BaseRAM的连续10个字的空间中;
-
将Addr重新设为初始地址(可以从拨码开关获得);
-
读取BaseRAM中地址为Addr的字,将低8位保存到Data寄存器;
-
写串口,把Data发送出去,发送完成后把Addr加一;
-
重复读内存、写串口的步骤10次,即把内存中的10字节数据依次发送出去;
实验中需要交替访问BaseRAM和UART,状态机必须控制好两者的使能信号,以及FPGA自身的数据线高阻态,避免发生冲突。
实验数据
将实验过程中对串口读写的数据记录在下表中:
写串口 | 读串口 |
---|---|
拨码开关数据 收到数据 | 发送数据 数码管显示数据 |
思考题
-
请总结教学机上的UART和普通的串口芯片8251的异同点?(不做要求,可以先参考阅读8251的相关资料。)
-
如果要求将PC端发送过来的数据存入到Base_RAM的某个单元,然后从该单元中读出,再加1送回到PC端,则代码需要进行怎样的修改?有兴趣可以试着做一下。
实验提示
上述实验过程实际上将状态机和需要实现的功能一并叙述了。在实际的工作过程中,串口控制器也最好需要接入50MHz的时钟,这也是为了下一步的处理器实验打下基础,获得感性认识。
首先一定要理解下面的输入输出信号(可以在thinpad_top项目中看到)
//CPLD串口控制器信号
output wire uart_rdn, //读串口信号,低有效
output wire uart_wrn, //写串口信号,低有效
input wire uart_dataready, //串口数据准备好
input wire uart_tbre, //发送数据标志
input wire uart_tsre, //数据发送完毕标志
其中uart_rdn和uart_dataready来控制从串口读取,一个为输入,一个为输出。
uart_wrn,uart_tbre,uart_tsre来控制往串口上写数据,其中uart_wrn说明需要写,uart_tbre和uart_tsre是串口的反馈信号。
串口读的流程:1. 探测到uart_dataready,说明串口有数据,cpld已经将数据准备好,等待控制器读取。2. 设置总线base_ram_data_wire为高阻态,控制器拉低uart_rdn,开始读取。3. 控制器读取数据,拉高uart_rdn,说明读取完毕。
串口写的流程:1. 首先要准备好数据。2. 拉低uart_wrn。3. 拉高uart_wrn。4. 等待uart_tbre拉高。5. 等待uart_tsre拉高。
下面是本实验的工作截图:
1 串口的输出。
2 选择共享总线CPLD模拟,不是直连的串口。
3 打开/关闭串口。
4 发送按钮(可以自行选择,按照程序要求)。
5 需要发送的数据。
6 LED显示。