VHDL串口通信.docx
- 文档编号:5547028
- 上传时间:2022-12-19
- 格式:DOCX
- 页数:17
- 大小:103.79KB
VHDL串口通信.docx
《VHDL串口通信.docx》由会员分享,可在线阅读,更多相关《VHDL串口通信.docx(17页珍藏版)》请在冰豆网上搜索。
VHDL串口通信
4.UART模块设计
UART异步通信串口协议的VHDL实现包括3个基本模块:
时钟分频、接收模块和发送模块,下面逐一介绍其实现方法。
4.2.1时钟分频模块
由于UART是异步传输,没有传输同步时钟。
为了能保证数据传输的正确性,UART采用16倍数据波特率的时钟进行采样。
每个数据有16个时钟采样,取中间的采样值,以保证采样不会滑码或误码。
一般UART一帧的数据位数为8,这样即使每个数据有一个时钟的误差,接收端也能正确地采样到数据。
这里采用常用的数据波特率为9600bps,则所需时钟的频率为16*9600。
系统时钟为50MHz,则分频系数为50000000/(16*9600)=325.52,取整为325。
分频器实现相对简单,这里对其设计流程图不做详细介绍。
只是将设计过程和结果简述如下:
首先用VHDL语言进行设计输入,并生成模块文件如图4.3所示,其中clk为50M系统时钟输入,clkout为325分频后时钟输出。
图4.3分频模块
然后建立波形文件,对以上模块进行时序仿真,仿真结果如图4.4所示,方正结果说明,分频输出实现了对输入的325分频,分频模块设计正确。
图4.4分频模块仿真结果
4.2.2UART发送模块
发送过程:
空闲状态,线路处于高电平;当受到发送数据指令后,拉低线路一个数据位的时间T,接着数据按地位到高位依次发送,数据发送完毕后,接着发送停止位(停止位为高电平),一帧数据发送结束。
(1)模块流程图
根据以上发送过程,发送模块算法示意图设计如图4.5所示。
图4.5UART发送数据算法示意图
(2)生成模块文件
新建一原理图文件,将VHDL源文件生成对应的模块文件如图4.6所示,其中clk为时钟输入,datain为需要发送的数据输入,wrsig为发送命令输入,idle为忙闲信号输出,tx为串行数据输出端。
图4.6UART发送模块
(3)波形仿真
要对发送模块进行时序仿真必须设计一测试模块,即在每一个clk来时产生一个八位的数据。
测试模块代码如下:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitytestuartis
port(clk:
instd_logic;
dataout:
outstd_logic_vector(7downto0);
wrsig:
outstd_logic
);
endtestuart;
architectureoneoftestuartis
signaldataoutreg:
std_logic_vector(7downto0);
signalcnt:
std_logic_vector(7downto0);
begin
dataout<=dataoutreg;
process(clk)
begin
if(clk'eventandclk='1')then
if(cnt="11111110")then
dataoutreg<=dataoutreg+"00000001";
wrsig<='1';
cnt<="00000000";
else
wrsig<='0';
cnt<=cnt+"00000001";
endif;
endif;
endprocess;
endone;
保存文件为testuart.hdl,单击Files→Create/Update→CreateSymbolFilesforCurrentFile命令,为testuart.hdl生成原理图模块。
新建一个原理图文件,各个模块的连接如图4.7所示。
在原理图的适当位置放置testuart模块和uarttx模块,并添加输入输出端口。
图4.7UART发送模块仿真原理图
保存原理图为uarttxts.bdf。
编译工程文件,编译无误后新建波形仿真文件,加入输入输出信号,设置系统时钟信号clk的周期为20ns,保存波形文件为uarttxts.vwf,进行UART数据发送的波形仿真,波形仿真报告如图4.8所示
图4.8UART发送模块仿真结果
对上图分析看出,当发送命令wrsig的上升沿有效时,启动发送数据。
串行数据的波形与发送数据dataout相一致,UART的发送模块得到正确验证。
4.2.3UART接收模块
UART接收模块的功能:
时时检测线路,当线路产生下降沿时,即认为线路有数据传输,启动接收数据进程进行接收,按从低位到高位接收数据。
(1)模块流程图
根据以上描述的接收模块的功能,可将接收模块算法示意图设计如图4.9所示。
图4.9接收模块算法示意图
(2)生成模块文件
新建一原理图文件,将VHDL源文件生成对应的模块文件如图4.10所示,其中clk为时钟输入,rx为需要串行数据输入,dataout为并行输出,rdsig为忙闲信号输出。
图4.10UART接收模块
(3)波形仿真
新建一个原理图文件,加入各功能模块,并添加输入输出端口,各个模块的连接如图4.11所示。
图4.11UART接收模块仿真原理图
保存原理图为uartrxts.bdf。
编译工程文件,编译无误后新建波形仿真文件,加入输入输出信号,设置系统时钟clk为50MHz,保存为uartrxts.vwf,进行UART数据接收的波形仿真,波形仿真报告如图4.12所示。
图4.12UART接收模块仿真结果
对上图分析看出,UART接收模块接收到的数据与UART发送模块发送的数据相一至,每接收到一个数据都有一个读取数据指示rdisg,UART接收模块得到正确验证。
4.2.3硬件测试
按照下图连接个模块,在PC机上安装一个串口调试工具,通过串口调试工具向FPGA发送一个数据,看在PC机上能否接受到发送的数据。
测试结果如下
附录:
程序代码
UART分频模块代码:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entityclkdivis
port(
clk:
instd_logic;
clkout:
outstd_logic
);
endclkdiv;
architectureoneofclkdivis
signalcnt:
std_logic_vector(15downto0);
begin
process(clk)
begin
if(clk'eventandclk='1')then
if(cnt="00010")then
clkout<='1';
cnt<=cnt+"00001";
elsif(cnt="00100")then
clkout<='0';
cnt<="00000";
else
cnt<=cnt+"00001";
endif;
endif;
endprocess;
endone;
UART发送模块代码:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entityuarttxis
port(
clk:
instd_logic;
datain:
instd_logic_vector(7downto0);
wrsig:
instd_logic;
idle:
outstd_logic;
tx:
outstd_logic
);
enduarttx;
architectureoneofuarttxis
signalsend:
std_logic;
signalwrsigbuf:
std_logic;
signalidlereg:
std_logic;
signalwrsigrise:
std_logic;
signalcnt:
std_logic_vector(7downto0);
begin
idle<=idlereg;
------------------------------------------------------
process(clk)
begin
if(clk'eventandclk='1')then
wrsigbuf<=wrsig;
wrsigrise<=(notwrsigbuf)andwrsig;
endif;
endprocess;
----------------------------------------------------------
process(clk)
begin
if(clk'eventandclk='1')then
if(wrsigrise='1'and(notidlereg='1'))then
send<='1';
elsif(cnt="10100000")then
send<='0';
endif;
endif;
endprocess;
--------------------------------------------------------
process(clk)
begin
if(clk'eventandclk='1')then
if(send='1')then
casecntis
when"00000000"=>
tx<='0';
idlereg<='1';
cnt<=cnt+"00000001";
when"00010000"=>
tx<=datain(0);
idlereg<='1';
cnt<=cnt+"00000001";
when"00100000"=>
tx<=datain
(1);
idlereg<='1';
cnt<=cnt+"00000001";
when"00110000"=>
tx<=datain
(2);
idlereg<='1';
cnt<=cnt+"00000001";
when"01000000"=>
tx<=datain(3);
idlereg<='1';
cnt<=cnt+"00000001";
when"01010000"=>
tx<=datain(4);
idlereg<='1';
cnt<=cnt+"00000001";
when"01100000"=>
tx<=datain(5);
idlereg<='1';
cnt<=cnt+"00000001";
when"01110000"=>
tx<=datain(6);
idlereg<='1';
cnt<=cnt+"00000001";
when"10000000"=>
tx<=datain(7);
idlereg<='1';
cnt<=cnt+"00000001";
when"10010000"=>
tx<='1';
idlereg<='1';
cnt<=cnt+"00000001";
when"10100000"=>
tx<='1';
idlereg<='0';
cnt<=cnt+"00000001";
whenothers=>
cnt<=cnt+"00000001";
endcase;
else
tx<='1';
cnt<="00000000";
idlereg<='0';
endif;
endif;
endprocess;
endone;
UART接收模块代码:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entityuartrxis
port(clk:
instd_logic;
rx:
instd_logic;
dataout:
outstd_logic_vector(7downto0);
rdsig:
outstd_logic
);
enduartrx;
architectureoneofuartrxis
signaldataoutreg:
std_logic_vector(7downto0);
signalrdsigreg:
std_logic;
signalcnt:
std_logic_vector(7downto0);
signalrxbuf:
std_logic;
signalrxfall:
std_logic;
signalreceive:
std_logic;
signalidle:
std_logic;
begin
------------------------------------------------
process(clk)
begin
if(clk'eventandclk='1')then
rxbuf<=rx;
if(rxbuf='1'andrx='0')then
rxfall<='1';
else
rxfall<='0';
endif;
endif;
endprocess;
--------------------------------------------------
process(clk)
begin
if(clk'eventandclk='1')then
if(rxfall='1'andidle='0')then
receive<='1';
elsif(cnt="10011000")then
receive<='0';
endif;
endif;
endprocess;
---------------------------------------------------
process(clk)
begin
if(clk'eventandclk='1')then
if(receive='1')then
casecntis
when"00000000"=>
idle<='1';
cnt<=cnt+"00000001";
rdsig<='0';
when"00011000"=>
idle<='1';
dataout(0)<=rx;
cnt<=cnt+"00000001";
rdsig<='0';
when"00101000"=>
idle<='1';
dataout
(1)<=rx;
cnt<=cnt+"00000001";
rdsig<='0';
when"00111000"=>
idle<='1';
dataout
(2)<=rx;
cnt<=cnt+"00000001";
rdsig<='0';
when"01001000"=>
idle<='1';
dataout(3)<=rx;
cnt<=cnt+"00000001";
rdsig<='0';
when"01011000"=>
idle<='1';
dataout(4)<=rx;
cnt<=cnt+"00000001";
rdsig<='0';
when"01101000"=>
idle<='1';
dataout(5)<=rx;
cnt<=cnt+"00000001";
rdsig<='0';
when"01111000"=>
idle<='1';
dataout(6)<=rx;
cnt<=cnt+"00000001";
rdsig<='0';
when"10001000"=>
idle<='1';
dataout(7)<=rx;
cnt<=cnt+"00000001";
rdsig<='1';
--when"10011000"=>
--idle<='1';
--cnt<=cnt+"00000001";
--rdsig<='1';
whenothers=>
cnt<=cnt+"00000001";
endcase;
else
cnt<="00000000";
idle<='0';
rdsig<='0';
endif;
endif;
endprocess;
----------------------------------------------
endone;
UART测试模块代码:
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitytestuartis
port(clk:
instd_logic;
dataout:
outstd_logic_vector(7downto0);
wrsig:
outstd_logic
);
endtestuart;
architectureoneoftestuartis
signaldataoutreg:
std_logic_vector(7downto0);
---signalwrsig:
std_logic;
signalcnt:
std_logic_vector(7downto0);
begin
------------------------------------------------------
dataout<=dataoutreg;
process(clk)
begin
if(clk'eventandclk='1')then
if(cnt="11111110")then
dataoutreg<=dataoutreg+"00000001";
wrsig<='1';
cnt<="00000000";
else
wrsig<='0';
cnt<=cnt+"00000001";
endif;
endif;
endprocess;
-------------------------------------------------------
endone;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- VHDL 串口 通信