首页资源分类FPGA/CPLD > 基于FPGA设计与实现UART

基于FPGA设计与实现UART

已有 445117个资源

下载专区

上传者其他资源

    文档信息举报收藏

    标    签:FPGAUART

    分    享:

    文档简介

    基于FPGA设计与实现UART

    文档预览

    基于FPGA设计与实现UART UART(即Universal Asynchronous Receiver Transmitter 通用异步收发器)是广泛使用的串行数据传输协议。UART允许在串行链路上进行全双工的通信。 --- 串行外设用到RS-232异步串行接口,本实验室平台用的是MAXIM公司生产的MAX23。MAX232可以将串口设备需要发送的TTL/CMOS逻辑电平转换为RS-232逻辑电平,同时也可以将要接收的RS-232逻辑电平转换为TTL/CMOS逻辑电平。本实验通过编写VHDL语言程序,实现数据在实验平台与PC之间通过串口进行收发,基于FPGA器件设计与实现UART。 一 UART基本知识 UART是通过串行传送数据而实现通信的,它的帧格式如下:-- -包括线路空闲状态(高电平)、起始位(低电平‘0’)、5~8位数据位、可选的校验位和停止位(可为1、1.5、2位)。这种格式是由起始位和停止位来实现字符的同步。 另外,UART在国际上有一标准的波特率系列,在本实验中采用的波特率为9600HZ。 二 管脚锁定及功能说明 1、时钟 clk锁定在4MHZ的频率,是本实验箱的28号管脚的第三个针脚; 2、复位键reset锁在105号管脚,用来复位; 3、数据输入端口din[7..0]为117——124,实验8位数据输入; 4、输入使能口trans_lock为57,按一次输入一位数据; 5、接收数据dout[7..0]显示为85——96,显示接收的数据 6、接收出错信号frame_erro锁在74,为1则表示接收有误; 7、接收完毕frame_end信号为75,为1表示接收完毕为0则表示正在接收,不允许发送; 8、发送完毕信号trans_end为76,为1表示发送完毕,为0则表示正在发送,不允许接收。 9、串行数据输入口rxd锁在97,串行数据输出口txd锁在98,分别用来数据的输入与输出。 三 UART的设计与实现 1、分频计: 由于本实验采用的波特率为9600HZ,它每隔16个时钟周期采样一个数据,因此实际输入的频率为9600HZ×16=153600HZ,实验平台上没有合适的时钟频率,因此在本实验中采用了4MHZ的时钟输入,对它进行了26分频(4000k/153.6k=26.42),接近了实验要求的时钟频率。它的源代码如下: -- Generated by Quartus II Version 4.0 (Build Build 190 1/28/2004) -- Created on Sun Nov 20 17:09:41 2005 --文件名:baud.vhd --功能:将外部输入的4MHz的信号分成频率为153600Hz=9600Hz×16的信号 --26倍分频计 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity baud is Port (clkb,resetb:in std_logic; clk_out:out std_logic); end baud; architecture Behavioral of baud is begin process(clkb,resetb) variable div:integer range 0 to 26; begin if resetb='1' then --复位 div:=0; clk_out<='0'; elsif clkb 'event and clkb='1' then--设置分频系数 div:=div+1; if div=13 then --一半的时候置0 clk_out<='0'; elsif div=26 then --26的时候置1 clk_out<='1'; div:=0; end if; end if; end process; end Behavioral; 2、 UART接收器 ---串行数据帧和接收时钟是异步的,发送来的数据由逻辑1变为逻辑0可以视为一个数据帧的开始。接收器先要捕捉起始位,确定rxd输入由1到0,逻辑0要8个CLK16时钟周期,才是正常的起始位,然后在每隔16个CLK16时钟周期采样接收数据,移位输入接收移位寄存器rbuf,最后输出数据dout。接收完毕时,数据接收标志信号frame_end置1,标志数据接收完毕,接收过程中为0,防止发送冲突。如果接收的过程中发生错误,则接收出错信号frame_error为1,平时此信号为0。接收器实现的源代码如下: -- Generated by Quartus II Version 4.0 (Build Build 190 1/28/2004) -- Created on Sun Nov 20 17:09:41 2005 --文件名:receive.vhd。 --功能:UART接受器。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity receive is Port (clkr:in std_logic; --采样时钟 resetr:in std_logic; --复位信号 rxd:in std_logic; --数据串行输入信号 r_lock:in std_logic; --接收锁存信号 frame_end:out std_logic;--一位接收完毕信号 frame_error:out std_logic;--接收出错信号 dout:out std_logic_vector(7 downto 0));--显示接收数据 end receive; architecture Behavioral of receive is begin pro:process(clkr,resetr,rxd) --接收信号进程 variable number:std_logic_vector(3 downto 0); --接收数据的位数计数 variable count:std_logic_vector(3 downto 0); --采样时钟计数 variable parity:std_logic:='0'; --计算出的奇偶校验位 variable receive_parity:std_logic; --接收到的奇偶校验位 variable rbuf:std_logic_vector(7 downto 0); --接收缓存 begin if resetr='1' then --复位 number:="0000"; count:="0000"; frame_end<='1'; frame_error<='0'; elsif rising_edge(clkr) then --接收 if number="0000"then --识别起始位 if rxd='0' then if count<"1000"then count:=count+1; else dout<="00000000"; count:="0000"; number:=number+1; frame_end<='0'; end if; end if; elsif number>="0001" and number<="1000"then --接收数据 if count<"1111"then count:=count+1; else count:="0000"; number:=number+1; frame_end<='0'; rbuf(7 downto 1) := rbuf(6 downto 0) ; rbuf(0):=rxd; parity := parity xor rbuf(0) ; end if; elsif number = "1001" then--接收奇偶校验位 if count<"1111"then count:=count+1; else count:="0000"; number:=number+1; frame_end<='0'; receive_parity:=rxd; end if; elsif number = "1010" then--接收完毕 if count<"1111"then count:=count+1; else count:="0000"; dout<= rbuf ; --接收移位寄存器数据进入接收缓冲器 rbuf:="00000000"; number:="0000"; frame_end<='1'; end if; else count:="0000"; number:="0000"; rbuf:="00000000"; frame_end<='1'; end if; if parity=receive_parity then --检验接收是否出错 frame_error<='0'; parity:='0'; else frame_error<='1'; parity:='0'; end if; end if; end process; end Behavioral; 3、 UART发送器 ---发送器每隔16个CLK16时钟周期输出1位,次序遵循1位起始位、8位数据位(假定数据位为8位)、1位校验位(可选)、1位停止位。--- -数据的发送是由手动发送键控制,当输入发送命令时,发送器根据此命进行发送。它将并行数据din[7..0]锁存进发送缓冲器tbuf[7..0],并通过移位发送把寄存器tbuf[7..0]里的数据串行发送至串行数据输出端dout。在数据发送过程中用输出信号trans_end作为标志信号,当一帧数据发送完毕时,trans_end信号为1,否则为0。防止发生冲突。它的实现代码如下: -- Generated by Quartus II Version 4.0 (Build Build 190 1/28/2004) -- Created on Sun Nov 20 17:09:41 2005 --文件名: transmit.vhd --功能: 根据输入的并行数据,发送串行数据 LIBRARY ieee; USE ieee.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; -- Entity Declaration ENTITY transmit IS -- {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE! PORT ( clkt : IN STD_LOGIC; --采样时钟 resett : IN STD_LOGIC; --复位 t_lock : IN STD_LOGIC; --输出锁定,跳变一次输出一个字节 din : IN STD_LOGIC_VECTOR(7 downto 0);--将要输出的数据 trans : OUT STD_LOGIC; --串行输出 trans_end : OUT STD_LOGIC --输出结束标志 ); -- {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE! END transmit; -- Architecture Body ARCHITECTURE transmit_architecture OF transmit IS BEGIN pro:process(clkt,resett,t_lock) variable number:STD_LOGIC_VECTOR(3 downto 0);--输出位数计数 variable count:STD_LOGIC_VECTOR(3 downto 0);--采样计数 variable tbuf:STD_LOGIC_VECTOR(7 downto 0);--输出缓存 variable parity:STD_LOGIC:='0';--奇偶校验位 begin if resett='1' then --复位 number:="0000"; trans_end<='1'; trans<='1'; count:="0000"; elsif rising_edge(clkt)then--信号发送 if (t_lock='1') and (number<"1101") then --保证跳变一次输出一位 if number="0000" then--初始化 if count<"1111" then count:=count+1; else count:="0000"; trans_end<='0'; trans<='1'; number:=number+1; tbuf:=din; end if; elsif number = "0001" then--第一位发送初始位 if count<"1111"then count:=count+1; else count:="0000"; trans_end<='0'; trans<='0'; number:=number+1; end if; elsif number>="0010" and number<="1001"then --发送8位数据位 if count<"1111"then count:=count+1; else count:="0000"; number:=number+1; trans_end<='0'; trans <= tbuf(0) ; --从低位到高位进行移位输出至串行输出端trans tbuf := '0' & tbuf(7 downto 1); parity := parity xor tbuf(0) ; end if; elsif number = "1010" then--发送奇偶校验位 if count<"1111"then count:=count+1; else count:="0000"; trans_end<='0'; number:=number+1; trans<= parity; end if; elsif number = "1011" then--发送结束位 if count<"1111"then count:=count+1; else count:="0000"; trans_end<='0'; trans<= '1' ; number:=number+1; end if; elsif number = "1100" then--发送结束 if count<"1111"then count:=count+1; else count:="0000"; trans_end<='1'; trans<= '1' ; number:=number+1; end if; end if; elsif t_lock='0' then count:="0000"; trans_end<='1'; trans<='1'; number:="0000"; end if; end if; end process; END transmit_architecture; 操作方法:调好时钟频率为4MHZ(重要) 发送过程 打开串口接收器,然后在管脚117——124上输入要输入的数据,例如要输入数据97(小写a的ASIIC值),则117到124的数据设置为“01100001”,然后按下57键,则在串的接收区会显示小写字母a。这样就完成了一次接收过程。 接收过程 打开串口, 在串口发送区输入要发送的数据,然后按下发送键,就完成了一交发送任务(注意 :16进制的发送要有两位,如0a,ab等)。在用ASIIC码发送时,如发送了一个a,则在实验箱85到96管脚显示它的ASIIC为97,即“01100001”,如用十六进制发送,如发送ab则在85到96脚显示它们的十六进制数值,为“10101011”。 四 小结 ---通过波特率发生器、发送器和接收器模块的设计与下载仿真,能较容易地实现通用异步收发器总模块,对于收发的数据帧和发生的波特率时钟频率能较灵活地改变,而且硬件实现不需要很多资源,尤其能较灵活地嵌入到FPGA的开发中。在EDA技术平台上进行设计、仿真与实现具有较好的优越性。

    Top_arrow
    回到顶部
    EEWORLD下载中心所有资源均来自网友分享,如有侵权,请发送举报邮件到客服邮箱bbs_service@eeworld.com.cn 或通过站内短信息或QQ:273568022联系管理员 高进,我们会尽快处理。