UART串通信设计实例
-
2.5
UART
串口通信设计实例(
1
)
接下来用刚才采用的方法设计一个典型实例。在一般的嵌入式开发和
FPG
A
设计中,串
口
UART
是使用非常频繁的一种调试手段。下面我们将使用
Verilog RTL<
/p>
编程设计一个串口
收发模块。
这个实例虽
然简单,
但是在后续的调试开发中,串口使用的次数比较多,这里阐
明它的设计方案,不仅仅是为了讲解
RTL
编程,而且为了
后续使用兼容
ARM9
内核实现嵌入
式
开发。
串口在一般的台式机上都会有。
随着笔记本电脑的使用,
一般会采用
USB
< br>转串口的方案
虚拟一个串口供笔记本使用。图
2-7
p>
为
UART
串口的结构图。串口具有
9
个引脚,但是真正
连接入
< br>FPGA
开发板的一般只有两个引脚。这两个引脚是:发送引脚
< br>TxD
和接收引脚
RxD
。
p>
由于是串行发送数据,因此如果开发板发送数据的话,则要通过
Tx
D
线
1
bit
接着
1 bit
发送。在接收时
,同样通过
RxD
引脚
1
bit
接着
1
bit
接收。
再看看串口发送
/
接收的数据格式(见图
< br>2-8
)。在
TxD
或
RxD
这样的单线上,是从一个周
期的低电平开
始,
以一个周期的高电平结束的。
它中间包含
< br>8
个周期的数据位和一个周期针
对
8
位数据的奇偶校验位。
每次传送一字节数据,
它包含的
8
位是由低位开始传送,
< br>最后一
位传送的是第
7
位。
p>
(点击查看大图)图
2-8
串口发送串行数据的格式示意图
<
/p>
上述格式只是发送串口数据最通常的格式。打开
Windows<
/p>
自带的串口收发软件:超级终端,
可以配置相关的选项。比如,每
秒位数,可以设定一个周期的长度:如果我们设定为
9600
,
则上图中
1
位持续的时间是:
1/9600s
。数据位也可以从
5
、
6
、
7
、
8
中选一位。奇偶校验可
以
从偶校验、奇校验、无、标记、空格中任选一个。停止位可以是:
1
、
1.5
、
2
。在这里,
我们选择最通常的配置,如图
2-9
所示。
这个设计有两个目的:一是从串口中接收数据,发送到输出端
口。
接收的时候是串行的,也
就是一个接一个的;
但是发送到输出端口时,
我们希望是
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;
rx
对应
RxD
,
tx
对应
TxD
。<
/p>
rx_vld
就是“接收有效”信号,
r
x_data
则是“接收字节”
信号。
tx_vld
是“发送有效”信号,
tx_data
是“发送字节”信号。
txrdy
是“发送状态”
信号,它是低电平表示正处于发送状态,不接收新的字节而进行发送。
< br>
我们知道,串行数据的频率是
9600Hz
,而
FPGA
开发板的频率却是非常高的。这里,
我
们假定
FPGA
的工作频率是
25MHz
,
则串口发送
1
位信息,
则
FPGA
上的
clk
需要计数:
2
5
000
000/9600=2604
次。我们知道
rx
一旦变化,不论是从
0
到
1
,还是从
< br>1
到
0
,都表示
1
位信
息的传递开始。因此,我们在设计一个最大计数
值为
2604
的计数器的时候,
rx<
/p>
的变化都将
导致这个计数器重新开始计数。如果计数到
2604
附近,
rx
发生
变化,那么又将导致计数器
清零;如果
rx
没有发生变化,没关系,计数器在计数到
2604
时,自动
清零。因此,
rx
的
变化会不断调整计
数器的计数。
在这个计数器计算到中间,也就是
1302
时,是最佳采样时刻,这个时候,
rx
p>
的电平是
我们需要知道的位信息。
对于
p>
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;