《Xilinx FPGA设计与实践教程》课件-第8章_第1页
《Xilinx FPGA设计与实践教程》课件-第8章_第2页
《Xilinx FPGA设计与实践教程》课件-第8章_第3页
《Xilinx FPGA设计与实践教程》课件-第8章_第4页
《Xilinx FPGA设计与实践教程》课件-第8章_第5页
已阅读5页,还剩52页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第八章UART串口通信控制器

8.1UART传输系统8.2UART接收模块设计8.3UART发送模块设计8.4UART系统的总结本章小结 8.1UART传输系统

UART整个系统包含两个部分:发送器和接收器。发送器主要是使用移位寄存器将并行的数据一位一位地按照某特定速率发送出去,而接收器恰好相反,它将数据使用移位寄存器一位一位地接收回来,然后再进行打包。整个UART数据传输在单线上进行,发送和接收信号线分别标记为TXD和RXD。具体传输过程如下:首先在不进行数据传输时,处于空状态(即idle状态),串行线RXD或者TXD上面信号置1(高电平)。在数据发送过程中,开始时发送0(Start状态,意味着发送数据开始),然后依次发送数据位(可选择6位、7位和8位的数据位宽)、奇偶校验位(位数可选)、停止位。在这里,奇偶校验是为了检验传输中是否有误码。对于偶校验来说,当传输数据中有偶数个1时,校验位为0。对于奇校验,当传输数据中有奇数个1时,校验位为0;停止位置1(高电平),可以是1位、1.5位或者2位。如图8-1所示为8位数据传输位,无校验位,1位停止位的UART传输数据格式。在这里要注意,数据传输为LSB方式,即低位在前,高位在后;另外,还有MSB方式,即高位在前,低位在后。所以数据处理时一定要注意数据的传输方式。图8-18位UART数据传输协议另外,要注意串口传输过程中物理连线仅仅有三根信号线:TXD、RXD和GND信号。所以UART传输过程当中,没有时钟信息包含在里面。那么发送端与接收端需要协商一个数据传输的速率才能进行传输,通常称为传输波特率,即每秒钟传输多少位数据。波特率的计算包括了数据位数、停止位、校验位。通常所用的波特率包括以下几种:2400,9600,19200Bps(即B/s,波特每秒)等。本节举例以如下的通信方式为标准:波特率为19200,8位数据宽,1位停止位且没有校验位。 8.2UART接收模块设计

8.2.1设计方案

通常选用16倍于波特率的时钟进行采样,也就是说串行通信线上的每个数据位都采样16次。假设在数据传输中有N位的数据和M位的停止位,那么过采样的具体步骤如下:

(1)等待接收信号为0,按照UART协议,数据传输以0(低电平)为起始位,开启采样时钟计数器。

(2)当计数器计数到7,也就是已经计数到起始位数据的中间时刻时,开始清零计数器,然后重新开始。

(3)当计数器计到15时,从时间上分析已经到第一位数据的中间,这时开始采集数据,并移位到寄存器中,然后重新启动计数器。

(4)重复N-1次步骤(3),接收剩余的数据。

(5)如果使用了校验位,那么再重复一次步骤(3)来获取校验位值。

(6)重复M次步骤(3),获取停止位。采用上述方法有如下优点:使用采样时钟来估计数据到达的中间时刻,然后采样,即使在数据起始位采集不准时,估计的误差也仅仅在1/16,也就是后续采集数据时刻会有距数据到达中间时刻有1/16的数据偏差,其实是不会影响数据的正确采集的。但是也有缺点:数据波特率不可以太高。如果波特率太高,要求的采样时钟就会太高,这样会引起系统的不稳定。整个UART接收模块包括如下几个部分(如图8-2所示):

(1) UART接收器:用来接收串行传输数据;

(2)波特率产生器:产生采样时钟;

(3)接口电路:包括提供数据缓冲,UART和其它系统之间的握手状态信号等。图8-2UART接收器模块框图8.2.2波特率产生器

根据过采样采集原理,波特率产生器需要产生一个采样信号,其频率为UART传输波特率的16倍。为了不在FPGA系统中产生别的时钟域,从而违背FPGA同步设计的原则,应采用系统时钟的使能时钟脉冲来产生采样信号,而不是采用直接送到UART接收器的时钟信号。

对于19 200Bps波特率来说,采样频率应该为307200(19 200 × 16)。由于系统时钟为50MHz,波特率产生

器需要一个模163计数器,也就是每163个时钟产生一个时钟脉宽的脉冲信号作为接收采样信号。8.2.3UART接收器

为了能够清晰地了解过采样数据采集方法,设计了如图8-3所示的UART接收模块流程图。为了增强程序的规范性并方便以后的修改,设置了两个常数D_BIT和SB_TICK。D_BIT表示数据的位宽,包括16、32、24位;SB_TICK表示针对不同的停止位需要的采样时钟脉冲个数,对应停止位为1、1.5和2位,所选择的采样脉冲数为16、24和32。选择D_BIT为8位,即停止位为1位,SB_TICK为16位。按照上述过采样原理,所设计流程图包括三个状态:开始、数据传输和停止状态,对应于UART传输协议当中的开始位、数据传输位、停止位。s_tick信号为波特率产生模块提供的脉冲信号,它在每16个时钟周期有一个翻转。需要注意的是,状态机是在每次s_tick信号有效之后才进行状态变化的。同时设置两个寄存器(计数器):s和n。s寄存器用来追踪采样时钟数,在start状态时计数到7,在数据传输状态时计数到15,然后等SB_TICK信号来临时进入停止状态。n计数器追踪在数据传输状态接收到的数据位数,接收到数据移位寄存到b寄存器当中。状态信号rx_done_tick用来指示接收状态的结束标志,在接收状态结束时输出一个时钟周期的高电平。对应代码如程序8-1所示。图8-3UART接收器的ASMD状态转移图

【程序8-1】UART接收器。

moduleuart_rx

#(

parameterDBIT=8, //数据位宽

SB_TICK=16//对应停止位的采样脉冲数

)

(

input

wireclk,reset,

input

wirerx,s_tick,

output

regrx_done_tick,

output

wire[7:0]dout

);

//状态机状态声明

localparam[1:0]

idle=2'b00,

start  =2'b01,

data=2'b10,

stop=2'b11;

//信号声明

reg[1:0]state_reg,state_next;

reg[3:0]s_reg,s_next;

reg[2:0]n_reg,n_next;

reg[7:0]b_reg,b_next;

//FSMD状态和数据寄存器

always@(posedgeclk,posedgereset)

if(reset)

begin

state_reg<=idle;

s_reg<=0;

n_reg<=0;

b_reg<=0;

end

else

begin

state_reg<=state_next;

s_reg<=s_next;

n_reg<=n_next;

b_reg<=b_next;

end

//FSMD下一状态逻辑

always@*

begin

state_next=state_reg;

rx_done_tick=1'b0;

s_next=s_reg;

n_next=n_reg;

b_next=b_reg;

case(state_reg)

idle:

if(~rx)

begin

state_next=start;

s_next=0;

end

start:

if(s_tick)

if(s_reg==7)

begin

state_next=data;

s_next=0;

n_next=0;

end

else

s_next=s_reg+1;

data:

if(s_tick)

if(s_reg==15)

begin

s_next=0;

b_next={rx,b_reg[7:1]};

if(n_reg==(DBIT-1))

state_next=stop;

else

n_next=n_reg+1;

end

else

s_next=s_reg+1;

stop:

if(s_tick)

if(s_reg==(SB_TICK-1))

begin

state_next=idle;

rx_done_tick=1'b1;

end

else

s_next=s_reg+1;

endcase

end

//输出

assigndout=b_reg;

endmodule8.2.4接口电路

在FPGA系统设计中,UART经常作为串行通信的接口,主系统通过周期性检测接收和发送状态字与UART进行通信。接收模块接口电路有两个功能:①提供一种正确的数据传输机制,包括对单个数据或者数据包的正确传输,同时能够避免重复接收和漏接收;②对于包传输来说,接口模块电路提供了主系统和UART接收器之间的缓冲器。常用的接口方案有三种:

(1)采用状态寄存器;

(2)采用状态寄存器和单个数据缓冲器;

(3)采用FIFO缓冲器。

注意在程序8-1中,UART接收器在每次数据接收完之后置位rx_ready_tick信号,就是用来跟主系统进行握手用的。

1.方案一

第一种方案是采用一个状态寄存器来检测是否有新的有效数据到达,这个寄存器有两个输入信号,一个为置位标志:set_flag,用来置位寄存器。一个为清零标志:clr_flag,用来清零寄存器。状态标识信号rx_ready_tick信号与set_flag信号相连,如果新的有效数据到来将置位set_flag,而对于主系统来说,通过检测标识信号的输出来判断是否有新的有效数据来临。等接收到一个字节时,延时一个时钟周期之后clr_flag信号有效,如图8-4(a)所示为第一种方案的接口电路顶层原理图。

为了与外界电路进行通信,标识寄存器输出取反并产生最终rx_empty信号,表示没有新的有效数据。在本方案中,主系统直接从UART的移位寄存器接收到数据,并没有做任何的缓冲,那么很有可能在主系统还在传输旧的数据时(状态寄存器有效),UART系统开始一个新的传输,这时旧数据就会被新数据覆盖,而导致发生错误。

2.方案二

为了改善上述电路,采用第二种方案。在第一个方案的基础上增加一个字的缓冲器,如图8-4(b)所示。当信号rx_ready_tick有效时,接收数据存储到缓冲器,同时状态寄存器有效,接收器可以持续接收数据而不会影响已经接收到的旧的数据。这样,如果主系统能够在新数据到达之前处理接收数据,则不会有数据被覆盖,如程序8-2所示。

【程序8-2】带缓冲器的UART接口程序。

moduleflag_buf

#(parameterW=8) //缓冲区位宽

(

input

wireclk,reset,

input

wireclr_flag,set_flag,

input

wire[W-1:0]din,

output

wireflag,

output

wire[W-1:0]dout

);

//信号声明

reg[W-1:0]buf_reg,buf_next;

regflag_reg,flag_next;

//寄存器

always@(posedgeclk,posedgereset)

if(reset)

begin

buf_reg<=0;

flag_reg<=1'b0;

end

else

begin

buf_reg<=buf_next;

flag_reg<=flag_next;

end

//下一状态逻辑

always@*

begin

buf_next=buf_reg;

flag_next=flag_reg;

if(set_flag)

begin

buf_next=din;

flag_next=1'b1;

end

else

if(clr_flag)

flag_next=1'b0;

end

//输出逻辑

assigndout=buf_reg;

assignflag=flag_reg;

endmodule

3.方案三

第三种方案是采用FIFO缓冲器。采用FIFO缓冲器,为系统提供了更大的缓冲空间,从而进一步降低了数据溢出的几率。可以根据实际情况调节FIFO的深度来满足系统的需求,具体细节如图8-4(c)所示。

rx_ready_tick信号与FIFO的wr信号相连,当信号数据到达时,wr信号有效一个时钟周期,将数据写入FIFO中。主系统从FIFO的读端口获取数据,当接收到一个字时,主系统有效FIFO的rd信号一个时钟周期,然后立即清除rd信号,从而结束与FIFO的通信。

FIFO的空标志信号empty可以用来判断是否有效地接收到数据,而当FIFO的满标志有效时,如果有新的数据来临,则会发生数据溢出错误。 8.3UART发送模块设计

UART发送模块在结构上与接收模块很相似,也包含三个部分:发送器、波特率产生器和接口电路。接口电路部分与接收模块的接口电路相似,不同之处在于,接收模块中,由主系统设置FIFO标志寄存器和写FIFO缓冲器,而UART发送模块清标志寄存器并读FIFO缓冲器。

UART发送器本质上是一个移位寄存器,其功能是按照一定的波特率将移位寄存器中的数据一位一位地移出去,发送速率由波特率产生器产生。由于不存在过采样的问题,所以发送的时钟频率低于接收时钟频率的1/16。发送模块在时钟方面为了与接收模块一致和避免产生新的计数器,通常与接收模块共享同一个波特率产生器并使用一个内部计数器来追踪接收时钟脉冲,确保每16个时钟节拍移出一位数据。

UART发送模块的ASMD状态转移图与接收模块的相似。当接收到tx_start信号时,装载数据并按照UART协议依次发送开始位、数据、停止位到通信对方;当一次数据传输结束时,tx_done_tick状态标志信号置位,其中tx_reg信号为1位缓冲器,用来过滤潜在的毛刺,具体如程序8-3所示。

【程序8-3】UART发送模块。

moduleuart_tx

#(

parameterDBIT=8, //数据位宽

SB_TICK=16 //脉冲采样数

)

(

input

wireclk,reset,

input

wiretx_start,s_tick,

input

wire[7:0]din,

output

regtx_done_tick,

output

wiretx

);

//状态机状态定义

localparam[1:0]

idle=2'b00,

start  =2'b01,

data=2'b10,

stop=2'b11;

//信号声明

reg[1:0]state_reg,state_next;

reg[3:0]s_reg,s_next;

reg[2:0]n_reg,n_next;

reg[7:0]b_reg,b_next;

regtx_reg,tx_next;

//FSMD状态及数据寄存器

always@(posedgeclk,posedgereset)

if(reset)

begin

state_reg<=idle;

s_reg<=0;

n_reg<=0;

b_reg<=0;

tx_reg<=1'b1;

end

else

begin

state_reg<=state_next;

s_reg<=s_next;

n_reg<=n_next;

b_reg<=b_next;

tx_reg<=tx_next;

end

//FSMD下一状态逻辑及功能单元

always@*

begin

state_next=state_reg;

tx_done_tick=1'b0;

s_next=s_reg;

n_next=n_reg;

b_next=b_reg;

tx_next=tx_reg;

case(state_reg)

idle:

begin

tx_next=1'b1;

if(tx_start)

begin

state_next=start;

s_next=0;

b_next=din;

end

end

start:

begin

tx_next=1'b0;

if(s_tick)

if(s_reg==15)

begin

state_next=data;

s_next=0;

n_next=0;

end

else

s_next=s_reg+1;

end

data:

begin

tx_next=b_reg[0];

if(s_tick)

if(s_reg==15)

begin

s_next=0;

b_next=b_reg>>1;

if(n_reg==(DBIT-1))

state_next=stop;

else

n_next=n_reg+1;

end

else

s_next=s_reg+1;

end

stop:

begin

tx_next=1'b1;

if(s_tick)

if(s_reg==(SB_TICK-1))

begin

state_next=idle;

tx_done_tick=1'b1;

end

else

s_next=s_reg+1;

end

endcase

end

//输出逻辑

assigntx=tx_reg;

endmodule图8-5完整UART系统方案 8.4UART系统的总结

8.4.1完整UART系统

UART的接收和发送子模块结合起来,就可以建立完整的UART模块。顶层框图如8-5所示。详细程序如8-4所示。

【程序8-4】完整UART系统。

moduleuart

#(//默认设置

//19200波特率,8位数据位宽,1位停止位,22的FIFO

parameterDBIT=8, //数据位宽

SB_TICK=16,//根据停止位宽不同脉冲计数值不同,对应停止位为

//1/1.5/2,则脉冲计数值分别为16/24/32

DVSR=163, //波特率分频值DVSR=50M/(16 × 波特率)

DVSR_BIT=8, //DVSR的位宽

FIFO_W=2 //FIFO地址位宽

//FIFO容量为22地址

)

(

input

wireclk,reset,

input

wirerd_uart,wr_uart,rx,

input

wire[7:0]w_data,

output

wiretx_full,rx_empty,tx,

output

wire[7:0]r_data

);

//信号声明

wiretick,rx_done_tick,tx_done_tick;

wiretx_empty,tx_fifo_not_empty;

wire[7:0]tx_fifo_out,rx_data_out;

//程序主体部分

mod_m_counter#(.M(DVSR),.N(DVSR_BIT))baud_gen_unit

(.clk(clk),.reset(reset),.q(),.max_tick(tick));

uart_rx#(.DBIT(DBIT),.SB_TICK(SB_TICK))uart_rx_unit

(.clk(clk),.reset(reset),.rx(rx),.s_tick(tick),

.rx_done_tick(rx_done_tick),.dout(rx_data_out));

fifo#(.B(DBIT),.W(FIFO_W))fifo_rx_unit

(.clk(clk),.reset(reset),.rd(rd_uart),

.wr(rx_done_tick),.w_data(rx_data_out),

.empty(rx_empty),.full(),.r_data(r_data));

fifo#(.B(DBIT),.W(FIFO_W))fifo_tx_unit

(.clk(clk),.reset(reset),.rd(tx_done_tick),

.wr(wr_uart),.w_data(w_data),.empty(tx_empty),

.full(tx_full),.r_data(tx_fifo_out));

uart_tx#(.DBIT(DBIT),.SB_TICK(SB_TICK))uart_tx_unit

(.clk(clk),.reset(reset),.tx_start(tx_fifo_not_empty),

.s_tick(tick),.din(tx_fifo_out),

.tx_done_tick(tx_done_tick),.tx(tx));

assigntx_fifo_not_empty=~tx_empty;

endmodule8.4.2UART验证电路

在PC机上有超级终端,实际上就是在Windows操作系统下已经开发好的可以与串口进行通信的上位机软件。可以采用环路测试方法用PC机来验证UART电路发送和接收模块,其电路原理框图如8-6所示。测试时采用如下方案。

(1)硬件连接:FPGA验证板串口与PC连接好。

(2)功能方案:当PC发送一个字符时,FPGA接收模块将接收到的数据(通过r_data_port)保存在4words容量的FIFO当中;当重新接收新数据时,将接收的数据加1,然后发送到发送模块(w_data_port)。

(3)设置当按钮按下时产生一个时钟宽度的脉冲,并将rd_uart与wr_uart信号与按钮连在一起。这样一来,如果按钮被按下,将移除接收FIFO中一个字节数据,然后进行加1并写入到发送FIFO中。比如说,一开始在PC上发送三个字符“HAL”,三个字符存在接收模块的FIFO中,然后按下按钮三次,将有三个字符“IBM”发送出来并显示。

(4)为了显示直观,同时将rx_data端口与七段数码管相连,tx_full和rx-empty与开发板右端两个七段数码管的小数点位相连。图8-6UART验证电路原理图

【程序8-5】UART验证电路。

moduleuart_test

(

input

wireclk,reset,

input

wirerx,

input

wire[2:0]btn,

output

wiretx,

output

wire[3:0]an,

output

wire[7:0]sseg,led

);

//信号声明

wiretx_full,rx_empty,btn_tick;

wire[7:0]rec_data,rec_data1;

//例化uart模块

uartuart_unit

(.clk(clk),.reset(reset),.rd_uart(btn_tick),

.wr_uart(btn_tick),.rx(rx),.w_data(rec_data1),

.tx_full(tx_full),.rx_empty(rx_empty),

.r_data(rec_data),.tx(tx));

//例化防反弹电路

debouncebtn_db_unit

(.clk(clk),.reset(reset),.sw(btn[0]),

.db_level(),.db_tick(btn_tick));

//接收到的数据加1并返回到发送

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论