390 likes | 622 Views
通用异步接收发送器 的设计和实现. 何宾 2011.09. UART 的设计和实现 - 本章概要. 本章给出了 PLD 器件在简单通信系统的应用 -UART 设计。 通用异步接收 / 发送器的设计也是 PLD 在通信系统的经典应 用。该章首先介绍了 UART 设计原理,其中包括 UART 原 理和设计描述、接收模块设计,随后介绍了 UART 的 VHDL 代码描述,最后介绍了 URAT 的软件仿真验证和硬 件验证。. UART 的设计和实现 - 设计原理.
E N D
通用异步接收发送器 的设计和实现 何宾 2011.09
UART的设计和实现-本章概要 • 本章给出了PLD器件在简单通信系统的应用-UART设计。 • 通用异步接收/发送器的设计也是PLD在通信系统的经典应 • 用。该章首先介绍了UART设计原理,其中包括UART原 • 理和设计描述、接收模块设计,随后介绍了UART的 • VHDL代码描述,最后介绍了URAT的软件仿真验证和硬 • 件验证。
UART的设计和实现-设计原理 • 基于通用异步接收发送器UART的RS-232接口是以前计算机上提供的一个串行数据接口,用来将接收的串行数据转换成并行数据,同时将并行数据转换成串行数据后发送出去。当PLD和其它外设通过串口通信时就非常有用。UART发送的数据,经过电平转换后,传送到PLD的外部串行总线接口,然后这些串行数据被送到PLD内部进行处理。被处理的数据然后转换为串行数据经电平转换后传回串口。
UART的设计和实现-设计原理 • 该设计包含下面几个方面: • 并行/串行和串行/并行数据转换 • 使用用户定义的奇偶校验位(缺省设置为奇校验) • 数据波特率可修改(缺省9600) • 包含测试代码和测试向量
UART RXD TXD DBIN DBOUT RDA RDA RD TBE WR PE RST E FE UART的设计和实现-符号描述图
UART的设计和实现-原理和设计描述 • UART设计主要包括两部分:并行数据转化成串行数 • 据,串行数据转换成并行数据。 • UART设计的接收端口将接收到的串行数据转换成 • 并行数据,同时UART的发送端口负责并行数据转换成串 • 行数据。 • 测试代码完成对UART设计的验证,该验证已经在 • Xilinx大学计划提供的开发平台进行了验证,该设计也很 • 容易的移植到其它的EDA平台上。
接收模块 RXD DBOUT RDA RDA RD PE CLK OE FE 发送模块 DBIN TXD WR TBE CLK UART的设计和实现-原理和设计描述符号
UART的设计和实现-原理和设计描述 • UART设计包含两个主要模块,这两个模块封装在一 • 个UART的设计文件中。 • 这两个模块一个处理接收的串行数据,另一个处理发 • 送的串行数据。 • 接收模块的端口接收一个字节的有效数据,并将其转 • 换成8位的并行数据。转换的并行数据放在DBOUT端口。 • 发送模块将发送的数据送到DBIN端口,并且将其转换 • 成一个字节的串行发送数据,转换完的数据TXD端口上。
UART的设计和实现-接收模块的设计 • 接收模块接收串行数据并将其转换为并行数据。该 • 设计包括下面几个部分: • 串行数据控制器 • 用于同步的两个计数器 • 移位寄存器,移位寄存器保存来自RXD的数据。 • 错误比特控制器。 • 来自RXD串口的数据以一定的波特率被接收,所以 • 需要有个控制器同步接收数据的采集相位。串行同步控 • 制器的设计采用了一个状态机和两个同步计数器。在设 • 计中,在每个接收比特数据的中间采集数据。
ctr(3)=’1’ or datactr!=”1010” ctr!=”1000” RXD=’1’ idle dataRst=’1’ ctRst=’1’ EightDelay dataRst=’1’ Waitfor0 RXD=’0’ ctr!=”1000” RST Ctr(3)=’0’and Datactr!=”1010” CheckStop CE=’1’ GetData dataIncr=’1’ rShift=’1’ Waitfor1 Datactr!=”1010” Ctr(3)=’1’ Ctr(3)=’0’ UART的设计和实现-接收模块状态机
UART的设计和实现-接收模块状态机原理 • 当处于idle状态时,串行数据管脚RXD处于高电平状 • 态,在该状态一直等待直到检测到RXD为低电平时,进入 • 到EightDelay状态。 • 在该状态,主要是进行同步,使得在每个比特位的中间 • 采样数据,计数器ctr比波特率快16倍。在该状态下,ctr计 • 数到8。然后进入到WaitFor0状态,waitfor1状态跟在其 • 后,这两个状态的转移由ctr的最高两位确定。进入到 • GetData状态时,开始对RXD数据进行移位。
START D0 D1 D2 D3 D4 D5 D6 D7 PAR STOP UART的设计和实现-接收模块状态机原理 • 这两个状态保证有足够的延迟保证读取采样数据的 • 正中间。当计数器计数到10(8个数据位、一个奇偶位 • 和一个停止位),然后进入到CheckStop状态。这个状 • 态进行奇偶校验。当该状态结束后,进入到idle状态。 对接收数据进行采样的时序的描述
UART的设计和实现-差错控制的实现 • 差错控制寄存器分析接收到的数据,并对三种错误进 • 行判断:奇偶错、帧错误和溢出错误。 • 奇偶错误指接收数据的得到的校验和与接收到的Par不 • 一样。当进行偶校验的时候,D0到D7的和应该是偶数, • 否则是奇校验。该设计中缺省设置为偶校验。当奇偶校验 • 错误时,PE端口为高。 • 帧错误是指UART在给定的时序没有正确的读到数 • 据。当停止位不为1时,表示帧错误,此时FE端口为1。 • 溢出错误是指,当前帧接收完,但还没有读时下一帧 • 数据就到了的情况。当单字节的串行数据可读时RDA为 • 高,移位后的并行数据放在DBOUT端口。一旦RDA端口 • 为高,且此时数据仍在DBOUT端口时,OE溢出错误标志 • 为高。
UART的设计和实现-接收模块内各个子模块的连接关系UART的设计和实现-接收模块内各个子模块的连接关系
UART的设计和实现-发送模块的设计 • 发送模块接收来自DBIN模块的数据,并以串行数据 • 的发送发送到TxD端口上。 • 发送端口的波特率和接收数据的波特率一样,接收和 • 发送波特率的修改方式一样。 • 为了发送存储在DBIN端口的数据,发送模块必须有 • 一个发送控制器、两个控制数据的波特率的同步计数器和 • 发送移位寄存器。 • 两个计数器中的一个计数器用于延迟发送控制器,另 • 一个计数器用来计算发送的串行数据位的个数。TXD端口 • 和发送移位寄存器的最低位连接。
WR=‘0’ idle tdelayRst=’1’ TBE=’1’ Transfer tdelayrst=’ load=’1’ tclkrst=’1’ ’ Shift Shift=’1’ Tfctr=’1’ WR=’1’ RST Tdelayctr= bandrate Tfctr!=”1001” tfctr=”1001” CheckStop CE=’1’ Delay UART的设计和实现-发送模块的状态机
UART的设计和实现-发送模块的状态机 • UART在idel状态,当WR为高时状态发生变化。然 • 后,发送模块加载DBIN端口的数据,下一个状态发送数 • 据。 • Transfer状态准备发送移位寄存器发送数据。设置 • load=’1’,移位寄存器开始加载数据,其顺序是一个起始 • 位、一个字节的DBIN数据、一个奇偶校验位和一个停止 • 位。下一个状态进入到shift状态。在该状态下,移位信号 • 置‘1’,表示移位寄存器移1。Tfincr信号也置1表示递增数 • 据计数器。如果数据计数器不等于9,表示发送移位寄存 • 器没有进行移位操作,此时进入delay状态。如果移位完 • 成,此时进入WaitWrite状态。
UART的设计和实现-发送模块的状态机 • 在delay状态下,发送数据按照正确的波特率发送数 • 据。当tdelayctr与波特率常数一样时,结束该状态。进 • 入到Shift状态。一旦进入到waitwrite状态,结束发送过 • 程。在这个状态需要确认WR信号为高,才能开始发送 • 过程。
UART的设计和实现-UART的VHDL设计代码 • entity UARTcomponent is • Port ( • TXD : out std_logic:= '1'; • RXD : in std_logic; • CLK : in std_logic; • DBIN : in std_logic_vector (7 downto 0); • DBOUT : out std_logic_vector (7 downto 0); • RDA : inout std_logic; • TBE : out std_logic := '1'; • RD : in std_logic; • WR : in std_logic; • PE : out std_logic; • FE : out std_logic; • OE : out std_logic; • RST : in std_logic:= '0‘ • ); • end UARTcomponent;
UART的设计和实现-UART的VHDL设计代码 • architecture Behavioral of UARTcomponent is • type rstate is(strIdle,strEightDelay,strGetData,strWaitFor0,strWaitFor1,strCheckStop); • type tstate is (sttIdle,sttTransfer,sttShift,sttDelay,sttWaitWrite); • constant baudRate : std_logic_vector(12 downto 0) := "1010001011000"; • constant baudDivide : std_logic_vector(8 downto 0) := "101000110"; • signal rdReg : std_logic_vector(7 downto 0) := "00000000"; • signal rdSReg : std_logic_vector(9 downto 0) := "1111111111"; • signal tfReg : std_logic_vector(7 downto 0); • signal tfSReg : std_logic_vector(10 downto 0) := "11111111111"; • signal clkDiv : std_logic_vector(9 downto 0) := "0000000000"; • signal ctr : std_logic_vector(3 downto 0) := "0000"; • signal tfCtr : std_logic_vector(3 downto 0) := "0000" • signal dataCtr : std_logic_vector(3 downto 0) := "0000";
UART的设计和实现-UART的VHDL设计代码 • signal parError : std_logic; • signal frameError : std_logic; • signal CE : std_logic; • signal ctRst : std_logic := '0'; • signal load : std_logic := '0'; • signal shift : std_logic := '0'; • signal par : std_logic; • signal tClkRST : std_logic := '0'; • signal rShift : std_logic := '0'; • signal dataRST : std_logic := '0'; • signal dataIncr : std_logic := '0'; • signal tfIncr : std_logic := '0'; • signal tDelayCtr : std_logic_vector (12 downto 0); • signal tDelayRst : std_logic := '0'; • signal strCur : rstate := strIdle; • signal strNext : rstate; • signal sttCur : tstate:= sttIdle; • signal sttNext : tstate;
UART的设计和实现-UART的VHDL设计代码 • begin • ------------------------------------------------------------------------- • --Title: 初始信号定义 • ------------------------------------------------------------------------- • frameError <= not rdSReg(9); • parError <= not ( rdSReg(8) xor (((rdSReg(0) xor rdSReg(1)) xor (rdSReg(2) xor rdSReg(3))) xor ((rdSReg(4) xor rdSReg(5)) xor (rdSReg(6) xor rdSReg(7)))) ); • DBOUT <= rdReg; • tfReg <= DBIN; • TXD <= tfsReg(0); • par <= not ( ((tfReg(0) xor tfReg(1)) xor (tfReg(2) xor tfReg(3))) xor ((tfReg(4) xor tfReg(5)) xor (tfReg(6) xor tfReg(7))) );
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: 时钟分频计数器 • ------------------------------------------------------------------------- • process (CLK, clkDiv) • begin • if (CLK = '1' and CLK'event) then • if (clkDiv = baudDivide or ctRst = '1') then • clkDiv <= "0000000000"; • else • clkDiv <= clkDiv +1; • end if; • end if; • end process;
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: 传输延迟计数器 • ------------------------------------------------------------------------- • process (CLK, tDelayCtr) • begin • if (CLK = '1' and CLK'event) then • if (tDelayCtr = baudRate or tDelayRst = '1') then • tDelayCtr <= "0000000000000"; • else • tDelayCtr <= tDelayCtr+1; • end if; • end if; • end process; • -------------------------------------------------------------------------
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: ctr 设置 • ------------------------------------------------------------------------- • process (CLK) • begin • if CLK = '1' and CLK'Event then • if ctRst = '1' then • ctr <= "0000"; • elsif clkDiv = baudDivide then • ctr <= ctr + 1; • else • ctr <= ctr; • end if; • end if; • end process;
UART的设计和实现-UART的VHDL设计代码 • --------------------------------------------------------------------------- • --Title: 传输计数器 • ------------------------------------------------------------------------- • process (CLK, tClkRST) • begin • if (CLK = '1' and CLK'event) then • if tClkRST = '1' then • tfCtr <= "0000"; • elsif tfIncr = '1' then • tfCtr <= tfCtr +1; • end if; • end if; • end process;
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: 错误和RDA标志控制器 • ------------------------------------------------------------------------- • process (CLK, RST, RD, CE) • begin • if RD = '1' or RST = '1' then • FE <= '0'; • OE <= '0'; • RDA <= '0'; • PE <= '0'; • elsif CLK = '1' and CLK'event then • if CE = '1' then • FE <= frameError; • PE <= parError; • rdReg(7 downto 0) <= rdSReg (7 downto 0); • if RDA = '1' then OE <= '1'; • else OE <= '0'; RDA <= '1'; • end if; • end if; • end if; • end process;
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: Receiving shift register • ------------------------------------------------------------------------- • process (CLK, rShift) • begin • if CLK = '1' and CLK'Event then • if rShift = '1' then • rdSReg <= (RXD & rdSReg(9 downto 1)); • end if; • end if; • end process; • -------------------------------------------------------------------------
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: 进入数据计数器 • ------------------------------------------------------------------------- • process (CLK, dataRST) • begin • if (CLK = '1' and CLK'event) then • if dataRST = '1' then • dataCtr <= "0000"; • elsif dataIncr = '1' then • dataCtr <= dataCtr +1; • end if; • end if; • end process;
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: 接收状态控制器 • ------------------------------------------------------------------------- • process (CLK, RST) • begin • if CLK = '1' and CLK'Event then • if RST = '1' then strCur <= strIdle; • else strCur <= strNext; • end if; • end if; • end process;
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: 接收状态机 • ------------------------------------------------------------------------- • process (strCur, ctr, RXD, dataCtr) • begin • case strCur is • when strIdle => dataIncr <= '0'; rShift <= '0'; dataRst <= '1';CE <= '0'; ctRst <= '1'; • if RXD = '0' then strNext <= strEightDelay; • else strNext <= strIdle; end if; • when strEightDelay => dataIncr <= '0'; rShift <= '0'; dataRst <= '1'; CE <= '0'; ctRst <= '0'; • if ctr(3 downto 0) = "1000" then strNext <= strWaitFor0; • else strNext <= strEightDelay; end if; • when strGetData =>CE <= '0';dataRst <= '0';ctRst <= '0'; dataIncr <= '1';rShift <= '1'; • strNext <= strWaitFor0; • when strWaitFor0 => • CE <= '0'; dataRst <= '0';ctRst <= '0'; dataIncr <= '0'; rShift <= '0'; • if dataCtr = "1010" then strNext <= strCheckStop; • elsif ctr(3) = '0' then strNext <= strWaitFor1; • else strNext <= strWaitFor0; end if; • when strWaitFor1 =>CE <= '0'; dataRst <= '0'; ctRst <= '0';dataIncr <='0'; rShift <= '0'; • if ctr(3) = '0' then strNext <= strWaitFor1; • else strNext <= strGetData; end if; • when strCheckStop =>dataIncr <= '0';rShift <= '0';dataRst <= '0';ctRst <= '0';CE <= '1'; • strNext <= strIdle; • end case; • end process;
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: 传输移位寄存器控制器 • ------------------------------------------------------------------------- • process (load, shift, CLK, tfSReg) • begin • if CLK = '1' and CLK'Event then • if load = '1' then • tfSReg (10 downto 0) <= ('1' & par & tfReg(7 downto 0) &'0'); • elsif shift = '1' then • tfSReg (10 downto 0) <= ('1' & tfSReg(10 downto 1)); • end if; • end if; • end process; • -------------------------------------------------------------------------
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: Transfer State Machine controller • ------------------------------------------------------------------------- • process (CLK, RST) • begin • if (CLK = '1' and CLK'Event) then • if RST = '1' then sttCur <= sttIdle; • else sttCur <= sttNext; end if; • end if; • end process;
UART的设计和实现-UART的VHDL设计代码 • ------------------------------------------------------------------------- • --Title: 发送状态机 • ------------------------------------------------------------------------- • process (sttCur, tfCtr, WR, tDelayCtr) • begin • case sttCur is • when sttIdle => TBE <= '1';tClkRST <= '0'; tfIncr <= '0'; shift <= '0'; • load <= '0';tDelayRst <= '1'; • if WR = '0' then sttNext <= sttIdle; • else sttNext <= sttTransfer; end if; • when sttTransfer =>TBE <= '0'; shift <= '0';load <= '1'; tClkRST <= '1'; • tfIncr <= '0';tDelayRst <= '1'; • sttNext <= sttDelay; • when sttShift =>TBE <= '0';shift <= '1';load <= '0';tfIncr <= '1';tClkRST <= • '0';tDelayRst <= '0'; • if tfCtr = "1001" then sttNext <= sttWaitWrite; • else sttNext <= sttDelay; end if;
UART的设计和实现-UART的VHDL设计代码 • when sttDelay =>TBE <= '0'; shift <= '0'; load <= '0'; • tClkRst <= '0';tfIncr <= '0';tDelayRst <= '0'; • if tDelayCtr = baudRate then sttNext <= sttShift; • else sttNext <= sttDelay; end if; • when sttWaitWrite =>TBE <= '0';shift <= '0';load <= '0';tClkRst <= '0'; • tfIncr <= '0';tDelayRst <= '0'; • if WR = '1' then sttNext <= sttWaitWrite; • else sttNext <= sttIdle; end if; • end case; • end process; • end Behavioral;
UART的设计和实现-UART设计验证 • 对UART的验证包括两个部分,串/并转换和并/串转 • 换。在验证的时候,可以直接在EDA平台上直接验证。该 • 设计在Digilent Pegasus板上验证通过。该设计验证的方法 • 是盘扫描码通过PC机上的超级终端以波特率9600发出, • 通过串行传输后,然后再8个LED上进行显示。然后这个 • 键盘扫描码正确的传回来。 • 在不同的平台上进行验证的要求是,首先要完成前面 • 的VHDL设计文件,然后完成用户约束文件,将平台上的 • 串口和PC正确的连接。下面给出该设计验证的结构图。
习题 • 1、说明基于PLD的UART的结构及其实现原理。 • 2、在ISE软件和相关的硬件平台上完成本章所介绍的 • UART的设计。