UART串通信设计实例

别妄想泡我
898次浏览
2021年02月11日 04:21
最佳经验
本文由作者推荐

-

2021年2月11日发(作者:星空下的倾情)


2.5



UART


串口通信设计实例(


1


)


< p>
接下来用刚才采用的方法设计一个典型实例。在一般的嵌入式开发和


FPG A


设计中,串


口


UART


是使用非常频繁的一种调试手段。下面我们将使用


Verilog RTL< /p>


编程设计一个串口


收发模块。


这个实例虽 然简单,


但是在后续的调试开发中,串口使用的次数比较多,这里阐

明它的设计方案,不仅仅是为了讲解


RTL


编程,而且为了 后续使用兼容


ARM9


内核实现嵌入


式 开发。



串口在一般的台式机上都会有。


随着笔记本电脑的使用,


一般会采用


USB

< br>转串口的方案


虚拟一个串口供笔记本使用。图


2-7


为


UART


串口的结构图。串口具有


9


个引脚,但是真正


连接入

< br>FPGA


开发板的一般只有两个引脚。这两个引脚是:发送引脚

< br>TxD


和接收引脚


RxD


。


由于是串行发送数据,因此如果开发板发送数据的话,则要通过


Tx D


线


1 bit


接着


1 bit


发送。在接收时 ,同样通过


RxD


引脚


1 bit


接着


1 bit


接收。



再看看串口发送


/


接收的数据格式(见图

< br>2-8


)。在


TxD


或


RxD


这样的单线上,是从一个周


期的低电平开 始,


以一个周期的高电平结束的。


它中间包含

< br>8


个周期的数据位和一个周期针


对


8


位数据的奇偶校验位。


每次传送一字节数据,


它包含的


8


位是由低位开始传送,

< br>最后一


位传送的是第


7


位。






(点击查看大图)图


2-8




串口发送串行数据的格式示意图


< /p>


上述格式只是发送串口数据最通常的格式。打开


Windows< /p>


自带的串口收发软件:超级终端,


可以配置相关的选项。比如,每 秒位数,可以设定一个周期的长度:如果我们设定为


9600


,


则上图中


1


位持续的时间是:


1/9600s


。数据位也可以从


5

< p>
、


6


、


7


、


8


中选一位。奇偶校验可


以 从偶校验、奇校验、无、标记、空格中任选一个。停止位可以是:


1

、


1.5


、


2

。在这里,


我们选择最通常的配置,如图


2-9

< p>
所示。






这个设计有两个目的:一是从串口中接收数据,发送到输出端 口。


接收的时候是串行的,也


就是一个接一个的;


但是发送到输出端口时,


我们希望是


8


位放在一起,成为并行状态


(见


图

< br>2-10


)。我们知道,串口中出现信号,是没有先兆的。如果出现了串行数据, 则如何通


知到输出端口呢?我们引入


“接收有效”


端口。


“接收有效”


端口在一般情况下都是低电平,


一旦有数据到来时,它就变成高电平。下一个模块在得知“接收有效”信号为高电平时, 它


就明白:新到了一个字节的数据,放在“接收字节”端口里面。






图


2-10




串口接收和发送数据时进行串并转换的示意图



二是发送数据到串口。


发送数据的时候,


我们也希望输 入端口能够给出一个简单的形式。


我们引入


“发送有效”


信号,


它为高电平,


表示我们希望把


“发送字节”


送入


TxD


发送出去。


但是“发送有效”信号是否生效是有限制的,


也就 是正在发送的时候,


是不能接收新的数据


并发送的。所以,我们 引入一个“发送状态”信号,它标识当前的“发报机”是否处于忙碌


状态。如果“发报机 ”处于忙碌状态,则它拒绝“发送有效”信号,不予执行。



根据上面的分析,可以确定端口信号如下:



1.



2.



3.



4.



5.



6.



7.



8.



9.



module rxtx (



clk,



rst,



rx,



tx_vld,



tx_data,





rx_vld,



rx_data,



10.



tx,



11.



txrdy



12.



);



13.



input clk;



14.



input rst;



15.



input rx;



16.



input tx_vld;



17.



input [7:0] tx_data;



18.





19.



output rx_vld;



20.



output [7:0] rx_data;



21.



output tx;



22.



output txrdy;


< p>
rx


对应


RxD


,


tx


对应


TxD


。< /p>


rx_vld


就是“接收有效”信号,


r x_data


则是“接收字节”


信号。


tx_vld


是“发送有效”信号,


tx_data

< p>
是“发送字节”信号。


txrdy


是“发送状态”


信号,它是低电平表示正处于发送状态,不接收新的字节而进行发送。

< br>


我们知道,串行数据的频率是


9600Hz

< p>
,而


FPGA


开发板的频率却是非常高的。这里, 我


们假定


FPGA


的工作频率是


25MHz


,


则串口发送

1


位信息,


则


FPGA

< p>
上的


clk


需要计数:


2 5


000


000/9600=2604

次。我们知道


rx


一旦变化,不论是从

0


到


1


,还是从

< br>1


到


0


,都表示


1


位信


息的传递开始。因此,我们在设计一个最大计数 值为


2604


的计数器的时候,


rx< /p>


的变化都将


导致这个计数器重新开始计数。如果计数到

< p>
2604


附近,


rx


发生 变化,那么又将导致计数器


清零;如果


rx

没有发生变化,没关系,计数器在计数到


2604


时,自动 清零。因此,


rx


的


变化会不断调整计 数器的计数。



在这个计数器计算到中间,也就是


1302


时,是最佳采样时刻,这个时候,


rx


的电平是


我们需要知道的位信息。


对于


rx


的接收,


需要


2


~


3


个寄存器同步,


来消除异步传送的不确


定性。下面描述的


rx1


、


rx2


、


rx3< /p>


、


rxx


只是对


rx


进行延时,消除异步效果。



1.



2.



3.



4.



5.



6.



7.



reg rx1,rx2,rx3,rxx;



always @ ( posedge clk ) begin



rx1


<


= rx;



rx2


<


= rx1;



rx3


<


= rx2;



rxx


<


= rx3;



end



对于


rxx


,我们将检测它的变化,这个变化将作为 置位计数器的标志。


rx_change


表示

< br>rxx


发生了改变,它比较了


rx_dly


和


rxx


的差别。



1.



2.



3.



4.



5.



reg rx_dly;



always @ ( posedge clk )



rx_dly


<


= rxx;





wire rx_change;


-


-


-


-


-


-


-


-