SAST weekly 是由电子工程系学生科协推出的科技系列推送,内容涵盖信息领域技术科普、研究前沿热点介绍、科技新闻跟进探索等多个方面,帮助同学们增长姿势,开拓眼界,每周更新,欢迎关注!欢迎愿意分享知识的同学投稿至eesast@mail.tsinghua.edu.cn , 期待你的作品!
![5a942742875c3774ec41b0bea6ed0eea.png](https://i-blog.csdnimg.cn/blog_migrate/ec349b560275239d39301e766c20e979.png)
Part I
UART简介
UART,即通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),是一种异步串行通讯方式,在发送数据时将并行数据转换成串行数据传输,在接收数据时将接收到的串行数据转换成并行数据。
UART发送或接收的一帧数据由4个部分组成,分别是起始位、数据位、奇偶校验位和停止位。在空闲时,数据线通常保持着高电平的状态;起始位是一个低电平信号,标志着一帧数据的开始;数据位是一帧数据中传输的有效数据,位数可在5至8位中进行选择,实际应用中通常选择8位;校验位用于检验数据在传输过程中是否出现错误,可选奇校验、偶校验或无校验,奇校验时检查一帧数据中1的个数是否为奇数数,偶校验时则检查一帧数据中1的个数是否为偶数;最后,高电平的停止位表示一帧数据的结束,可选择1位,1.5位或2位。
![7846ae4f40976fc1ee7a8fa35d54d6e7.png](https://i-blog.csdnimg.cn/blog_migrate/5b28a85e88b330d9ec2dfa2795b1f9fa.png)
UART数据格式
由于UART是一种异步的通讯方式,通信双方在不同的时钟域内,因此在进行串口通讯时,需要规定信息的传输速率,即串口通讯的波特率。波特率表示着每秒传输二进制数据的位数(注意并不是一帧数据的个数),单位是 位/秒,即bps。常用的波特率有9600、 19200、 38400、 57600以及115200等,波特率越高则意味着串口传输的速率越快,相应的对设备的要求也会有所提高。
在介绍完了UART的通讯协议后,我们再来了解一下UART的接口标准。常见的UART接口标准有RS232、RS422、RS485等,它们在对信号的传输过程中有着不同的电平标准。RS232是一种在老式台式机上很常见的接口标准,采用负逻辑电平,以+15V作为逻辑0,-15V作为逻辑1,使用RXD、TXD、GND三条线进行数据传输,可实现全双工、点对点的通讯。RS422和RS485则是采用正逻辑电平,与RS232不同,这两种标准采用了差分传输,因此比RS232抗干扰能力要强许多。RS422和RS485的区别是,RS422有四条数据线,可以实现全双工通讯,而RS485只有两条数据线,只能实现半双工通讯。由于现在一般的笔记本上都已经没有物理上的串口了,因此笔记本与外部设备的串口通信一般都是通过USB转串口线来实现的。
![3c364534484968eb457380b04d2e731a.png](https://i-blog.csdnimg.cn/blog_migrate/dfce24d7567a2f4f6918cab4a0452762.jpeg)
USB串口线
![5a942742875c3774ec41b0bea6ed0eea.png](https://i-blog.csdnimg.cn/blog_migrate/ec349b560275239d39301e766c20e979.png)
![5335ece99f849e47e2adfbfa9c4643b8.gif](https://i-blog.csdnimg.cn/blog_migrate/8933c7ccd75bc645e75f33b568273c16.gif)
![5a942742875c3774ec41b0bea6ed0eea.png](https://i-blog.csdnimg.cn/blog_migrate/ec349b560275239d39301e766c20e979.png)
Part II
Verilog程序设计
在熟悉了UART的通讯协议后,我们就可以开始着手编写实现串口通信的Verilog代码了。下面采用8位数据位、1位停止位、无校验位的数据格式,以UART的接收模块为例进行代码编写。
![3c0e101aa2d425fe8e9c61a3d7b6de12.png](https://i-blog.csdnimg.cn/blog_migrate/8d5537c3cdb28e459ae4db4584118d81.png)
首先定义模块的输入与输出。
![95a849fc283bb86a66cb2821cfc8b728.png](https://i-blog.csdnimg.cn/blog_migrate/d46042252c7d0283a159d7e99adef3b8.png)
除了最基本的系统时钟信号与复位信号外,为了实现UART接收功能,还需要一个连接UART接收端口的输入信号uart_rxd,以及输出接收数据的输出信号uart_data和接收完成的标志信号uart_done。
之后,定义模块内部所需要的参数。
![7f7ad2720ae53f432f65648601995e55.png](https://i-blog.csdnimg.cn/blog_migrate/38f2f6c07f7519b59649d5af477fef85.png)
在参数定义时,需要定义系统的时钟频率CLK_FREQ和串口通讯的波特率UART_BPS,其中系统的时钟频率由FPGA所用的晶振频率决定,视不同的情况需要自行调整。此外,还需要用CLK_FREQ和UART_BPS相除,计算出每传输一个bit需要多少个时钟周期,用于之后在接收过程中的计数。
由于空闲时数据线为高电平,起始位是一个低电平信号,所以首先要捕获输入信号uart_rxd的下降沿。
![7ab49c9d21abd7901230fe09f65efad6.png](https://i-blog.csdnimg.cn/blog_migrate/421b19c6359da5876f1599766af6478b.png)
上述代码是一个非常经典的边沿捕捉方法,通过简单的时序分析可得:当且仅当uart_rxd在此时钟周期为低电平,上一个时钟周期为高电平时,该周期内start_flag信号变为高电平,即实现下降沿捕获功能。
当start_flag信号变为高电平,即代表着一帧数据的接收即将开始,之后通过对接收到的bit数进行计数来判断一帧数据的接收是否应当结束。
![f75bd2115f609e605a55b2b808e08261.png](https://i-blog.csdnimg.cn/blog_migrate/320ecb2eb8e9d939e40bd47218c4d198.png)
![f7fb004205f74ca31fb98295e4fe4d7a.png](https://i-blog.csdnimg.cn/blog_migrate/3aea498ad2de90955fe93dcbd893f8b6.png)
在上述两段程序中,第一个always用来控制接收过程的开始与结束,第二个always用来记录接收到第几个bit位。需要注意的是判断接收过程停止的条件,当记录到停止位的一半时将rx_flag置0,结束接收过程。这样做的目的是,当接收到连续的几帧数据时,可以为捕捉下一帧数据的起始位留出足够的时间。
接下来根据接收数据计数器rx_cnt的值为接收数据寄存器赋值。
![c9361e228cdba8dedd311c9bb4552b71.png](https://i-blog.csdnimg.cn/blog_migrate/7aacbdbe10e4c2a9dfd293209b8297a6.png)
在赋值的过程中需要注意的是,在每一bit位的中间到来时将此时接收端口的电平记录下来,作为接收到的数据值。这样做可以避免采样到数据信号在上升沿或下降沿处的不稳定值。
最后,在一帧数据接收完后,输出接收数据寄存器的值,并将接收完成的标志信号拉高。
![c48c9b5eee3993a18cbdfc9b5f30b90e.png](https://i-blog.csdnimg.cn/blog_migrate/7f4625c8943fd8c2018bf43e51593782.png)
不要忘了在最后加endmodule。
![5a942742875c3774ec41b0bea6ed0eea.png](https://i-blog.csdnimg.cn/blog_migrate/ec349b560275239d39301e766c20e979.png)
![5335ece99f849e47e2adfbfa9c4643b8.gif](https://i-blog.csdnimg.cn/blog_migrate/8933c7ccd75bc645e75f33b568273c16.gif)
![5a942742875c3774ec41b0bea6ed0eea.png](https://i-blog.csdnimg.cn/blog_migrate/ec349b560275239d39301e766c20e979.png)
Part III
结果测试
按照上述思路再写一个UART串口发送模块,就可以搭建一个从电脑接收串口数据,再将数据发回电脑的小工程(结构图如下图所示)。
![bcd7b961b8ffe9ac4a3950ceb00211f8.png](https://i-blog.csdnimg.cn/blog_migrate/1eac1ed99fdbe413409b1f58868e764e.png)
在配置好管脚后,将工程烧入FPGA,再打开串口助手,即可检验程序的正确性。
![4a7154af45abf3b45ae711d5999ad8b0.png](https://i-blog.csdnimg.cn/blog_migrate/d9e38dabec8e289e22c396317f628a31.png)
从上述结果中可以看出,电脑发出的数据在被FPGA接收后又成功传回电脑了。
![5a942742875c3774ec41b0bea6ed0eea.png](https://i-blog.csdnimg.cn/blog_migrate/ec349b560275239d39301e766c20e979.png)
![5335ece99f849e47e2adfbfa9c4643b8.gif](https://i-blog.csdnimg.cn/blog_migrate/8933c7ccd75bc645e75f33b568273c16.gif)
![5a942742875c3774ec41b0bea6ed0eea.png](https://i-blog.csdnimg.cn/blog_migrate/ec349b560275239d39301e766c20e979.png)
Part IV
结语
通过这个非常简单的小实验,我们可以深入了解UART的通讯协议,进一步熟悉Verilog语法的使用,并利用UART接收发送模块实现很多其他的更有趣的功能。
祝同学们在数逻的学习过程中收获快乐!
参考资料:
1.百度百科
2.《开拓者FPGA开发指南》
![5a942742875c3774ec41b0bea6ed0eea.png](https://i-blog.csdnimg.cn/blog_migrate/ec349b560275239d39301e766c20e979.png)
![5335ece99f849e47e2adfbfa9c4643b8.gif](https://i-blog.csdnimg.cn/blog_migrate/8933c7ccd75bc645e75f33b568273c16.gif)
![5a942742875c3774ec41b0bea6ed0eea.png](https://i-blog.csdnimg.cn/blog_migrate/ec349b560275239d39301e766c20e979.png)
撰稿人:伍雨心
审稿人:钟宏涛
![a73814c97aca119bed25d896e0a4d32f.png](https://i-blog.csdnimg.cn/blog_migrate/e8bcf93a727d266c507830061d7ce5ff.jpeg)