基于FPGA的串口通信设计.docx

上传人:b****2 文档编号:17207589 上传时间:2023-07-23 格式:DOCX 页数:17 大小:453.53KB
下载 相关 举报
基于FPGA的串口通信设计.docx_第1页
第1页 / 共17页
基于FPGA的串口通信设计.docx_第2页
第2页 / 共17页
基于FPGA的串口通信设计.docx_第3页
第3页 / 共17页
基于FPGA的串口通信设计.docx_第4页
第4页 / 共17页
基于FPGA的串口通信设计.docx_第5页
第5页 / 共17页
基于FPGA的串口通信设计.docx_第6页
第6页 / 共17页
基于FPGA的串口通信设计.docx_第7页
第7页 / 共17页
基于FPGA的串口通信设计.docx_第8页
第8页 / 共17页
基于FPGA的串口通信设计.docx_第9页
第9页 / 共17页
基于FPGA的串口通信设计.docx_第10页
第10页 / 共17页
基于FPGA的串口通信设计.docx_第11页
第11页 / 共17页
基于FPGA的串口通信设计.docx_第12页
第12页 / 共17页
基于FPGA的串口通信设计.docx_第13页
第13页 / 共17页
基于FPGA的串口通信设计.docx_第14页
第14页 / 共17页
基于FPGA的串口通信设计.docx_第15页
第15页 / 共17页
基于FPGA的串口通信设计.docx_第16页
第16页 / 共17页
基于FPGA的串口通信设计.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

基于FPGA的串口通信设计.docx

《基于FPGA的串口通信设计.docx》由会员分享,可在线阅读,更多相关《基于FPGA的串口通信设计.docx(17页珍藏版)》请在冰点文库上搜索。

基于FPGA的串口通信设计.docx

基于FPGA的串口通信设计

基于FPGA的UART设计与实现

0引言

通用异步收发器(UniversalAsynchronousReceiver/Transmitter,UART)可以和各种标准串行接口,如RS232和RS485等进行全双工异步通信,具有传输距离远、成本低、可靠性高等优点。

一般UART由专用芯片如8250,16450来实现,但专用芯片引脚都较多,内含许多辅助功能,在实际使用时往往只需要用到UART的基本功能,使用专用芯片会造成资源浪费和成本提高。

一般而言UART和外界通信只需要两条信号线RXD和TXD,其中RXD是UART的接收端,TXD是UART的发送端,接收与发送是全双工形式。

由于可编程逻辑器件技术的快速发展,FPGA的功能日益强大,其开发周期短、可重复编程的优点也越来越明显,在FPGA芯片上集成UART功能模块并和其他模块组合可以很方便地实现一个能与其他设备进行串行通信的片上系统。

FPGA(FieldProgrammableGateArray)现场可编程门阵列在数字电路的设计中已经被广泛使用。

这种设计方式可以将以前需要多块集成芯片的电路设计到一块大模块可编程逻辑器件中,大大减少了电路板的尺寸,增强了系统的可靠性和设计的灵活性。

1UART功能设计

1.1UART的工作原理

异步通信时,UART发送/接收数据的传输格式表1所示,一个字符单位由开始位、数据位、停止位组成。

表1UART发送/接收数据的传输格式

START

D0

D1

D2

D3

D4

D5

D6

D7

P

STOP

起始位

数据位

较验位

停止位

异步通信的一帧传输经历以下步骤:

(1)无传输。

发送方连续发送信号,处于信息“1”状态。

(2)起始传输。

发送方在任何时刻将传号变成空号,即“1”跳变到“O”,并持续1位时间表明发送方开始传输数据。

而同时,接收方收到空号后,开始与发送方同步,并期望收到随后的数据。

(3)奇偶传输。

数据传输之后是可供选择的奇偶位发送或接收。

(4)停止传输。

最后是发送或接收的停止位,其状态恒为“1”。

发送或接收一个完整的字节信息,首先是一个作为起始位的逻辑“0”位,接着是8个数据位,然后是停止位逻辑“1”位,数据线空闲时为高或“1”状态。

起始位和停止位的作用是使接收器能把局部时钟与每个新开始接收的字符再同步。

异步通信没有可参照的时钟信号,发送器可以随时发送数据,任何时刻串行数据到来时,接收器必须准确地发现起始位下降沿的出现时间,从而正确采样数据。

设计时可参考由专用芯片实现的UART的功能并进行一定精简,如可以用FPGA的片内RAM替代UART的FIFO,不用单独在UART模块中实现。

设计的基本原则是保留最主要的功能,基于FPGA的UART系统波特率时钟发生器、接收器和发送器3个子模块组成,如图1所示。

图1基于FPGA的UART组成模块

1.2接收器设计

接收器的工作过程如下,如图2所示,在接收数据寄存器被读出一帧数据或系统开始工作以后,接收进程被启动。

接收进程启动之后,检测起始位,检测到有效起始位后,以约定波特率的时钟开始接收数据,根据数据位数的约定,计数器统计接收位数。

一帧数据接收完毕之后,如果使用了奇偶校验,则检测校验位,如无误则接收停止位。

停止位接收完毕后,将接收数据转存到数据寄存器中。

图2数据接收图

为确保接收器可靠工作,在接收端开始接收数据位之前,处于搜索状态,这时接收端以16倍波特率的速率读取线路状态,检测线路上出现低电平的时刻。

因为异步传输的特点是以起始位为基准同步的。

然而,通信线上的噪音也极有可能使传号“1”跳变到空号“0”。

所以接收器以16倍的波特率对这种跳变进行检测,直至在连续8个接收时钟以后采样值仍然是低电平,才认为是一个真正的起始位,而不是噪音引起的,其中若有一次采样得到的为高电平则认为起始信号无效,返回初始状态重新等待起始信号的到来。

找到起始位以后,就开始接收数据,最可靠的接收应该是接收时钟的出现时刻正好对着数据位的中央。

由于在起始位检测时,已使时钟对准了位中央,用16倍波特率的时钟作为接收时钟,就是为了确保在位宽的中心时间对接收的位序列进行可靠采样,当采样计数器计数结束后所有数据位都已经输入完成。

最后对停止位的高电平进行检测,若正确检测到高电平,说明本帧的各位正确接收完毕,将数据转存到数据寄存器中,否则出错。

采用有限状态机模型可以更清晰明确地描述接收器的功能,便于代码实现。

接收器的状态转换图如图3所示,为突出主要过程,图中省略了奇偶校验的情况。

接收器状态机由5个工作状态组成,分别是空闲状态、起始位确认、采样数据位、停止位确认和数据正确,触发状态转换的事件和在各个状态执行的动作见图中的文字说明。

图3接收器状态转换图

根据状态图其主要的程序如下所示:

elseif(RX_En_Sig)

case(i)

4'd0:

if(H2L_Sig)begini<=i+1'b1;isCount<=1'b1;end

4'd1:

if(BPS_CLK)begini<=i+1'b1;end

4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8,4'd9:

if(BPS_CLK)begini<=i+1'b1;rData[i-2]<=RX_Pin_In;end

4'd10:

if(BPS_CLK)begini<=i+1'b1;end

4'd11:

if(BPS_CLK)begini<=i+1'b1;end

4'd12:

begini<=i+1'b1;isDone<=1'b1;isCount<=1'b0;end

4'd13:

begini<=4'd0;isDone<=1'b0;end

endcase

其中起始位检测正确会触发RX_En_Sig,一次的定时采集时第0、1位数据(起始位),保持忽略态度。

定时采集的是八位数据位,每一位数据位会依低位到最高位储存入rData寄存器。

此时程序前两位省略取2-9位就是传送的数据

1.3波特率发生器设计

波特率发生器实质是设计一个分频器,用于产生和RS232通信同步的时钟。

在系统中用一个计数器来完成这个功能,分频系数N决定了波特率的数值。

该计数器一般工作在一个频率较高的系统时钟下,当计数到N/2时将输出置为高电平,再计数到N/2的数值后将输出置为低电平,如此反复即可得到占空比50%的波特率时钟,具体的波特率依赖于所使用的系统时钟频率和N的大小。

如系统时钟频率是50MHz,要求波特率是9600,N=1/50MHz=5208,如果从零开始算起就是5207个计数。

然而,采集数据要求“在周期的中间”,那么结果是5208/2,结果等于2604。

基本上rx_bps_module.v只有在Count_Sig拉高的时候,模块才开始计数。

利用verlog所写的具体代码如下:

modulerx_bps_module

CLK,RSTn,

Count_Sig,

BPS_CLK

);

inputCLK;

inputRSTn;

inputCount_Sig;

outputBPS_CLK;

/***************************/

reg[12:

0]Count_BPS;

always@(posedgeCLKornegedgeRSTn)

if(!

RSTn)

Count_BPS<=13'd0;

elseif(Count_BPS==13'd5207)

Count_BPS<=13'd0;

elseif(Count_Sig)

Count_BPS<=Count_BPS+1'b1;

else

Count_BPS<=13'd0;

/********************************/

assignBPS_CLK=(Count_BPS==12'd2604)?

1'b1:

1'b0;

/*********************************/

endmodule

1.4发送器设计

图4发送数据原理图

当发送数据时,对于每一个数据的发送,每一位采用的是定时发送。

假设,配置的波特率是9600bps,那么当有一个发送标志位时,数据将会以1/9600的节拍将数据一位一位的发送出去。

一帧数据有11位,需要12次定时。

主要代码为:

always@(posedgeCLKornegedgeRSTn)

if(!

RSTn)

begin

i<=4'd0;

rTX<=1'b1;

isDone<=1'b0;

end

elseif(TX_En_Sig)

case(i)

4'd0:

if(BPS_CLK)begini<=i+1'b1;rTX<=1'b0;end

4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8:

if(BPS_CLK)begini<=i+1'b1;rTX<=TX_Data[i-1];end

4'd9:

if(BPS_CLK)begini<=i+1'b1;rTX<=1'b1;end

4'd10:

if(BPS_CLK)begini<=i+1'b1;rTX<=1'b1;end

4'd11:

if(BPS_CLK)begini<=i+1'b1;isDone<=1'b1;end

4'd12:

begini<=4'd0;isDone<=1'b0;end

endcase

2数据传输仿真

Modelsim仿真工具是Model公司开发的。

它支持Verilog、VHDL以及他们的混合仿真,它可以将整个程序分步执行,使设计者直接看到他的程序下一步要执行的语句,而且在程序执行的任何步骤任何时刻都可以查看任意变量的当前值,可以在Dataflow窗口查看某一单元或模块的输入输出的连续变化等,比quartus自带的仿真器功能强大的多,是目前业界最通用的仿真器之一。

2.1仿真串口发送模块

编写一个仿真激励程序用于单独仿真串口发送模块。

步骤0的时候,将数据8'h2E发送至串口发送模块后使能串口发送模块,然后等待串口发送模块反馈完成信号。

同样的动作也有...步骤1是发送数据8'h3f,然而步骤2是发送数据8'hdd。

步骤3是停止动作

图5发送数据仿真

放大第二个数据0x3f的发送过程,如下图所示。

可以看出串口发送模块,发送数据的格式是一帧11位。

[0]开始位-逻辑0,[1:

8]数据位,[9]校验位没有需要可以随便填,这里填逻辑1,[10]停止位逻辑1。

图6发送过程仿真结果

图7发送数据的延时仿真

串口发送模块配置的波特率是9600kbps,所以一个数据逗留的时间是大约104us。

在仿真结果中,在B0~B1是数据[0],B1~B2是数据[1]......B10~B11是数据[10]。

Bx~Bx之间的时间大约是104us。

2.2仿真串口接收模块

用串口发送模块作为串口接收模块的刺激,亦即串口接收模块的输入(复杂输入)。

用串口发送模块作为串口接收模块的刺激,亦即串口接收模块的输入(复杂输入)。

下图是仿真虚拟环境env_rx_module.v它组合了串口发送模块和串口接收模块。

env_rx_module.v拥有TX_En_Sig,TX_Data,TX_Done_Sig,RX_En_Sig,RX_Done_Sig,RX_Data等信号。

在激励的过程中,需要对这些信号控制。

图8接收模块仿真建模图

当RX_En_Sig拉高的时候,串口接收模块开始准备接收数据了。

当一帧11位数据发送

至串口接收模块,并且被串口接收模块过滤。

最后经过过滤的数据会输出至RX_Data,

然后产生一个完成信号至RX_Done_Sig。

(在这里数据格式四1帧11位,并且波特率为9600kbps。

仿真结果如下图所示:

图10发送结果仿真图

上图仿真结果显示了“串口发送模块作为串口接收模块的刺激”的激励过程。

(Cursor省略为C)在C1~C2之间是第一帧数据的传送,C2~C3是第二位数据的传送,其他的以此类推,然和C1~C12是一帧数据11位的传送过程。

注意,每个Cx~Cx之间的时间大约是104us,亦即9600kbps的波特率

3结语

本设计是基于FPGA的UART设计,用时较少,逻辑消耗小,成熟稳定的实现了数据的发送与接收,可以兼容到自己的程序中。

本设计的仿真程序实现了激励的所有功能,完成初步设计要求。

附录1:

发送模块

moduletx_control_module

CLK,RSTn,

TX_En_Sig,TX_Data,BPS_CLK,

TX_Done_Sig,TX_Pin_Out

);

inputCLK;

inputRSTn;

inputTX_En_Sig;

input[7:

0]TX_Data;

inputBPS_CLK;

outputTX_Done_Sig;

outputTX_Pin_Out;

/********************************************************/

reg[3:

0]i;

regrTX;

regisDone;

always@(posedgeCLKornegedgeRSTn)

if(!

RSTn)

begin

i<=4'd0;

rTX<=1'b1;

isDone<=1'b0;

end

elseif(TX_En_Sig)

case(i)

4'd0:

if(BPS_CLK)begini<=i+1'b1;rTX<=1'b0;end

4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8:

if(BPS_CLK)begini<=i+1'b1;rTX<=TX_Data[i-1];end

4'd9:

if(BPS_CLK)begini<=i+1'b1;rTX<=1'b1;end

4'd10:

if(BPS_CLK)begini<=i+1'b1;rTX<=1'b1;end

4'd11:

if(BPS_CLK)begini<=i+1'b1;isDone<=1'b1;end

4'd12:

begini<=4'd0;isDone<=1'b0;end

endcase

/********************************************************/

assignTX_Pin_Out=rTX;

assignTX_Done_Sig=isDone;

/*********************************************************/

Endmodule

 

附录2:

接收模块:

modulerx_control_module

CLK,RSTn,

H2L_Sig,RX_Pin_In,BPS_CLK,RX_En_Sig,

Count_Sig,RX_Data,RX_Done_Sig

);

inputCLK;

inputRSTn;

inputH2L_Sig;

inputRX_En_Sig;

inputRX_Pin_In;

inputBPS_CLK;

outputCount_Sig;

output[7:

0]RX_Data;

outputRX_Done_Sig;

/********************************************************/

reg[3:

0]i;

reg[7:

0]rData;

regisCount;

regisDone;

always@(posedgeCLKornegedgeRSTn)

if(!

RSTn)

begin

i<=4'd0;

rData<=8'd0;

isCount<=1'b0;

isDone<=1'b0;

end

elseif(RX_En_Sig)

case(i)

4'd0:

if(H2L_Sig)begini<=i+1'b1;isCount<=1'b1;end

4'd1:

if(BPS_CLK)begini<=i+1'b1;end

4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8,4'd9:

if(BPS_CLK)begini<=i+1'b1;rData[i-2]<=RX_Pin_In;end

4'd10:

if(BPS_CLK)begini<=i+1'b1;end

4'd11:

if(BPS_CLK)begini<=i+1'b1;end

4'd12:

begini<=i+1'b1;isDone<=1'b1;isCount<=1'b0;end

4'd13:

begini<=4'd0;isDone<=1'b0;end

endcase

/********************************************************/

assignCount_Sig=isCount;

assignRX_Data=rData;

assignRX_Done_Sig=isDone;

/*********************************************************/

endmodule

 

附录3:

波特率发生器

modulerx_bps_module

CLK,RSTn,

Count_Sig,

BPS_CLK

);

inputCLK;

inputRSTn;

inputCount_Sig;

outputBPS_CLK;

/***************************/

reg[12:

0]Count_BPS;

always@(posedgeCLKornegedgeRSTn)

if(!

RSTn)

Count_BPS<=13'd0;

elseif(Count_BPS==13'd5207)

Count_BPS<=13'd0;

elseif(Count_Sig)

Count_BPS<=Count_BPS+1'b1;

else

Count_BPS<=13'd0;

/********************************/

assignBPS_CLK=(Count_BPS==12'd2604)?

1'b1:

1'b0;

/*********************************/

endmodule

 

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 经管营销 > 经济市场

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2