FPGA实 验 报 告
基于VHDL的串口通信实现设计
摘要
串口是计算机上一种非常通用设备通信的协议,其特点是通信线路简单,成本低,特别适用于远距离通信,因此有较为广泛的应用。为了深入了解串口,本课程设计基于VHDL语言,利用FPGA开发板实现了板间串口通信。在程序设计中,考虑到串口波特率、数据格式等参数,共采用了四个模块:分频模块(即波特率产生模块),接受模块,发送模块,显示模块。通过软件和开发板调试,实现了板和串口调试助手收发数据,软件改变波特率等参数,并在数码管显示的功能。
关键词:串口 VHDL FPGA 分频 接收 发送 显示
正文
1.研究背景知识
1.1串口简介
串行接口Serial Interface是指数据一位一位地顺序传送,其特点是通信线路简单,只要一对传输线就可以实现双向通信(可以直接利用电话线作为传输线),从而大大降低了成本,特别适用于远距离通信,但传送速度较慢。
串口通信的两种最基本的方式:同步串行通信方式和异步串行通信方式。
1.2串口通信参数
双方为了可以进行通信,必须要遵守一定的通信规则,这个共同的规则就是通信端口的初始化。通信端口的初始化有以下几项必须设置:
1.数据的传输速率
传输双方通过传输线的电压改变来交换数据,但传输线的电压改变的速度必须和接收端的接收速度保持一致,RS-232通常用于异步传输,即双方并没有一个可参考的同步时钟作为基准。由于没有一个参考时钟,双方所发送的高低电位到底代表几个位就不得而知了,要使得双方的数据读取正常,就要考虑到传输速率——波特率,其所代表的意义是每秒钟所能产生的最大电压状态改变率,或者说是每秒钟可以振荡的次数。
2.数据的发送单位
一般串行通信端口所发送的数据是字符类型的,若用来传输文件,则会使用二进制的数据类型。当使用字符类型时,通常使用ASCII码,ASCII码中8个位形成一个字符。以实际的RS-232传输来看,由于大多数应用只是发送文字码,因此只要7个位就可以将ASCII码的0-127号字符表达出来,所有的可见字符都在这个范围内,所以只要7个数据位就足够了。不同的情况下,会使用到不同的发送单位,但使用多少个位合成一个字节必须先行确定。
3.起始位及停止位
由于异步串行通信中并没有使用同步脉冲作为基准,故接收端完全不知道发送端何时将进行数据的发送,而当发送端准备要开始发送数据时,发送端会在所送出的字符前后分别加上高电位的起始位(逻辑0)及低电位的停止位(逻辑1),它们分别是所谓的起始位和停止位。当发送端要开始发送数据时,便将传输在线的电位由低电位提升至高电位,而当发送结束后,再将电位降至低电位。接收端会因起始位的触发(因电压由低电位升至高电位)而开始接收数据,并因停止位的通知(因电压维持在低电位)而确切数据的字符信号已经结束。
4.校验位的检查
为了预防错误的产生,因此使用校验位作为检查的机制;校验位是用来检查所发送数据正确性的一种核对码,其中又分成奇校验位和偶校验位两种方式,分别是检查字符码中I的数目是奇数或偶数。以偶校验位为例,A的ASCII码01100001 (二进制),其中1的数目是三个,因此校验位便是1,使1的数目保持偶数。
2.系统整体设计
2.1 系统框图
2.2原理图
2.3管脚介绍:
功能
| 管脚 | 输入/输出 | 功能 |
| RST | 输入 | 复位,初始化 |
| CLK | 输入 | 时钟 |
| RXD | 输入 | 串行收引脚 |
| SK_RP | 输入 | 高电平为接收数据 低电平为发送数据 |
| BAUD8X | 输出 | 波特率*8 |
| TXD | 输出 | 串行发引脚 |
| SEG_EN | 输出 | 数码管位选择 |
| SEG_DATA | 输出 | 数码管段选择 |
3.1分频模块
通过本模块要产生8×波特率的时钟,FPGA开发板时钟振荡频率为50MHZ,因此要产生9600*8的时钟,分频数为50M/9600/8=325*2,本程序以9600波特率为例,展开分频。其余波特率依例可以选择产生。
3.11流程图
3.12程序
PROCESS(clk,rst) --分频得到8倍波特率的时钟
BEGIN
SEG_EN<="11111110" ;
IF ( rst = '1') THEN
DIV_BUF <= '0';
div_REG<= "0000000000000000" ;
ELSIF(clk'EVENT AND clk='1')THEN
IF (div_reg = div_par - "0000000000000001") THEN--//FEN PIN SHU YI BAN QU FAN
DIV_BUF<= NOT DIV_BUF ; --产生时钟脉冲
DIV_REG<="0000000000000000" ;
ELSE
div_reg <= div_reg + "0000000000000001";
END IF;
BAUD8X<=DIV_BUF ;
END IF;
| END PROCESS; |
3.2接收模块
3.21流程图
在进入收发模块之前。在复位中进行初始化: 接收缓冲器RXD_BUF<="00000000";RXD_CNT<="0000"; 接收计数器 RXD_START<="000"; 接收前级接收器RXD_TXT <="00000000"; 接收数据采用移位设计,将数据传进缓冲器。 每八个时隙对RXD取样一次,存进RXD_TXT中,比较中间五次,若五位数据一致,则认为可以接受一位数据,送进RXD_BUF,共接受八位数据。等八个时隙(停止位),再进入接收初态 。
3.22程序
///////////////////////////////////////////
--//JIE SHOU
ELSIF (SK_RP='1')THEN
IF(RXD_CNT="0000")THEN
IF( RXD='0' )THEN--JIAN CE DAO XIA JIANG YAN WEI QI SHI WEI
RXD_CNT<=RXD_CNT+"0001";
END IF;
ELSIF(RXD_CNT >= "0001" AND RXD_CNT<="1001")THEN--//JIE SHOU BA WEI SHU JU
IF( RXD_START="111" )THEN--//BA GE SHI XI
RXD_START<="000";
RXD_CNT<=RXD_CNT+"0001";
IF (RXD_TXT(6 DOWNTO 1)="000000"OR RXD_TXT(6 DOWNTO 1 )="111111")THEN--//BA CI CAI YANG YI YANG SHI JIE SHOU YI WEI SHU JU;
RXD_BUF(6 DOWNTO 0 )<= RXD_BUF(7 DOWNTO 1); --//YI WEI
RXD_BUF(7)<=RXD_TXT(7);--//JIE SHOU DI YI WEI
ELSIF (RXD_CNT= "1010")THEN
RXD_START<="000";
RXD_CNT<="0000";--//SHU JU CHOU YANG BU YI YANG ,RUO JIE SHOU ZUI HOU YI WEI ,QING LING
ELSE
RXD_CNT<=RXD_CNT+"0001";
END IF;
ELSE
RXD_TXT(7)<=RXD;
RXD_TXT(6 DOWNTO 0) <= RXD_TXT(7 DOWNTO 1) ;--//CAI YANG BA CI,FANG JIN RXD_TXD SHU ZU ZHONG;
RXD_START<=RXD_START+"001";
END IF;
ELSE
IF(RXD_CNT= "1010") THEN --//JIE SHOU TING ZHI WEI
DATA_B<=RXD_BUF;--//TING ZHI WEI YOU XIAO ,JIANG SHU JU CUN RU DATA BUS;
IF( RXD_START="110")THEN
RXD_START<="000";
RXD_CNT<="0000";
RXD_BUF<="00000000";
ELSE
RXD_START<=RXD_START+"001";
END IF;
END IF;
END IF;
| END IF; |
3.31流程图
为实现收发保持同一时隙,每八个时隙发送一位数据,通过移位,把八位数据发送出去。
3.32程序
///////////////////
-- //FASONG //
ELSIF(DIV_BUF' EVENT AND DIV_BUF='1')THEN
IF (SK_RP='0')THEN
IF (TXD_CNT="0000")THEN --//QI SHI WEI
TXD<='0';
TXD_CNT<=TXD_CNT+"0001";
TXD_BUF<=DATA_B; --//FA SONG DE SHU SONG JIN FA SONG HUN CHONG QI
ELSIF (TXD_CNT >= "0001" AND TXD_CNT<="1000")THEN--FA SONG BA WEI SHU JU
IF( TXD_START="111")THEN
TXD_START<="000";
TXD_CNT<=TXD_CNT+"0001";
TXD<=TXD_BUF(0);--//DI YI WEI FA SONG
TXD_BUF(6 DOWNTO 0 )<= TXD_BUF(7 DOWNTO 1); --//YI WEI
ELSE
TXD_START<=TXD_START+"001";
END IF;
ELSE
IF(TXD_CNT= "1001") THEN--//FA TING ZHI WEI
IF( TXD_START="111")THEN
TXD_START<="000";
TXD<='1';
TXD_CNT<=TXD_CNT+"0001";
ELSE
TXD_START<=TXD_START+"001";
END IF;
ELSE
IF( TXD_START="110")THEN
IF(RST='0')THEN
TXD_START<="000";
TXD_CNT<="0000";
TXD_BUF<="00000000";
END IF;
ELSE
TXD_START<=TXD_START+"001";
END IF;
END IF;
| END IF; |
4.1 时序调试
分频:波特率*8
接收和显示
发送和显示
4.2硬件调试
管脚分配
实验结果:
与串口调试助手调试,在助手上发送一个字节,FPGA板上接收并在数码管上显示出来,若发送一串数据,则只显示最后一个字节。摁下复位键(RST),再摁下(SK_RP),将把一个字节发送给助手,并在助手窗口上方显示出来。
波特率改变可通过,在软件中左右移动预置分频数,或者直接重设。
5.总结
对于系统设计,先在整体上进行功能和原理设计,然后分模块进行具体设计,这样比较容易实现。
避免眼高手低。刚选题时,是确定要把校验位也设计出来的,当时没想到再后来四天的设计中遇到了种种细节问题,以至于才勉强实现了基本的串口通信。因此以后要注意谨慎严谨。
在没有进展的情况下,尤其是在设计接收模块时,更改多次,调试不出来,一度要崩溃的,最后硬着头皮坚持了下来,还好最后都调试成功了。透过这次课设,对于串口设计的思想以后可能会忘记,但是这段在很困难、很没进展的情况下没有放弃,并且次次逼着自己静下心来一遍遍读改程序,并最终顺利完成了设计的经历告诉我信念,坚持,信心,会帮助我们克服困难,走出困境,完成任务。
无论如何,这次课设学到了很多串口和VHDL语言的知识,也收获了经验与信心,感谢这次课设。下载本文