基于FPGA的通用8251串行异步收发器(6600+字)
1.简介与仿真结论
随着集成电路技术的发展,电子设计自动化(EDA)逐渐成为重要的设计手段,已经广泛应用于模拟与数字电路系统等许多领域。电子设计自动化是一种实现电子系统或电子产品自动化设计的技术,它与电子技术,微电子技术的发展密切相关,它吸收了计算机科学领域的大多数最新研究成果,以高性能的计算机作为工作平台,促进了工程发展。EDA的一个重要特征就是使用硬件描述语言(HDL)来完成的设计文件,VHDL语言是经IEEE确认的标准硬件语言,在电子设计领域受到了广泛的接受。本文介绍了串行通信的基本理论;综述了EDA技术的发展概况,介绍了MAX+PLUSll软件;熟悉Intel8251基本结构和工作原理.
发送段的说明:
当发送01000110,发出去的是01100010——010,后面的010是校验位和停止位,注意每次发送的后三位是校验位。
paritycycle <= tsr(1) AND NOT (tag2 OR tag1 OR tsr(7) OR tsr(6) OR tsr(5) OR tsr(4) OR tsr(3) OR tsr(2));
txdone <= NOT (tag2 OR tag1 OR tsr(7) OR tsr(6) OR tsr(5) OR tsr(4) OR tsr(3) OR tsr(2) OR tsr(1) OR tsr(0));
txrdy <= NOT txdatardy;
接收段的说明:
发送01101010,接收也为01101010
2.理论分析
发送模块的设计
首先来设计URAT的发送模块,根据系统的要求我们首先定义如下的管脚:
mclkx16 : IN std_logic; --系统时钟
write : IN std_logic; --写时钟
reset : IN std_logic; --复位,0工作,1复位
data : IN std_logic_vector(7 downto 0); --8位并行数据输入
tx : OUT std_logic ; --串行输出
txrdy : OUT std_logic --标志位
该模块的仿真波形图如下图所示:
图1
当信号发送的01000110的时候,将并行信号变为串行信号,data[0]=0, data[1]=1, data[2]=1, data[3]=0, data[4]=0, data[5]=0, data[6]=1, data[7]=0,后3位的010为该数据的校验信号位。由此我们验证了系统发送部分的正确性。
下面来具体介绍发送部分的工作流程:
图2
上图中状态的转移是靠一个内部变量(Variable)来实现的,该变量在进行完当前状态的处理后指向下一个将处理的状态,进程(Process)的每一次处理都根据变量的内容进行相应状态的处理,由于其功能就像一个指针,因此我们称之为接收或发送指针。
其中的信号的转换过程如下:
tsr <= '0'&tsr(7 downto 1);
tsr(7) <= tag1;
tag1 <= tag2;
tag2 <= '0';
txparity <= txparity XOR tsr(0);
IF (txdone = '1') THEN
tx <= '1';
ELSIF (paritycycle = '1') THEN
tx <= txparity;
ELSE
tx <= tsr(0);
END IF;
通过这个代码可以将并型信号转为串型信号,将串行信号发送出去。
其中信号的校验公式如下:
paritycycle <= tsr(1) AND NOT (tag2 OR tag1 OR tsr(7) OR tsr(6) OR tsr(5) OR tsr(4) OR tsr(3) OR tsr(2));
2 接收模块的设计
首先来设计URAT的发送模块,根据系统的要求我们首先定义如下的管脚:
mclkx16 : IN std_logic; -- 输入时钟
read : IN std_logic; -- 读取信号
rx : IN std_logic; -- 接收到的信号
reset : IN std_logic; -- 复位
rxrdy : OUT std_logic; -- 接收的数据准备读取
parityerr : OUT std_logic; -- 接收校验标志
framingerr : OUT std_logic;
overrun : OUT std_logic;
data : OUT std_logic_vector(7 downto 0)); -- 8 bit 数据输出该模块的仿真波形图如下图所示:
图3
当信号接收串型信号01101010的时候,将串行信号变为并行信号,data[0]=0, data[1]=1, data[2]=1, data[3]=0, data[4]=1, data[5]=0, data[6]=1, data[7]=0。由此我们验证了系统发送部分的正确性。
下面来具体介绍发送部分的工作流程:
图4
接收处理首先完成起始位的检测,并自己产生接收时序控制信号,在控制信号的控制下,逐位接收串行输入数据,并根据控制字判断接收数据位数,完成数据的接收后,进行奇偶校验位的判断,最后判断停止位。在接收的过程中设置接收状态输出信号。
其中的信号的转换过程如下:
sample_data : PROCESS (rxclk, reset)
BEGIN
IF (reset = '1') THEN
-- idle_reset
rsr <= "11111111";
rxparity <= '1';
paritygen <= paritymode;
rxstop <= '0';
ELSIF (rxclk='1') AND (rxclk'EVENT) THEN
IF (idle='1') THEN
-- idle_reset
rsr <= "11111111";
rxparity <= '1';
paritygen <= paritymode;
rxstop <= '0';
ELSE
-- shift_data
rsr <= '0'&rsr(7 downto 1);
rsr(7) <= rxparity;
rxparity <= rxstop;
rxstop <= rx;
paritygen <= paritygen XOR rxstop;
END IF;
END IF;
END PROCESS;
通过这个程序,我们可以讲接收端的串行信号变为原始的串行信号。
3.部分核心代码
·发送模块:
LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.std_logic_unsigned.ALL; ENTITY txmit IS PORT (mclkx16 : IN std_logic; --系统时钟write : IN std_logic; --写时钟reset : IN std_logic; --复位,0工作,1复位data : IN std_logic_vector(7 downto 0); --8位并行数据输入tx : OUT std_logic ; --串行输出txrdy : OUT std_logic --标志位); END txmit; --以下定义一些中间变量,具体使用在以下模块中介绍 ARCHITECTURE behave OF txmit ISSIGNAL write1, write2 : std_logic;SIGNAL txdone1, txdone : std_logic;SIGNAL thr, tsr : std_logic_vector(7 downto 0);SIGNAL tag1, tag2 : std_logic;CONSTANT paritymode : std_logic :='1';SIGNAL txparity : std_logic;SIGNAL txclk : std_logic;SIGNAL paritycycle : std_logic;SIGNAL txdatardy : std_logic;SIGNAL cnt : std_logic_vector(2 downto 0); BEGIN --校验公式 paritycycle <= tsr(1) AND NOT (tag2 OR tag1 OR tsr(7) OR tsr(6) OR tsr(5) OR tsr(4) OR tsr(3) OR tsr(2)); txdone <= NOT (tag2 OR tag1 OR tsr(7) OR tsr(6) OR tsr(5) OR tsr(4) OR tsr(3) OR tsr(2) OR tsr(1) OR tsr(0)); txrdy <= NOT txdatardy; --当写信号为0的时候讲数据打入寄存器THR中,THR是一个中间变量thr_write : PROCESS (write, data)BEGINIF (write = '0') THENthr <= data;END IF;END PROCESS; --生成一个分频后的时钟,16分频baud_clock_gen : PROCESS (mclkx16, reset)BEGINIF (reset ='1') THENtxclk <= '0';cnt <= "000";ELSIF (mclkx16='1') AND mclkx16'EVENT THENIF (cnt = "000") THENtxclk <= NOT txclk;END IF;cnt <= cnt + 1;END IF;END PROCESS; --转换过程。shift_out : PROCESS (txclk, reset)BEGINIF (reset = '1') THENtsr <= (OTHERS => '0');tag2 <= '0';tag1 <= '0';txparity <= paritymode;tx <= '1';--idle_reset;ELSIF txclk = '1' AND txclk'EVENT THENIF (txdone='1' AND txdatardy = '1') THEN -- load_data;tsr <= thr;tag2 <= '1';tag1 <= '1';txparity <= paritymode;tx <= '0';ELSE -- shift_data; --一下几行就是并-》串的过程。tsr <= '0'&tsr(7 downto 1);tsr(7) <= tag1;tag1 <= tag2;tag2 <= '0';txparity <= txparity XOR tsr(0);IF (txdone = '1') THENtx <= '1';ELSIF (paritycycle = '1') THENtx <= txparity; --输出校验位ELSEtx <= tsr(0);END IF;END IF;END IF;END PROCESS; --几个控制信号的生成PROCESS (mclkx16, reset)BEGINIF (reset='1') THENtxdatardy <= '0';write2 <= '1';write1 <= '1';txdone1 <= '1';ELSIF mclkx16 = '1' AND mclkx16'EVENT THENIF (write1 = '1' AND write2 = '0') THENtxdatardy <= '1';ELSIF (txdone = '0' AND txdone1 = '1') THENtxdatardy <= '0';END IF;write2 <= write1;write1 <= write;txdone1 <= txdone;END IF;END PROCESS; END behave;·接收模块:
LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE ieee.std_logic_unsigned.ALL; ENTITY rxcver IS PORT (mclkx16 : IN std_logic; -- 输入时钟read : IN std_logic; -- 读取信号rx : IN std_logic; -- 接收到的信号reset : IN std_logic; -- 复位rxrdy : OUT std_logic; -- 接收的数据准备读取parityerr : OUT std_logic; -- 接收校验标志framingerr : OUT std_logic; overrun : OUT std_logic; data : OUT std_logic_vector(7 downto 0)); -- 8 bit 数据输出 END rxcver; --定义的中间变量 ARCHITECTURE behave OF rxcver IS SIGNAL rxcnt : std_logic_vector(3 downto 0); SIGNAL rx1, read1, read2, idle1 : std_logic; SIGNAL hunt : std_logic; SIGNAL rhr : std_logic_vector(7 downto 0); SIGNAL rsr : std_logic_vector(7 downto 0); SIGNAL rxparity : std_logic; SIGNAL paritygen : std_logic; SIGNAL rxstop : std_logic; CONSTANT paritymode : std_logic := '1'; SIGNAL rxclk : std_logic; SIGNAL idle : std_logic; SIGNAL rxdatardy : std_logic; BEGINidle_preset : PROCESS (rxclk, reset)BEGINIF reset = '1' THENidle <= '1';ELSIF rxclk'EVENT AND rxclk='1' THENidle <= (NOT idle) AND (NOT rsr(0));END IF;END PROCESS; --时钟分频rxclk_sync : PROCESS (mclkx16, reset)BEGINIF reset='1' THENhunt <= '0';rxcnt <= "0001";rx1 <= '1';rxclk <= '0';ELSIF (mclkx16='1') AND mclkx16'EVENT THENIF (idle='1' AND rx='0' AND rx1='1') THENhunt <= '1';ELSEIF (idle='0' OR rx='1') THENhunt <= '0';END IF;IF (idle ='0' OR hunt='1') THENrxcnt <= rxcnt + 1;ELSErxcnt <= "0001";END IF;END IF;rx1 <= rx;rxclk <= rxcnt(3); END IF;END PROCESS; --校验位判断过程和数据转换sample_data : PROCESS (rxclk, reset)BEGINIF (reset = '1') THEN-- idle_reset rsr <= "11111111"; rxparity <= '1'; paritygen <= paritymode; rxstop <= '0'; ELSIF (rxclk='1') AND (rxclk'EVENT) THENIF (idle='1') THEN-- idle_reset rsr <= "11111111"; rxparity <= '1'; paritygen <= paritymode; rxstop <= '0';ELSE-- shift_datarsr <= '0'&rsr(7 downto 1); rsr(7) <= rxparity; rxparity <= rxstop; rxstop <= rx; paritygen <= paritygen XOR rxstop; END IF;END IF;END PROCESS; --标志信号的生成generate_flag : PROCESS (mclkx16, reset)BEGINIF (reset='1') THENrhr <= "00000000";rxdatardy <= '0';overrun <= '0';parityerr <= '0';framingerr <= '0';idle1 <= '1'; read2 <= '1'; read1 <= '1'; ELSIF (mclkx16='1') AND (mclkx16'EVENT) THENIF (idle='1' AND idle1='0') THENIF (rxdatardy='1') THENoverrun <= '1';ELSEoverrun <= '0'; rhr <= rsr; parityerr <= paritygen; framingerr <= NOT rxstop; rxdatardy <= '1'; END IF;END IF;IF (read2 = '0' AND read1='1') THENrxdatardy <= '0';parityerr <= '0';framingerr <= '0';overrun <= '0';END IF;idle1 <= idle; read2 <= read1; read1 <= read; END IF;END PROCESS;rxrdy <= rxdatardy;latch_data : PROCESS (read, rhr)BEGINIF (read = '1') THENdata <= rhr;END IF;END PROCESS; END behave;A38-01
总结
以上是生活随笔为你收集整理的基于FPGA的通用8251串行异步收发器(6600+字)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 基于FPGA的图像增强系统的verilo
- 下一篇: 基于FPGA的AFDX接口实现