基于FPGA的RS232设计.docx
《基于FPGA的RS232设计.docx》由会员分享,可在线阅读,更多相关《基于FPGA的RS232设计.docx(19页珍藏版)》请在冰点文库上搜索。
基于FPGA的RS232设计
课程设计(论文)说明书
题目:
基于FPGA的RS232串口通信
院(系):
信息与通信学院
专业:
微电子学
学生姓名:
学号:
指导教师:
职称:
副教授
2012年12月10日
摘要
实验设计了基于verilog描述的RS232串口通信控制器,通过串口调试工具实现PC机和FPGA互发和接收数据。
完成的功能包括实现收发一帧10个bit、波特率为9600的串口通信控制器,FPGA接收数据后显示在串口助手的接收数据栏里。
实验的重心放在了RS232串口通信控制器发送模块和接收模块的设计,采用了自顶向下的思路进行设计。
报告中给出了完整的设计思路和过程,并将系统分模块进行了详细的设计,给出了verilog语言描述。
完成了各个模块以及系统整体的仿真验证。
最终下载到实验板上测试通过。
关键词:
RS232;verilog;串口通信;发送;接收;分频
Abstract
ExperimentdesignbasedonthedescriptionoftheVerilogRS232serialcommunicationcontroller,throughtheserialportdebuggingtoolstoachievePCmachineandFPGAsendingandreceivingdata.Completefunctionincludestransmittingaframeof10bit,baudrateto9600serialcommunicationcontroller,FPGAreceivesthedatadisplayedinaserialassistantstoreceivedatacolumn.
Keywords:
RS232;verilog;Serialcommunication;transmission;receive;frequencydivision
引言
引言
数据采集系统常需要进行异步串行数据传输。
目前广泛使用的RS232异步串行接口,如8250、NS16450等专用集成器件,虽然使用简单,却占用电路板面积、布线复杂等缺点。
片上系统SoC(SystemonChip)是以嵌入式系统为核心,以IP复用技术为基础,集软、硬件于一体的设计方法。
使用IP复用技术,将UART集成到FPGA器件上,可增加系统的可靠性,缩小PCB板面积;其次由于IP核的特点,使用IP核可使整个系统更加灵活,还可根据需要实现功能升级、扩充和裁减。
这里采用VHDL语言编写UART模块,将其集成到FPGA上,与器件其他功能模块构成片上系统SoC。
第一部分任务要求
1.1课题要求
设计并实现一个可以和PC机通过RS232协议进行通信的串口通信控制器。
1.PC机通过串口调试工具来验证程序的功能;
2.实现一个收发一帧10个bit的串口控制器,10个bit是1位起始位,8位数据位,1位结束位,无奇偶校验位;
3.串口的波特率选择9600bit,串口处于全双工工作状态;
4.PC机可随时向FPGA发送0~F的十六进制数据;
1.2设计目标
根据课题要求,实验中将目标进行了细化,叙述如下:
1.设定数据帧格式为10bit,其中第一位为起始位,定位低电平,8位数据位,1位结束位,无数据传输时为高电平;
2.通过串口调试工具向FPGA发送数据,FPGA接收后显示串口调试工具的接收数据窗口;
第二部分系统设计
2.1系统结构设计
2.1.1系统结构框图
图2.1RS232串口通信控制器系统结构框图
串口通信控制器的输入是PC发送的数据。
当发送数据按键按下时,FPGA向PC发送已定义好的数据。
同时,当FPGA检测到PC发送数据帧的起始位时,开始接收数据,并行输出。
2.1.2系统逻辑功能划分
图2.2RS232串口通信控制器系统逻辑框图
如图2.2所示,系统可逻辑地划分为三个子系统:
一是分频子系统,包括为发送模块和接收模块提供波特率为9600bit的时钟;二是发送子系统,包括发送模块;三是接收子系统,包括接收模块和串口助手显示模块。
2.1.3层次模块划分
系统划分为两层,自顶向下分别是顶层模块、控制器子模块。
顶层描述了整个系统的功能和运行;控制器子模块实现系统中各个独立而完整的功能部分,每个层次可用一个或多个具体模块加以实现。
A.顶层模块:
作用为集成子模块功能,控制子模块的连接和耦合信号。
定义名称为uart1,在其中例化子模块。
B.中层模块:
具体实现顶层模块的描述,包括的功能主要是产生时钟信号,发送模块和接收模块的定义和状态的转移:
speed_select时钟分频模块,将50MHz的时钟分频为9600×1Hz的时钟。
定义波特率为9600bit,波特因子为1。
输入:
50MHz晶振信号。
输出:
送往接收模块和发送模块的9600×11Hz的信号。
a)my_uart_rx
接收模块,检测接收端,若检测到低电平则开始接收数据,每隔1个周期接收一位数据,直到接满8bit。
输入:
9600×1Hz时钟信号、PC机发送的串行数据。
输出:
PC机发送的串行数据并行输出。
b)my_uart_tx
发送模块。
当发送数据按键确定有效时向PC发送自定义的数据。
输入:
9600×1Hz时钟信号、发送数据按键。
输出:
字符串的串行输出。
以上模块分别定义在一个工程内,最后在顶层模块中用语言进行连接。
2.1.4模块设计图
发送模块设计
发送模块工作时首先检测发送数据下降沿到来,如复位信号有效时,控制器处于复位状态,一旦检测到复位信号无效并且检测到下降沿的到来则进入起始状态。
从PC接收到的数据帧:
1位起始位+8位数据位+1()位停止位(无奇偶校验),检测到电脑端的起始位后(rs232_rx下降沿)打开波特率发生器,到起始电平时间的中点时检测数据,每隔“一个”电平时间,采集一次并存入接收暂存寄存器,待到1(或)个结束位到来后将接收暂存寄存器数据放入接收寄存器并关闭波特率发生器,清楚数据检测使能标志。
接收模块设计
与发送模块类似,接收模块分为检验下降沿到来、启动接收数据使能有效、接收数据处理等模块。
没有检测到起始位时程序一直处于开始状态,一旦检测到低电平的起始位(neg_rs232_rx=1),则进入找中状态。
定时计数器cnt=0时则进入等待状态,当定时计数器cnt=1时对数据进行采样,直到移位计数器rx_temp_data[0]<=rs232_rx;,即8bit数据采样完毕,此时进入停止状态,重新返回开始状态。
检测到由接收模块使能位的下降沿后开启波特率发生器并使能发送,隔半个电平时间后开始发送数据帧每隔“一个”电平时间更新要发的数据位,发送一位结束位后停止工作
2.1.7分频模块设计
串行异步通信的关键在于准确地检测到起始位,因此接收端的时钟必须采用比波特率更高的时钟信号,以便提高采样的分辨率和抗干扰能力,从而更准确地判定起始位。
本实验中波特率为9600bit,取波特率因子为1。
接收端检测到传输线上电平由高到低的变化后便开始对接收时钟进行计数,当计到8个时钟以后,再次对传输线进行采样,如果仍为低电平,则确认是起始位,而不是干扰信号,之后每隔16个时钟进行一次采样,直到采样到停止位。
而且由于每一次采样都是在码元的中心进行的,这样还可以最大限度地避免收、发时钟偏差对数据传送造成的影响。
2.2系统硬件语言描述
2.2.1verilog描述思路
第二部分“系统设计”中对系统的功能和逻辑结构、状态转移以及模块划分都有了详细的叙述,模块间的耦合和信号的传递关系已经清晰。
可以使用verilog语言描述硬件电路了。
发送模块和接收模块的verilog语言描述按照事先设计好的状态转移进行编写可以使电路思想明晰化,避免编程过程中用软件的思维去描述硬件的电路系统,也可有效避免系统性的错误。
由于进行了细致的模块划分,模块的间的耦合程度降到了很低,这就使得电路设计的可靠性大为增强,只要模块的输出满足了功能定义,整个系统就能正常工作,即便个别模块出现问题,也不会过多影响到其他模块。
实际测试过程中也印证了这一点。
2.2.2总体电路的描述
顶层符号文件描述如下:
图2.8顶层符号文件
2.2.3分块电路的verilog描述
本节给出分块电路的硬件描述,对关键部分进行了分析。
1、发送模块的描述
`timescale1ns/1ps
modulemy_uart_tx(clk,rst_n,
rx_data,rx_int,rs232_tx,
clk_bps,bps_start,led1
);
inputclk;//50MHz主时钟
inputrst_n;//低电平复位信号
inputclk_bps;//clk_bps_r高电平为接收数据位的中间采样点,同时也作为发送数据改变点
input[7:
0]rx_data;//接收数据寄存器
inputrx_int;//接收数据中断信号,接收到数据期间始终为高电平,在该模块中利用它的下降沿来启动串口发送数据
outputrs232_tx;//RS232发送数据信号
outputbps_start;//接收或者要发送数据,波特率时钟启动信号置位
outputled1;
regrx_int0,rx_int1,rx_int2;//rx_int信号寄存器,捕捉下降沿滤波用
wireneg_rx_int;//rx_int下降沿标志位
always@(posedgeclkornegedgerst_n)begin
if(!
rst_n)begin
rx_int0<=1'b0;
rx_int1<=1'b0;
rx_int2<=1'b0;
end
elsebegin
rx_int0<=rx_int;
rx_int1<=rx_int0;
rx_int2<=rx_int1;
end
End
assignneg_rx_int=~rx_int1&rx_int2;//捕捉到下降沿后,neg_rx_int拉高保持一个主时钟周期
reg[7:
0]tx_data;//待发送数据的寄存器
regbps_start_r;
regtx_en;//发送数据使能信号,高有效
reg[3:
0]num;
always@(posedgeclkornegedgerst_n)begin
if(!
rst_n)begin
bps_start_r<=1'bz;
tx_en<=1'b0;
tx_data<=8'd0;
end
elseif(neg_rx_int)begin//接收数据完毕,准备把接收到的数据发回去
bps_start_r<=1'b1;
tx_data<=rx_data;//把接收到的数据存入发送数据寄存器
tx_en<=1'b1;//进入发送数据状态中
end
elseif(num==4'd11)begin//数据发送完成,复位
bps_start_r<=1'b0;
tx_en<=1'b0;
end
end
assignbps_start=bps_start_r;
regrs232_tx_r;
regled1_r;
always@(posedgeclkornegedgerst_n)begin
if(!
rst_n)begin
num<=4'd0;
rs232_tx_r<=1'b1;
led1_r<=1'b0;
end
elseif(tx_en)begin
if(clk_bps)begin
led1_r<=1'b1;
case(num)
4'd0:
rs232_tx_r<=1'b0;//发送起始位
4'd1:
rs232_tx_r<=tx_data[0];//发送bit0
4'd2:
rs232_tx_r<=tx_data[1];//发送bit1
4'd3:
rs232_tx_r<=tx_data[2];//发送bit2
4'd4:
rs232_tx_r<=tx_data[3];//发送bit3
4'd5:
rs232_tx_r<=tx_data[4];//发送bit4
4'd6:
rs232_tx_r<=tx_data[5];//发送bit5
4'd7:
rs232_tx_r<=tx_data[6];//发送bit6
4'd8:
rs232_tx_r<=tx_data[7];//发送bit7
4'd9:
rs232_tx_r<=1'b1;//发送结束位
default:
rs232_tx_r<=1'b1;
endcase
num<=num+1'b1;
end
elseif(num==4'd11)
begin
num<=4'd0;//复位
led1_r<=1'b0;
end
end
end
assignrs232_tx=rs232_tx_r;
assignled1=led1_r;
endmodule
2、接收模块的描述
`timescale1ns/1ps
modulemy_uart_rx(clk,rst_n,
rs232_rx,rx_data,rx_int,
clk_bps,bps_start,led0);
inputclk;//50MHz主时钟
inputrst_n;//低电平复位信号
inputrs232_rx;//RS232接收数据信号
inputclk_bps;//clk_bps的高电平为接收或者发送数据位的中间采样点
outputbps_start;//接收到数据后,波特率时钟启动信号置位
output[7:
0]rx_data;//接收数据寄存器,保存直至下一个数据来到
outputrx_int;//接收数据中断信号,接收到数据期间始终为高电平
outputled0;
regrs232_rx0,rs232_rx1,rs232_rx2,rs232_rx3;//接收数据寄存器,滤波用
wireneg_rs232_rx;//表示数据线接收到下降沿
always@(posedgeclkornegedgerst_n)begin
if(!
rst_n)begin
rs232_rx0<=1'b0;
rs232_rx1<=1'b0;
rs232_rx2<=1'b0;
rs232_rx3<=1'b0;
end
elsebegin
rs232_rx0<=rs232_rx;
rs232_rx1<=rs232_rx0;
rs232_rx2<=rs232_rx1;
rs232_rx3<=rs232_rx2;
end
end
assignneg_rs232_rx=rs232_rx3&rs232_rx2&~rs232_rx1&~rs232_rx0;//接收到下降沿后neg_rs232_rx置高一个时钟周期
regbps_start_r;
reg[3:
0]num;//移位次数
regrx_int;//接收数据中断信号,接收到数据期间始终为高电平
always@(posedgeclkornegedgerst_n)
if(!
rst_n)begin
bps_start_r<=1'bz;
rx_int<=1'b0;
end
elseif(neg_rs232_rx)begin//接收到串口接收线rs232_rx的下降沿标志信号
bps_start_r<=1'b1;//启动串口准备数据接收
rx_int<=1'b1;//接收数据中断信号使能
end
elseif(num==4'd12)begin//接收完有用数据信息
bps_start_r<=1'b0;//数据接收完毕,释放波特率启动信号
rx_int<=1'b0;//接收数据中断信号关闭
end
assignbps_start=bps_start_r;
reg[7:
0]rx_data_r;//串口接收数据寄存器,保存直至下一个数据来到
regled0_r;
reg[7:
0]rx_temp_data;//当前接收数据寄存器
always@(posedgeclkornegedgerst_n)
if(!
rst_n)begin
rx_temp_data<=8'd0;
num<=4'd0;
rx_data_r<=8'd0;
led0_r<=1'b0;
end
elseif(rx_int)begin//接收数据处理
led0_r<=1'b1;
if(clk_bps)begin//读取并保存数据,接收数据为一个起始位,8bit数据,1或2个结束位
case(num)
4'd1:
rx_temp_data[0]<=rs232_rx;//锁存第0bit
4'd2:
rx_temp_data[1]<=rs232_rx;//锁存第1bit
4'd3:
rx_temp_data[2]<=rs232_rx;//锁存第2bit
4'd4:
rx_temp_data[3]<=rs232_rx;//锁存第3bit
4'd5:
rx_temp_data[4]<=rs232_rx;//锁存第4bit
4'd6:
rx_temp_data[5]<=rs232_rx;//锁存第5bit
4'd7:
rx_temp_data[6]<=rs232_rx;//锁存第6bit
4'd8:
rx_temp_data[7]<=rs232_rx;//锁存第7bit
default:
;
endcase
num<=num+1'b1;
end
elseif(num==4'd12)begin//我们的标准接收模式下只有1+8+1
(2)=11bit的有效数据
num<=4'd0;//接收到STOP位后结束,num清零
rx_data_r<=rx_temp_data;//把数据锁存到数据寄存器rx_data中
led0_r<=1'b0;
end
end
assignrx_data=rx_data_r;
assignled0=led0_r;
endmodule
3、分频模块的描述
modulespeed_select(clk,rst_n,
bps_start,clk_bps);
inputclk;////50MHz主时钟
inputrst_n;//低电平复位信号
inputbps_start;////接收到数据后,波特率时钟启动信号置位
outputclk_bps;//clk_bps的高电平为接收或者发送数据位的中间采样点
`defineBPS_PARA5207//波特率9600分频点数
`defineBPS_PARA_22603
reg[12:
0]cnt;
regclk_bps_r;
reg[2:
0]uart_ctrl;//uart?
?
?
?
?
?
?
?
always@(posedgeclkornegedgerst_n)
begin
if(!
rst_n)cnt<=13'd0;
elseif((cnt==`BPS_PARA)||!
bps_start)cnt<=13'd0;//clear
elsecnt<=cnt+1'b1;end
always@(posedgeclkornegedgerst_n)
begin
if(!
rst_n)clk_bps_r<=1'b0;
elseif(cnt==`BPS_PARA_2)clk_bps_r<=1'b1;
elseclk_bps_r<=1'b0;
end
assignclk_bps=clk_bps_r;
endmodule
2.3系统仿真验证
系统仿真分为两个步骤进行,首先是关键模块的仿真,验证子系统功能的正确性,然后是综合仿真,验证整个系统的功能。
仿真环境是QuartusII7.2。
首先是分频模块的仿真。
由仿真结果可看出bclk的时钟周期为104us,与要求结果一致,频率为9600Hz。
图2.9分频模块仿真图(9600Hz分频)
然后是发送模块的仿真波形。
下图为发送模块第一个字符发送的波形,第一个字符的数值为“01100110”,发送时低位先发送,因此仿真波形由时间的先后顺序,其序列应为“01100110”,每一帧数据为10个bit,第一个bit为起始位,最后一个bit为停止位,可以看出,中间的八位为“01100110”,说明了仿真波形的正确性。
图2.10发送模块仿真图
下图为接收模块仿真图。
设定的输入信号为“10010110”。
接收时将先接收到的数据作为低位,后接收到的数据作为高位,因此转化成的并行数据应为“01101001”,因此仿真波形正确。
图2.11接收模块仿真图
第三部分结果与分析
3.1实现功能说明
本实验完成的RS232串口通信控制器,完成了课题要求的所有功能。
由于顶层设计采用了子系统分模块描述的方法,使得控制器具有很好的扩展性。
可以在不改变系统框架和模块间电路连接关系,增加其他模块,实现其他功能。
本课题中并没有在数据帧中加入校验位,仅仅实现了1位起始位,1位停止位和8位数据位的传输。
初步实现了PC和FPGA之间的通信。
数字系统的设计,真正的重点在于把系统层面的设计做好,把系统状态机设计完整,系统架构清晰,层次明确,稳定性好,可扩展和可移植性好,这样的系统给到用户,只要添加用户模块或者稍作修改即可完成非特定的功能。
3.2器件资源分析
在设计阶段,对系统描述采用过多种方式,尝试了多种描述,代码的长度在增加,模块在增多,但系统稳定性和可扩展性也在增强,层次结构和模块设计也更加完善。
设计之初对资源使用没有多少概念,时常以软件的思想描述硬件,在描述中使用乘法等资源耗费严重的操作,也曾使用过嵌套多层的IF-ELSE语句,产生很长的选择器,降低了模块的可靠性,增加处理延时。
随着设计的深入,加上反复求精的过程磨练,逐步对硬件描述综合出的实际电路形式有了更多的理解,对延