




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第第页UART串口收发的原理与Verilog设计实现一、软件平台与(硬件)平台
软件平台:
1、(操作系统):Windows-8.1
2、开发套件:ISE14.7
3、(仿真)工具:Model(Sim)-10.4-SE
硬件平台:
1、(FPGA)型号:XC6SLX45-2CSG324
2、(USB)转(UART)(芯片):(SiliconLabs)CP2102GM
二、原理介绍
串口是串行(接口)(serialport)的简称,也称为串行(通信接口)或COM接口。串口(通信)是指采用串行通信协议(serialcommun(ic)ation)在一条(信号)线上将数据一个比特一个比特地逐位进行传输的通信模式。串口按(电气)标准及协议来划分,包括(RS)-232、RS-422、(RS485)等。其中最常用的就是RS-232接口。
RS-232接口有以下三个特性:
1、用了一个9针的(连接器)"DB-9"(早期的(电脑)有用25针的连接器"DB-25")
2、允许全双工通信(即通过串口发送数据和接收数据可以同时进行)
3、通信的最大速率大约在10KBy(te)s/s左右
现在一般都用USB转串口线进行串口通信):
虽然DB-9接头一共有9根线,但是实现串口通信只需要其中的3根线就可以了,分别是:
1、(pi)n-2:RXD(receivedata),接收串行数据
2、pin-3:TXD(transmitdata),发送串行数据
3、pin-5:GND(ground),地线
在串口通信中,数据在1位宽的单条线路上进行传输,一个字节的数据要分为8次,由低位到高位按顺序一位一位的进行传送,这个过程称为数据的"串行化(serialized)"过程。由于串口通信是一种异步通信协议,并没有(时钟)信号随着数据一起传输,而且空闲状态(没有数据传输的状态)的时候,串行传输线为高电平1,所以发送方发送一个字节数据之前会先发送一个低电平0,接收方收到这个低电平0以后就知道有数据要来了,准备开始接收数据从而实现一次通信。串口通信的时序如下图所示:
串口通信的规范如下:
1、空闲状态(没有数据传输的状态)下,串行传输线上为高电平1
2、发送方发送低电平0表示数据传输开始,这个低电平表示传输的起始位
3、8-bit的数据位(1Byte)是从最低位开始发送,最高位最后发送
4、数据位的最高位发送完毕以后的下一位是奇偶校验位,这一位可以省略不要,同时,当不发送奇偶校验位的时候接收方也相应的不接收校验位
5、最后一位是停止位,用高电平1表示停止位
下面以发送字节0x55为例来说明整个的发送过程:
先把0x55转化成二进制为:01010101。显然0x55的最低位bit0是1,次低位bit1是0,……..,最高位bit7是0,由于串口是从最低位开始发送一个字节,所以0x55各个位的发送顺序是1-0-1-0-1-0-1-0,波形如下图所示
下面在给出一个波形,根据上面的规则也可以很容易判断这是发送字节0x13的波形
接下来的最后一个问题是:串口传输的速度是多少?
实际上,串口传输的速度用波特率(baudrate)来指定。波特率表示的是每秒发送的比特数,单位是bps(bits-per-seconds),例如,1000bauds表示1秒钟发送了1000个比特,或者说每个比特持续的时间是1ms。关于串口发送的波特率是有一组标准的规定的,并不是随便一个数字。常用的波特率标准有:
1、1200bps
2、9600bps(常用)
3、38400bps
4、115200bps(常用,而且通常情况下是我们能用的最快的波特率)
波特率为115200bps时,每个比特持续的时间为(1/115200)=8.7us,所以发送8个bit(1Byte)需要的时间是8*8.7us=69us。在不考虑奇偶校验位的情况下,发送一个字节还需要发送额外的1个起始位和1个停止位,所以发送1个字节实际所需要的最少时间是10*8.7us=87us,这意味着1s(1000000us)中能发送的字节数为(1000000/87)=11494,所以在波特率为115200bps的情况下,串口传输数据的速率约为11.5KB/s。而有些电脑的串口有时候需要一个更长的停止位,比如1.5位或2位的停止位,那么发送一个字节所需要的时间比只有一个比特停止位的情况所耗费的时间更长,在这种情况下,串口的传输速率会低于10.5KB/s。
通过上面一系列的总结以后,可以得出FPGA与PC之间的串口通信主要包括三个模块:波特率产生模块、发射模块和接收模块。
三、目标功能
1、编写发送模块的(verilog)代码,并往PC上连续不断发送0x00~0xff这些数据,PC上用串口调试助手进行接收并以16进制显示出来
2、在第一个功能的基础上编写接收模块的verilog代码,接收模块接收到第一个功能中发送模块发送的数据以后,用接收到的并行数据的低四位驱动板上的四个(LED)灯
3、编写一个顶层模块把发送模块和接收模块均例化进去,然后从PC的串口调试助手上发送数据到FPGA,FPGA接收到数据以后把接收的数据返回给串口调试助手显示
四、设计思路与Verilog代码编写
4.1、发送模块波特率时钟的设计与实现
本节以波特率为115200bps为例来说明波特率模块设计方法,其余波特率可以以此类推。由于我的开发板上的时钟为50MHz,周期T=20ns,而波特率为115200bps,所以1个bit持续的时间是8.7us,那么每个bit占用的周期数N=(8.7us/20ns)=434,所以可以定义一个计数器,每当计数器从0计数到433的时候就把计数器清零,然后在计数值为1(这个计数值最好比433的一半要小,这篇博客的最后一部分分析了原因)的情况下产生一个高脉冲。发射模块只要(检测)到这个高脉冲的到来就发送一个bit,这样就实现了波特率为115200bps的串口数据发送。
而接收模块的波特率时钟产生逻辑与发送的波特率时钟相比稍有不同。不同之处在于当接收模块检测到I_(rs232)_rxd的下降沿以后,表示有数据过来,准备开始接收数据了,由于一个bit持续的时间为434个时钟周期,所以为了保证接收模块接收数据的准确性,我们需要在434/2=217个周期,也就是数据的正中间位置的时候把输入的数据接收并存起来。也就是说接收模块的波特率时钟要比发射模块的波特率时钟滞后数个周期
波特率产生模块的框图如下图所示
其中:
I_clk是系统时钟;
I_rst_n是系统复位;
I_tx_bps_en是发射模块波特率使能信号,当I_tx_bps_en为1时O_bps_tx_clk才有时钟信号输出;
I_rx_bps_en是接收模块波特率使能信号,当I_rx_bps_en为1时O_bps_rx_clk才有时钟信号输出。
波特率模块的完整代码如下:
modulebaudrate_gen(inputI_clk,//系统50MHz时钟inputI_rst_n,//系统全局复位inputI_bps_tx_clk_en,//串口发送模块波特率时钟使能信号inputI_bps_rx_clk_en,//串口接收模块波特率时钟使能信号outputO_bps_tx_clk,//发送模块波特率产生时钟outputO_bps_rx_clk//接收模块波特率产生时钟);pa(ram)eterC_BPS9600=5207,//波特率为9600bpsC_BPS19200=2603,//波特率为19200bpsC_BPS38400=1301,//波特率为38400bpsC_BPS57600=867,//波特率为57600bpsC_BPS115200=433;//波特率为115200bpsparameterC_BPS_SELECT=C_BPS115200;//波特率选择reg[12:0]R_bps_tx_cnt;reg[12:0]R_bps_rx_cnt;/////////////////////////////////////////////////////////////功能:串口发送模块的波特率时钟产生逻辑///////////////////////////////////////////////////////////always@(posedgeI_clk(or)negedgeI_rst_n)beginif(!I_rst_n)R_bps_tx_cnt>1'b1)?1'b1:1'b0;endmodule
波特率模块的ModelSim仿真图为
4.2、发送模块的设计与实现
有了波特率时钟以后,就可以开始编写发送模块的内部逻辑了。发送模块的结构框图如下图所示
其中:
I_clk是系统时钟;
I_rst_n是系统复位;
I_tx_start是开始发送信号,当检测到I_tx_start为高电平时,立马把输入I_para_data[7:0]的数据串行化成单bit的发出去;
I_bps_tx_clk是发送模块波特率时钟信号,当检测到I_bps_tx_clk为高的时候就发送1个bit;
I_para_data[7:0]是并行的8-bit数据;
O_rs232_txd是串行的bit数据流;
O_bps_clk_en是发射波特率时钟启动信号,当它为1是波特率产生模块才能产生发射模块的波特率时钟;
O_tx_done是发送1字节数据完成的标志位,当一个字节发送完毕以后,O_tx_done产生一个高脉冲。
以发送字节0x55为例,发送模块几个关键信号的时序图如下图所示
发送模块的代码如下:
moduleuart_txd(inputI_clk,//系统50MHz时钟inputI_rst_n,//系统全局复位inputI_tx_start,//发送使能信号inputI_bps_tx_clk,//发送波特率时钟input[7:0]I_para_data,//要发送的并行数据outputregO_rs232_txd,//发送的串行数据,在硬件上与串口相连outputregO_bps_tx_clk_en,//波特率时钟使能信号outputregO_tx_done//发送完成的标志);reg[3:0]R_state;regR_transmi(ti)ng;//数据正在发送标志///////////////////////////////////////////////////////////////////////////////产生发送R_transmiting标志位/////////////////////////////////////////////////////////////////////////////always@(posedgeI_clkornegedgeI_rst_n)beginif(!I_rst_n)R_transmitingen(dc)aseendendelsebeginO_bps_tx_clk_en
其中当检测到输入信号I_tx_start为高电平以后,发送模块立即把R_transmiting信号拉高,表示开始要发送数据了,在R_transmiting为高电平的期间,打开波特率时钟使能信号并且在波特率时钟的控制下通过一个状态机把并行数据发送出去,并产生发送完成信号O_tx_done,等O_tx_done为高以后再把R_transmiting拉低表示一次发送结束。
为了实现功能1的效果还需要编写一个顶层模块把波特率模块和发送模块例化进去并产生发送的信号,顶层模块的代码如下:
moduleuart_tx_top(inputI_clk,//系统50MHz时钟inputI_rst_n,//系统全局复位outputO_rs232_txd//发送的串行数据,在硬件上与串口相连);wireW_bps_tx_clk;wireW_bps_tx_clk_en;wireW_tx_start;wireW_tx_done;wire[7:0]W_para_data;reg[7:0]R_data_reg;reg[31:0]R_cnt_1s;regR_tx_start_reg;assignW_tx_start=R_tx_start_reg;assignW_para_data=R_data_reg;///////////////////////////////////////////////////////////////////////产生要发送的数据/////////////////////////////////////////////////////////////////////always@(posedgeI_clkornegedgeI_rst_n)beginif(!I_rst_n)beginR_cnt_1s
(下载)到板之前先用Modelsim仿一下看逻辑是否正确,仿之前把R_cnt_1s这个参数的上限值设置小一点,比如5000,可以加快仿真速度,下图是仿真时序图,显然完全满足设计要求。
仿真结束以后就绑定管脚然后下载到FPGA中,接着打开电脑的串口调试助手,下图是我的电脑上的显示效果:
4.3、接收模块的设计与实现
波特率模块和发送模块都没问题以后,就可以开始编写接收模块的代码了。接收模块的结构框图如下图所示
其中:
I_clk是系统时钟;
I_rst_n是系统复位;
I_rx_start是开始发送信号,当I_rx_start一直为高电平时,接收模块检测到有数据就会接收;
I_bps_rx_clk是接收模块波特率时钟信号,当检测到I_bps_rx_clk为高的时候就接收1个bit;
I_rs232_rx是串行的bit数据流;
O_para_data[7:0]是并行的8-bit数据;
O_bps_rx_clk_en是发射波特率时钟启动信号,当它为1是波特率产生模块才能产生接收模块的波特率时钟;
O_rx_done是接收1字节数据完成的标志位,当一个字节接收完毕以后,O_rx_done产生一个高脉冲。
接收模块与发射模块的逻辑结构非常类似,但是由于接收模块需要判断串行数据流的起始位,所以还要加一段检测串行数据流下降沿的逻辑,检测串行数据流下降沿的代码如下:
//////////////////////////////////////////////////////////////////////////////////功能:把I_rs232_rxd打的前两拍,是为了消除亚稳态//把I_rs232_rxd打的后两拍,是为了产生下降沿标志位////////////////////////////////////////////////////////////////////////////////always@(posedgeI_clkornegedgeI_rst_n)beginif(!I_rst_n)beginR_rs232_rx_reg0
这段逻辑一共把I_rs232_rxd信号打了四拍,其中前两排是为了消除I_rs232_rxd的亚稳态(后面有时间专门讨论亚稳态问题),后两排用来产生I_rs232_rxd信号下降沿的标志位。
这里以接收0x55这个字节为例来演示接收模块的几个重要信号的时序图如下图所示:
接收模块的完整代码如下:
moduleuart_rxd(inputI_clk,//系统50MHz时钟inputI_rst_n,//系统全局复位inputI_rx_start,//接收使能信号inputI_bps_rx_clk,//接收波特率时钟inputI_rs232_rxd,//接收的串行数据,在硬件上与串口相连outputregO_bps_rx_clk_en,//波特率时钟使能信号outputregO_rx_done,//接收完成标志outputreg[7:0]O_para_data//接收到的8-bit并行数据);regR_rs232_rx_reg0;regR_rs232_rx_reg1;regR_rs232_rx_reg2;regR_rs232_rx_reg3;regR_receiving;reg[3:0]R_state;reg[7:0]R_para_data_reg;wireW_rs232_rxd_neg;//////////////////////////////////////////////////////////////////////////////////功能:把I_rs232_rxd打的前两拍,是为了消除亚稳态//把I_rs232_rxd打的后两拍,是为了产生下降沿标志位////////////////////////////////////////////////////////////////////////////////always@(posedgeI_clkornegedgeI_rst_n)beginif(!I_rst_n)beginR_rs232_rx_reg0
在下载到开发板测试之前,可以先用ModelSim软件对模块进行一个功能仿真,方法是直接把接收模块例化到上一小节测试发送模块的例子中,例化的顶层代码如下:
moduleuart_top(inputI_clk,//系统50MHz时钟inputI_rst_n,//系统全局复位output[3:0]O_led_out,outputO_rs232_txd//发送的串行数据,在硬件上与串口相连);wireW_bps_tx_clk;wireW_bps_tx_clk_en;wireW_bps_rx_clk;wireW_bps_rx_clk_en;wireW_tx_start;wireW_tx_done;wireW_rx_done;wire[7:0]W_para_data;wire[7:0]W_rx_para_data;reg[7:0]R_data_reg;reg[31:0]R_cnt_1s;regR_tx_start_reg;assignW_tx_start=R_tx_start_reg;assignW_para_data=R_data_reg;assignO_led_out=W_rx_para_data[3:0];///////////////////////////////////////////////////////////////////////产生要发送的数据/////////////////////////////////////////////////////////////////////always@(posedgeI_clkornegedgeI_rst_n)beginif(!I_rst_n)beginR_cnt_1s
仿真图如下图所示
由图可以看到接收数据与发送的数据完全一致,说明逻辑没有问题,接下来就绑定管脚然后把代码下载到FPGA看看效果,正常的效果是,PC的串口调试助手一直按顺序显示00~FF这些数据,板上的LED灯的状态与数据的低四位状态相同。至此,功能二也全部实现完毕。
4.4、串口回显功能的设计与实现
有了发射模块和接收模块以后,功能三的要求就很简单了,直接写一个顶层模块,把串口的发送模块与接收模块例化进去就可以了,唯一要做的就是把接收模块的接收完成标志位O_rx_done连接到发送模块的I_tx_start上,把接收模块的8-bit并行输出总线O_para_data连接到发送模块的8-bit并行输入总线I_para_data上,下面直接给出顶层的代码:
moduleuart_top(inputI_clk,//系统50MHz时钟inputI_rst_n,//系统全局复位inputI_rs232_rxd,//接收的串行数据,在硬件上与串口相连outputO_rs232_txd,//发送的串行数据,在硬件上与串口相连output[3:0]O_led_out);wireW_bps_tx_clk;wireW_bps_tx_clk_en;wireW_bps_rx_clk;wireW_bps_rx_clk_en;wireW_rx_done;wireW_tx_done;wire[7:0]W_para_data;assignO_led_out=W_para_data[3:0];baudrate_genU_baudrate_gen(.I_clk(I_clk),//系统50MHz时钟.I_rst_n(I_rst_n),//系统全局复位.I_bps_tx_clk_en(W_bps_tx_clk_en),//串口发送模块波特率时钟使能信号.I_bps_rx_clk_en(W_bps_rx_clk_en),//串口接收模块波特率时钟使能信号.O_bps_tx_clk(W_bps_tx_clk),//发送模块波特率产生时钟.O_bps_rx_clk(W_bps_rx_clk)//接收模块波特率产生时钟);uart_txdU_uart_txd(.I_clk(I_clk),//系统50MHz时钟.I_rst_n(I_rst_n),//系统全局复位.I_tx_start(W_rx_done),//发送使能信号.I_bps_tx_clk(W_bps_tx_clk),//波特率时钟.I_para_data(W_para_data),//要发送的并行数据.O_rs232_txd(O_rs232_txd),//发送的串行数据,在硬件上与串口相连.O_bps_tx_clk_en(W_bps_tx_clk_en),//波特率时钟使能信号.O_tx_done(W_tx_done)//发送完成的标志);uart_rxdU_uart_rxd(.I_clk(I_clk),//系统50MHz时钟.I_rst_n(I_rst_n),//系统全局复位.I_rx_start(1'b1),//接收使能信号.I_bps_rx_clk(W_bps_rx_clk),//接收波特率时钟.I_rs232_rxd(I_rs232_rxd),//接收的串行数据,在硬件上与串口相连.O_bps_rx_clk_en(W_bps_rx_clk_en),//波特率时钟使能信号.O_rx_done(W_rx_done),//接收完成标志.O_para_data(W_para_data)//接收到的8-bit并行数据);endmodule
建立工程并绑定管脚以后下载到开发板中,利用串口调试助手的自动发送(自动发送的周期最好在200ms以上)功能我对波特率为9600bps和115200bps分别进行了测试,在9600bps的情况下我一共发送了1002512个字节,全部接受正确,115200bps波特率情况下一共发送了512325字节,也全部接受正确,逻辑基本稳定,欢迎大家继续测。我第一次写串口代码的时候出现过在115200bps的情况下发送字节达到10万以上的时候出现误码的情况,原因下一小节再说,上面的代码已经把这个问题修复了,原因就出在波特率模块上。至此,功能三已全部完成。
五、进一步思考
5.1、波特率模块产生的O_bps_tx_clk滞后O_bps_rx_clk可能出现的问题
我最开始写的波特率模块如下:
modulebaudrate_gen(inputI_clk,//系统50MHz时钟inputI_rst_n,//系统全局复位inputI_bps_tx_clk_en,//串口发送模块波特率时钟使能信号inputI_bps_rx_clk_en,//串口接收模块波特率时钟使能信号
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高效备考2024年CPSM考试试题及答案
- 2024年CPMM备考心得试题及答案
- CPSM考试界定范围试题及答案
- 2024年CPSM考试程序解析试题及答案
- 精确识别CPSM考试试题及答案
- 2025届内蒙古重点中学高三最后一模化学试题含解析
- 2025届内蒙古乌兰察布市重点中学高三第二次诊断性检测化学试卷含解析
- CPSM考试高分复习法则试题及答案
- 陕西省西安市西安电子科技大附中2025届高考化学全真模拟密押卷含解析
- 体育老师安全知识培训课件
- 2024年长江工程职业技术学院单招职业技能测试题库及答案解析
- T∕CACM 1075-2018 中医治未病技术操作规范 艾灸
- 宣传视频拍摄服务 投标方案(技术方案)
- 竹简制作工艺
- 比例的意义公开课省公开课一等奖全国示范课微课金奖课件
- 仓库管理员培训考试试题-含答案-
- JTG∕T F30-2014 公路水泥混凝土路面施工技术细则
- 水库巡查方案
- 植物生理学课件(王小菁-第8版)-第五章-植物同化物的运输
- 小学科学湘科版四年级下册全册同步练习含答案
- 小红书种草计划书
评论
0/150
提交评论