FPGA如何处理--器件数据传输的异步处理

  记于:2020.6.29

  概述:在FPGA设计中,异步信号是我们需要重点照顾的,很多不起眼的(缺乏我们仔细思考处理的)信号,往往会给我们的设计带来挥之不去的隐患。没错,就是那种时不时出现的小问题,你想他出现的时候,它不一定出现。但是,在你想早点下班的时候,它却会不经意出现。在这个笔记里边,我将讲述一个处理一个外部输入异步信号的过程。

  过程:

  在我们的一个产品中,需要用到一个母板以及一个子板,各自有一个FPGA芯片作为信号处理传输的中心。这两个FPGA之间,使用同一个状态机(3个状态,使用2bit),分别是idle状态(00),load状态(01),rtx状态(10)。从母板到子板使用的是2个普通的信号线连接,使用的是3.3v信号线,子板跟母板使用的时钟信号都是100MHz。该信号在子板中使用,作为重要的状态机信号,离职的工程师是直接的将该信号直接使用,甚至都没有将这个输入信号buffer一下。

  那么,现象是什么样子的呢?那就是在产品做高低温的时候,经常会采集的信号抖动(消失)。其实,现在回过头来,可以考虑得到,肯定是采集这个时间段的信号出现了异常。但是,由于整个信号链路比较长,我们也怀疑过是否其他模块的输出或者开关引起的干扰问题引起的。事实上,我接手后,在处理高低温的问题上,开始也是焦头烂额,这个工程的可维护性实在太差了。顶层使用的是quartus的图像界面,像硬件一样的连线的,那么可以想象的是,他肯定没有对这个设计做仿真的。然后,代码的整洁、规范、注释,肯定是没有的,想都不要想。上一个离职的工程师接手过来,两年了都不敢改动一点,就算是改动了,也过不了高低温测试,也就是无法转产。好吧,离题了。总之,在验证高低温的过程中,出现问题的原因可能很多。

  在我检查外部输入信号的时候,我发现这些信号都没有做输入输出的io_buffer,那不用多说了,先加上,稳妥一些。事实上,为这两根信号I_fsm_state加上输入输出buffer之后,高低温出现问题的概率(特别是低温)的情况明显减少了。原来在10台仪器中,一般会有8台高低温问题,现在可能变成了3/10台有问题。当然出现高低温问题的原因还有其他的,比如ADC的数据采样同步问题,这个是另外一个话题。当我处理完其他问题之后,也试过一次测试10台高低温,全部通过的情况。当我自以为是没有问题之后,在接下来的一年里边,大概是两三个月,质检人员会拿一台两台仪器过来给我说是低温问题,在-10度的左右的时候出现系统信号混乱不正常的情况,等到问题升高几度,又会恢复正常。这种情况,因为本身机器从-10度的冰箱里边拿出来,开机十几分钟后,机器本身会发热,温度自然会上去,因此这不算是严重问题,也不会影响使用,加上出现的情况极少,因此我也就敷衍过去了,总的来说,我是没有更多的头绪,以及充足的时间来解决这个问题,毕竟出现问题的时间还是很短的。

  根本因素出现了:

  然而,我在调试另外另外一个新板子的时候,意外的发现,这个I_fsm_state[1:0]信号,跳转居然出现这种情况: 01 01 01 01 01 00 10 10 10 10 10;实际上,这个状态机的跳转,应该是01 01 01 01 01 10 10 10 10.也就是说,只有从01->10的情况,没有从01->00的这个设计的。当我检查是否有buffer,以及将I_fsm_state打两拍之后再使用,情况还是一样。这时候,我就考虑,这两个信号从不同的IO出来,经过排插走线,在100MHz的时钟下,是否能够完全的同步呢,也即是I_fsm_state[0]需要从1->0,  以及I_fsm_state[1]需要从 0->1 ,这两个信号能否完全同步的跳转呢。在理想情况下,是可以的,但是实际上,这两个FPGA的时钟是同频异步的,这个两个信号经过不同的物理走线,难免会出现延时不一致的情况。因此,出现不同步反而是必然的情况。

  那么,既然问题的可能原因找到了,那么问题很好解决了。方法也是多种多样的,我想到的方法一,使用时钟进行跟FIFO做跨时域处理,这个是常用的方法,但是需要添加时钟信号又要浪费信号线,使用FIFO,总觉得还是浪费了一些资源。方法二,增加一些同步状态机逻辑,相当于去抖电路,例如当信号从01->10的时候,如果出现00,则不进行处理,保证状态机的顺序是正常的,不会中间出现01 01 00 10 10的这种情况,毕竟两个板子出现一个周期的跳动对系统没有影响。因此,我选择了方法二,但是,这种方法不是必然合适,当需要处理的bit数位宽比较多的时候,这种方法就不适用了。方法三、如果使用格雷码的状态机,应该可以避免这个问题的,但是由于该状态机牵涉到的东西比较多,所以还是作罢。

  这样,由于这两个信号的异步处理而引起的问题消失了。

  感想:如何处理异步信号,方法上,我们肯定听过很多,也知道出现这些情况应该怎么处理。但是,当我们设计的时候,很容易忽略这些处理方法,或者说,我们没有挨过板子,就不会把这些设计原则记在心里。在我们可以进行代码设计的时候,需要尽可能的按照前人总结的原则,不要走不必要的弯路。

 

2021.1.13更新

    之前在上文提到  “毕竟两个板子出现一个周期的跳动对系统没有影响”,我想我还是太年轻了。对于普通的信号,出现一个周期的跳动,可能是无关重要的。但是,这个是状态机信号,如果这个状态出现了跳动,那么意味着所有的相关状态信号都会出现一个周期的跳动,跳动时间不多,也就是10ns。

 

    这里呢,就要说到我在调试产品中,解决另外一个顽固问题的故事了!

    在我们的产品中,超声方面的应用,需要发送一个脉冲方波出去,然后多路ADC采集,然后将各个通道采集的数据显示在屏幕上,形成一个画面。我们发现,在脉冲发出去后很短的一个时间内,总是难免有些波形跳动,跳动发生在脉冲方波发出去的短时间内,随着时间的推移,这个跳动就消失。这里边涉及到超声成像的知识:稳定的干涉。我通过抓取跳动的通道的ADC数据,发现,这个波形看起来明显的跳动,其实,也就是跳动了一个周期10ns,比如说,峰值反复出现在时间30与31周期两个位置,正是由于这个跳动,使得整体的画面,看起来闪的非常明显。

    那么,得知画面闪的现象了,那么就寻找原因洛。首先,脉冲回波出现跳动,那么首先要开发出去的脉冲方波是否有跳动(状态:10的时候发出脉冲)。如果从状态10开始算,是没有跳动的,但是,从整个状态机来看,确发现发出去的脉冲方波,在某些状态下,的确存在一个周期的跳动,那么是不是由于这个跳动,导致的画面异常呢?如果要解决这个跳动问题,那么,如果还是使用另外一个FPGA传上来的状态信号(2bit),不管如何做同步,由于两个板子使用不同的时钟域,难免还是会出现一个周期的跳动的。那么干脆点,不使用这个状态信号了,而是使用1bit的同步信号(大约几十个状态周期进行一次同步),这样子,即使这个同步信号有一个周期的抖动,那么这个抖动也分散在几十个状态周期里边,这个变化抖动变化,可以忽略。那么,在本地的FPGA建立起独立的状态机,替换另一个FPGA的状态机信号。结果非常满意,存在的始波位置的抖动完全消失,得到的画面非常稳定。

    这个问题,不一定会出现在所有的产品中,只是极个别的机器中会出现,通过更换器件,也许能解决,也不一定。即使出现,在产品的应用中影响也不大,因为通常都是多个脉冲同时发出,并且经过信号处理,始波位置的波形也经常会被舍弃。但是,我们做严格的测试的时候才凸显出来,特别是高低温时,产品批量生产的时候,PCB,器件都会出现不一致性,那么难免会出现个别产品的画面抖动明显。

    经过这个问题的解决,对于处理异步信号有了更多的理解,或者说是体验式的理解。后边还有哪些找干扰,找单个数据异常的经历,后续更新上,这些经历往往是看起来不惊奇,但是过程非常煎熬。

posted @ 2020-06-29 11:39  不惑的初学者  阅读(442)  评论(1编辑  收藏  举报