FPGA之道(69)提高设计的综合性能(一)提高设计的鲁棒性

举报
李锐博恩 发表于 2021/07/15 01:16:14 2021/07/15
【摘要】 文章目录 前言提高设计的鲁棒性一些影响设计正常工作的原因非法输入环境干扰 应对方法之输入预处理应对方法之RAM替换FIFO应对方法之状态机超时跳转应对方法之三模冗余应对方法之全局复位应对方法之静态重构应对方法之动态重构 前言 本文节选自《FPGA之道》。 提高设计的鲁棒性 鲁棒即是英文Robust的音译,而鲁棒性也就是健壮性、强壮性的意思。这个世...

前言

本文节选自《FPGA之道》。

提高设计的鲁棒性

鲁棒即是英文Robust的音译,而鲁棒性也就是健壮性、强壮性的意思。这个世界充满着意外,充满着不可预料的东西,因此,为了让FPGA设计不至于那么脆弱,不至于一有风吹草动就撂挑子不干,我们必须想办法提高FPGA设计的鲁棒性。

一些影响设计正常工作的原因

导致设计出现问题的隐患有很多,其中主要的两种是非法输入和环境干扰,介绍如下:

非法输入

几乎所有的系统都必须同时具备输入与输出这两大关键要素,而这其中,影响系统的行为、控制系统的走向,是系统的输入环节。那么,如果输入信号或序列不符合系统设计的初衷,就可能造成系统的紊乱。
例1,对于一个命令解析系统,需要解析的命令共有10种,故其输入应该为4bits宽向量,但是由于4bits的向量共可以表示16种情况,那么当输入出现另外6种非预期的命令时,系统该怎么办?
例2,对于一个数据接收系统,事先约定好一个数据包共包含100个采样,可是当输入一个长度大于或小于100个采样的数据包时,系统该如何处理?
等等……

环境干扰

科学实验总是少不了要说明一下实验的环境,任何系统在工作的时候也是一样,环境温度多少?湿度多少?粉尘指数多少?光照如何?噪音如何?辐射如何?等等,这些都是逃避不了的外界因素。为什么仿真永远不能代替硬件实测?这就是因为仿真永远无法真实还原环境因素所带来的干扰。环境总是在不断变化的,有时细微,有时剧烈,但是总的来说,地球上的环境还是适合人类生存的,人类能抵抗零下四、五十度的严寒,也能承受四十三、四度的酷暑,一句话,“适者生存”。对于FPGA系统也是一样,输入、输出及其内部都无时无刻不受到环境因素的干扰,虽说从模拟到数字,我们已经迈出了抗干扰的一大步,但是对于FPGA设计来说,这还不够。
例1,当一个数据接收系统在等待一个数据接收使能时,由于附近一个大功率射频设备突然动作,导致线路上耦合了一个虚假的使能信号,该怎么办?
例2,由于缺少臭氧层的庇护,空间的辐射和射线都很强,因此用于航天系统中的设备都面临一种叫做“单粒子翻转”效应的环境干扰,它会有一定几率直接将寄存器中保存的数字量打翻,即0变成1、1变成0,那么当这种现象发生在FPGA内部,该怎么办?
类似上述例子的情况还有很多,不胜枚举,如果处理不当,将会导致做网站、网站被黑,做软件、软件死机,做硬件、硬件烧毁等等的囧象。因此,必须想办法提高设计的鲁棒性!

应对方法之输入预处理

输入预处理指的是在将输入信号引入相应的模块之前,先对其进行预处理,即在原有系统框图中添加一个输入预处理模块,用于矫正输入信号中存在的干扰、毛刺等不良因素,当然,矫正的方法通常是根据环境的噪声特性及以往的经验积累得出,因此预处理的效果也会随着对环境特性的认知深度及个人经验的积累多寡有着很强相关性。
如下即为没有输入预处理模块系统与添加输入预处理模块系统的框图对比:
在这里插入图片描述
以接收异步串口传递的信息为例,由于异步串口的波特率通常不高,一个符号通常占据几到几十微妙的时隙,而接收端为了匹配最佳采样位置,通常需要以三到几十倍以上的采样率来对异步串行信号进行采样。此时,设接收端的采样率为串口波特率的十倍,外界干扰导致异步串行信号上出现毛刺的时间宽度小于3个采样周期,那么可编写该异步串口接收系统的预处理模块HDL代码如下:

-- VHDL example
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity InputPreDealer is
	Port ( 
	clk : in  std_logic;
	uartInOriginal : in std_logic;
	uartInCorrection : out std_logic	
	);
end InputPreDealer;

architecture Behavioral of InputPreDealer is
	signal shiftReg : std_logic_vector(3 downto 0);
begin
	process(clk)
	begin
		if(clk'event and clk = '1')then shiftReg <= shiftReg(2 downto 0) & uartInOriginal; if(shiftReg = "0000")then uartInCorrection <= '0'; elsif(shiftReg = "1111")then uartInCorrection <= '1'; end if;
		end if;
	end process;
end Behavioral;

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
// Verilog example
module InputPreDealer(
input clk,
input uartInOriginal,
output reg uartInCorrection
);
reg [3:0] shiftReg;	
always@(posedge clk)
begin
	shiftReg <= {shiftReg[2:0], uartInOriginal};
	if(shiftReg == 4'b0000)
	begin
		uartInCorrection <= 1'b0;
	end
	else if(shiftReg == 4'b1111)
	begin
		uartInCorrection <= 1'b1;
	end
end
endmodule

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

上述矫正算法的核心思想是,当发现4个连续的1或0时,才改变输入预处理模块的输出为1或0,否则,若发现连续的4个数据有0也有1,则认为存在毛刺现象,输出不做改变。当然了,这样做会延迟正常的0、1跳变沿,不过这对于整个输入的原始异步串口信号是一个群延迟,因此只要毛刺不出现在跳变沿附近,就丝毫不会影响后续模块对其中信息的解析。
通过仿真,我们可以看出输入预处理模块的功效,对于毛刺较少的情况,该矫正算法还是很有效的:

应对方法之RAM替换FIFO

一般来说,RAM比FIFO具有更好的鲁棒性,因为我们可以随机读、写其内部任意一个地址,而FIFO由于具有先进先出性,并且当前数据一旦读出就再也无法访问到。总的说来,目前FPGA芯片的稳定性已经非常之高,只要算法或者设计方案能够保证读、写FIFO时候的逻辑正确性,我们还是更倾向于使用FIFO的,因为操作简单。但是,如果FPGA芯片的输入直接连接至内部FIFO,此时输入端的非法情况就会影响FIFO的正常工作,那么此时若使用RAM来代替FIFO,将能够更加简单的解决问题。
例如,标准的数据包长度为100,包与包之间有间隔,但每一个包的100个数据均是连续的,有使能配合。显然我们需要缓存这些数据包,并在需要的时候逐个包读出供后续的模块进行处理。若输入完全合法,那么采用RAM和FIFO均可以,且FIFO更为简单。但若输入存在非法情况,FIFO就不如RAM更加健壮。例如前级芯片某次只发送了50个数据就突然中断(短暂局部掉电或其他原因),并在几个周期后开始发送一个新数据包的数据。此时,如果仅仅简单使用FIFO的话,那么自从输出出现这种非法情况后,从这一数据包开始,以后每次输出的100个数据均为前一个包的后半段与后一个包的前半段组合,这样一来,整个FPGA系统将持续这种错误,无法恢复到正确情况。但是,如果我们使用RAM的话,可以定义每个数据包的存储和读取起始地址均为整百,这样一来,在为后级模块输出数据包时,仅仅会有一个数据包存在问题(后50个数据为RAM上次遗留数据),而在这之后的数据包均可以正常输出(前提是输入端不继续存在非法情况),由此可见,采用RAM的话,可以非常简单的就让系统具有很强的鲁棒性。
使用RAM替换FIFO的方法,就好比视音频在播放时,我们能忍受偶尔出现一点噪声或者一些雪花点,但不能忍受持续不断的图像歪斜或者分屏现象。

应对方法之状态机超时跳转

在【本篇->编程思路->状态机,FPGA的灵魂】一章中,我们已经充分见识到状态机之于FPGA设计的重要性,因此状态机的鲁棒性几乎就代表了FPGA设计的鲁棒性。如果能够参考【本篇->编程思路->代码中的约束信息->状态机的相关约束】章节中介绍的内容,以安全模式实现状态机,那对提高状态机的鲁棒性当然是极好的,但是,如果控制状态机状态跳转的输入信号存在异常情况,则仍可能导致状态机处于假死情况。
例如,状态机工作时的某一中间状态需要等待外界一个脉冲信号才能往下跳转,可是由于环境噪声等原因,外围器件明明发送了一个脉冲,但是在FPGA的端口却没有检测到,这个时候,如果不加入其他逻辑,状态机将会继续等待,如果十分不巧,外围器件也需要状态机后续状态的输出反馈后才会给出下一个脉冲信号,那么整个硬件系统将会由于这一次噪声干扰而进入死锁,俗称死机状态。
应对这种情况的一种比较有效的方法是为这类状态添加超时报错跳转机制。即进入该状态后,并不是无限等待,而是预先设定一个等待时间,该等待时间要保证正常情况下,脉冲信号肯定会在该时间段内到来。这样一来,如果预先设定的时间耗尽还没有等到脉冲信号,则发出出错报警信号供其他模块读取,并与此同时跳转到相应的出错处理状态,完成本次异常的善后工作,并开始下一轮运行。以下即为加入超时报错跳转的示例代码:

-- VHDL example
process(clk)
begin
	if(clk'event and clk = '1')then
		……
		state <= nextState;
		counter <= nextCounter;
		……
	end if;
end process;

process(state)
begin
	……
	when state_X => -- counter is set to 0 in previous state
		nextCounter <= counter + 1;
		if(counter > 1024)then error <=1; nextState <= state_Solve;
		elsif(pulse = '1')then nextState <= state_Y;
		else nextState <= state_X;
		end if;
	……
end process;

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
// Verilog example
always@(posedge clk)
begin
	……
	state <= nextState;
	counter <= nextCounter;
	……
end

always(state)
begin
	……
	state_X : // counter is set to 0 in previous state
	begin
		nextCounter = counter + 1'b1;
		if(counter > 11'd1024)
		begin error = 1'b1; nextState = state_Solve;
		end
		else if(pulse == 1'b1)
		begin nextState = state_Y;
		end
		else
		begin nextState = state_X;
		end
	end
	……
end

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

应对方法之三模冗余

三模冗余是提高应用在宇宙空间的FPGA设计鲁棒性的一种非常有效的方法,但对于一般的地面应用来说倒不需要。它是通过添加冗余电路的方法来提高设计的抗干扰能力,关于三模冗余的具体做法可以参考【本篇->编程思路->代码中的约束信息->HDL中的常用约束示例->保持约束->keep_hierarchy】小节中的例子。

应对方法之全局复位

前面介绍的提高系统鲁棒性的方法,其纠错能力都是有限的,只不过根据不同的环境因素以及设计者的经验而言,性能会有优劣罢了,它们的目的是保证系统不要太过脆弱,而不是杜绝系统出问题。假设真的存在一个足够好的算法,使用它就能够保证当前系统逻辑的超强鲁棒性,那么其所添加的逻辑规模可能比原系统还要庞大。那么新添加的这部分逻辑的鲁棒性又该由谁来保证呢?这是一个无穷尽的循环问题,并且逻辑规模的膨胀给FPGA系统所带来的影响远非如此而已。因此,没有什么方法是万无一失的!所以,一个设计的再好的FPGA系统也总有出问题的时候。
古语有云,“亡羊而补牢,未为迟也”,出了问题并不可怕,可怕的是没有解决的方法。那么,针对这种FPGA系统无法规避的风险,使用全局复位信号是一种常用的做法。这通常需要外界电路环境配合,或者在FPGA内部用逻辑实现一个Watch Dog(看门狗),当然了,前一种方法更好一点。这样一来,当使用电路系统的操作者或者外围检测电路系统感觉到FPGA芯片的行为可能存在一些问题的时候,就可以通过给FPGA芯片发送一个全局复位信号,从而让其从出错状态进入一个确定的状态,并重新开始正常工作。
关于复位信号的具体设计,请参考【本篇->编程思路->复位的设计】章节。

应对方法之静态重构

静态重构指的是对FPGA进行重新配置,它一般需要外部处理器配合,例如单片机、ARM等等,因此静态重构通常都是使用FPGA芯片的被动配置模式。
一般来说,只要为FPGA设计加入一个全局复位信号,就可以在发现FPGA设计出现问题时,让整个FPGA恢复到一个确定的状态,而这个确定的状态就可以是重新配置后的状态。那么为什么还需要使用静态重构这种效率要低得多的方法呢?
原因是这样的,如果干扰导致FPGA设计中,仅仅是寄存器、块存储等类似资源中存储的数据出现错误,那么全局复位信号是能够很好的解决问题的,因为复位操作可以重写这些部分的数据内容,事实上,全局复位信号适用于绝大部分情况。但是如果干扰导致基于SRAM或FLASH工艺的FPGA芯片的SRAM或FLASH中存储的内容出现变化的话,那么此时FPGA芯片所代表的数字电路结构已经发生了本质变化(因为SRAM或FLASH中存储的内容决定了逻辑资源块、连线盒、开关盒、接口资源等等资源内部的硬件连线关系及存储内容)。而全局复位信号只能对数字电路的状态进行调整,却不能对数字电路的硬件结构产生任何影响,因此在这个时候,只能使用静态重构的方法来纠正数字电路结构方面的错误。由此可见,静态重构技术主要是应用在一些极限环境下的,例如太空。
当然了,静态重构技术的用途也不仅限于此,在【本篇->编程思路->时空变换->时空变换之空域优化->静态重构】小节中,介绍了它的另一种用途。

应对方法之动态重构

有静态重构,就可以有动态重构,静态重构针对整个FPGA芯片中的电路系统,它保证FPGA芯片整体的鲁棒性,而动态重构则针对部分FPGA电路系统,它保证FPGA芯片内部某一部分的鲁棒性。
当然了,动态重构的用途也远不仅限于此,在【本篇->编程思路->时空变换->时空变换之空域优化->动态重构】小节中,介绍了它的另一种用途。

文章来源: reborn.blog.csdn.net,作者:李锐博恩,版权归原作者所有,如需转载,请联系作者。

原文链接:reborn.blog.csdn.net/article/details/105021146

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。