2.7 抗干扰设计思想
在FPGA设计中,信号中的毛刺现象是影响设计效率和数字系统设计有效性及可靠性的主要因素。由于信号在FPGA的内部走线和通过逻辑单元时造成的延迟,在多路信号变化的瞬间,组合逻辑的输出常常产生一些小的尖峰,或信号经过长路径传输时受到外界的干扰,产生一些小的尖峰,即毛刺信号,这是由FPGA内部结构和信号外界因素决定的。毛刺现象在FPGA的设计中是不可避免的,有时任何一点毛刺都可以导致系统出错,尤其是对尖峰脉冲或脉冲边沿敏感的电路更是如此。因此,克服和解决毛刺问题是现代数字系统抗干扰设计的重要内容。
2.7.1 干扰产生的原因
信号在FPGA器件中通过逻辑单元连线时,一定存在延时。延时的大小不仅和连线的长短有关,还和逻辑单元的数目有关,而且也和器件的制造工艺、工作环境等有关。因此,信号在器件中传输时,所需要的时间是不能精确估计的。在多路信号同时发生跳变的瞬间,产生了“竞争冒险”。这时,往往会出现 一些不正确的尖峰信号,这些尖峰信号就是“毛刺”。另外,由于FPGA与其他CPLD器件内部的分布电容和电感对电路中的毛刺基本没有什么过滤作用,因此这些毛刺信号就会被“保留”并传递到下一级,从而使毛刺问题更加突出。可见,即使在最简单的逻辑运算中,如果出现了多路信号同时跳变的情况,在通过内部走线之后,也一定会产生毛刺。现在,在数字电路设计及数字信号处理中的信号往往是由时钟控制的多数据输入的复杂运算系统,甚至每个数据都由相当多的位数组成,这时每一级的毛刺都会对结果产生严重的影响。如果是多级的设计,那么毛刺累加后甚至会影响整个设计的可靠性和精确性。
在进行信号传输过程(如常用的串口传输),由于外界的干扰,如在强电磁环境下,会使线上产生瞬时电脉冲(毛刺),从而导致接收端数据出错。
2.7.2 干扰抑制设计方法
1. 利用冗余项法
利用冗余项消除毛刺有两种方法:代数法和卡诺图法,两者都是通过增加冗余项来消除毛刺,只是前者针对函数表达式而后者针对真值表。以卡诺图为例,若两个卡诺图的两圆相切,则其对应的电路就可能产生毛刺。因此,修改卡诺图,在卡诺图的两圆相切处增加一个圆,以增加多余项来消除逻辑毛刺,但该方法对于计数器产生的毛刺是无法消除的。
2. 采样法
由于冒险多出现在信号发生电平跳变的时刻,即在输出信号的建立时间内会产生毛刺,而在保持时间内不会产生,因此,在输出信号的保持时间内对其进行采样,就可以消除毛刺信号的影响。常用的采样方法有两种:一种是使用一定宽度的高电平脉冲与输出,从而避开了毛刺信号,取得输出信号的电平值。这种方法必须保证采样信号在合适的时间产生,并且只适用于对输出信号时序和脉冲宽度要求不严的情况。另一种更常见的方法叫锁存法,利用D触发器的输入端D对毛刺信号不敏感的特点,在输出信号的保持时间内用触发器读取组合逻辑的输出信号。由于在时钟的上升沿,输出端Q=D, 因此当输入的信号有毛刺时,只要不发生在时钟的上升沿,输出信号就不会有毛刺。这种方法类似于将异步电路转化为同步电路,实现简单,但同样会涉及时序问题。
3. 吸收法
由于产生的毛刺实际上是高频窄脉冲,故增加输出滤波,在输出端接上小电容C就可以消除毛刺,如图2-47所示。但输出波形在毛刺出现时刻的前后时间内会发生畸变,在对波形要求较严格时,应再加整形电路,该方法不宜在中间级使用。
图2-47 吸收法消除毛刺
4. 使用D触发器
这是一种比较传统的去除毛刺的方法。原理是用一个D触发器读取毛刺信号,利用D触发器对输入信号的毛刺不敏感的特点,去除信号中的毛刺,如图2-48所示。这种方法在简单的逻辑电路中较常见,尤其对信号发生在非时钟跳变沿的毛刺信号的去除效果非常明显。但是,对于大多数的时序电路来说,毛刺信号往往发生在时钟的跳变沿,这样D触发器的效果就没有那么明显了。另外,D触发器的使用还会给系统带来一定的延时,特别是在系统级数较多的情况下,延时也将变大,因此在使用D触发器去除毛刺时,一定要视情况而定,并不是所有的毛刺都可以用D触发器来消除。
图2-48 利用D触发器消除毛刺
5. 延迟法
因为毛刺最终是由延迟造成的,所以可以找出产生延迟的支路。对于相对延迟小的支路,加上毛刺宽度的延迟可以消除毛刺。但有时随着负载的增加,毛刺会继续出现,而且当温度变化、所加的电压变化或增加逻辑门时,所加的延迟是不同的,必须重新设计延迟线,因而这种方法也是有局限性的。而且,采用延迟线的方法产生的延迟会由于环境温度的变化而使系统的可靠性变差。
6. 时钟信号的灵活使用
灵活使用时钟信号的目的也是尽可能地消除竞争冒险。例如,在时钟的第一个跳变沿触发模块a,下一个跳变沿控制触发模块b,这样时钟的交替也在一定程度上消除了竞争冒险现象,从而抑制了毛刺信号。又如,分别使用时钟的上升沿或下降沿控制不同的模块。但是这些方法不适合使用在比较复杂的设计中,会使设计的条理非常混乱,给以后的阅读、修改带来很大的困难。因此,在选用这种方法时一定要慎重。
7. 状态机控制
对于大型的数字电路设计,状态机是一种非常理想的选择,能使运行性能和硬件资源的占用达到最大的优化,另外,灵活的使用状态机也可以实现信号同步和消除毛刺的目的。在数据传递比较复杂的多模块系统中,由状态机在特定的时刻分别发出控制特定模块的时钟信号或模块的使能信号,状态机的循环控制就可以使整个系统协调运作,同时减少毛刺信号。那么,只要人们在状态机的触发时间上加以处理,就可以避开竞争冒险,从而抑制毛刺的产生。
2.7.3 基于采样法的串口通信设计
本节针对工程设计中常用的串行异步通信电路,给出了采用采样法进行高可靠设计的实例,其实现原理是对每比特位进行3倍采样,并利用3取2的方法进行数据有效位判断。经过实际测试表明,该方法对脉冲干扰有较好的冗余作用,具有很高的抗脉冲干扰能力。
1. 串口异步通信的帧格式和波特率
在串行异步通信中,数据位是以字符为传送单位的,数据位的前、后要有起始位、停止位,另外可以在停止位的前面加上一个比特位(bit)的校验位。起始位是一个逻辑0,总是加在每一帧的开始,在接收数据位过程中又被分离出去。根据串行通信协议,如果要传输非ASCII数据(假如使用扩展字符设置的文本或二进制数据),则数据位格式采用8位。数据位被传输时从一个字符的最低位数据开始,最高位数据排在最后。例如,字母C在ASCII表中是十进制数67,二进制数的01000011,那么传输的将是11000010。校验位是为了验证传输的数据是否被正确接收,常见的校验方法是奇、偶校验。停止位为逻辑1,总在每一帧的末尾,可以是1位、1.5位或2位,通常采用1位。
2. 串行发送电路的设计
为简化电路设计的复杂性,采用的帧的格式为:1位开始位+8位数据位+1位停止位,没有校验位,波特率为38400。
根据采用的帧格式,需要发送的数据为10位(1位开始位、8位数据位、1位停止位),在发送完这10位后,就应该停止发送,并使发送端电平处于逻辑1,然后等候下次的发送。下面是实现上述功能的VHDL源程序:
library ieee; use ieee.std logic 1164.all; entity Com is port(clk,en:in std logic; Send data:in std logic vector(9 downto 0); serial:out std logic); end com; architecture com arc of com is begin process(clk) variable count:integer range 0 to 9:=0; begin if en=′0′then count:=0; serial<=′1′; elsif rising edge(clk)then if count=9 then serial<=Send data(9); else serial<=Send data(count);count:=count+1; end if; end if; end process; end com arc;
其中,Send data(0 to 9)表示需要发送的数据帧,发送时,开始位Send data(0)必须为逻辑0,停止位Send data(9)必须为逻辑1,否则与硬件电路连接的设备接收到的数据会出现错误。在发送每一帧之前,首先给输入使能端一个低电平脉冲,让电路复位(count置0),然后开始发送。变量count 在进程中用来记录发送的数据数目,当数据帧发送完以后,发送端就一直发送停止位(逻辑1)。
3. 串行接收电路的设计
接收电路比发送电路复杂,接收电路要实时检测起始位的到来,一旦检测到起始位,就要将这一帧数据接收下来。为提高接收的准确性,减少误码率,每一位数据都用3倍频的波特率对数据进行采样,然后对3 次采样结果进行判断。如果3 次采样中至少有2 次为高电平,则接收的这一位数据被判断为高电平,否则为低电平。
(1)波特率发生器和采样时钟的设计。为完成3次采样,除了频率为38 400Hz的接收时钟外,还要有一个3倍频的采样时钟。下面是实现上述功能的VHDL源程序:
library ieee; use ieee.std logic 1164.all; entity count625 is port (clk,en:in std logic;Clock1,Clock3:out std logic); end count625; architecture count625 arc of count625 is begin process(clk,en) variable count:integer range 0 to 625:=0; begin if en=′0′then NUll; elsif (rising edge(clk))then count :=count+1; if count=625 then Clock1 <=′1′; count:=0; else Clock1<=′0′; end if; if (count=100 or count=300 or count=500 )then Clock3<=′1′; else Clock3<=′0′; end if; end if; end process; end count625 arc;
其中,clk为时钟;en 控制波形的产生;Clock1 为接收时钟;Clock3 为3 倍频的采样时钟。
(2)接收电路的设计。串行接收电路首先要能判断接收数据的到来,即每一帧的开始,然后对数据进行3次采样,最后判断输出。为简化设计,帧格式仍然采用1位开始位、8位数据位、1位停止位。下面是设计的接收电路VHDL程序:
library ieee; use ieee.std logic 1164.all; entity com receive10 is port(com,clr,clk1,clk3:in std logic; Q:out std logic vector(0 to 9);Valid:out std logic); end com receive10;
architecture com receive10 arc of com receive10 is Signal Enable :std logic :=′1′; Signal Hold :std logic :=′0′; Signal N:std logic vector(0 to 2):="000"; begin Valid<=Enable and Hold; process(clk1,clr) variable Num:integer range 0 to 9:=0; begin if clr=′0′then Enable <=′1′; Num:=0; Q<="0000000000"; elsif (rising edge(clk1))then Q(Num)<=(N(0)and N(1))or (N(1)and N(2))or (N(0)and N(2)); --3取2进行判断 if Num=9 then Enable <=′0′; Num:=0; else Num:=Num+1; Enable <=′1′; end if; end if; end process; process(clk3,clr) --3倍采样 variable m:integer range 0 to 2 :=0; begin if clr=′0′then m:=0; elsif(rising edge(clk3))then N(m) <=com; if m=2 then m:=0; else m:=m+1; end if; end if; end process; process(clr,com) begin if clr=′0′then
Hold <=′0′; elsif falling edge(com)then Hold <=′1′; end if; end process; end com receive10 arc;
其中,N(m)<=com用来对波形采样;Q(Num)<=(N(0)and N(1))or(N(1)and N(2))or(N(0)and N(2))是对其中1位数据的3次采样结果进行3取2判断;Num用来记录接收的数据位数;falling edge(com)用来实时检测每一帧的起始位(即下降沿)的到来;Valid<=Enable and Hold用来产生波特率发生器电路的控制时钟,最后将一帧的10 位数据输出。