在通信数字信号处理中,经常会遇到带有反馈环路的设计。例如数字时钟恢复或者自适应均衡滤波器。该类设计的基础都是对输入数据进行滤波或者均衡,调相,而进行上述计算所用到的系数来自于该滤波器或者均衡器的输出结果。换句话说,本次数据的输出依赖于之前输出数据。该类设计框图如下图所示:
图1
在某些场合下,有可能需要对环路计算/系数计算出来的系数再重新进行变换才加载到滤波器或者均衡器中,这时候在环路计算/系数计算中间会多出一个系数变换的环节,其框图如下图所示:
图2
如上图所示,此时在环路计算/系数计算的输出多了一个系数变换模块,该模块可以是一个FFT或者其他变换。假设此时的输入数据存在缺口(即不是每个时钟节拍都有效),那么此时存在反馈环路的设计应该特别注意,由于环路计算/系数计算和系数变换存在延时,当数据存在缺口时,传给滤波器用的系数应该如何处置?此时有一种常见的解决方案,即把系数通过一个buffer缓存起来,等到新的有效数据出来,再把数据从buffer中读出。注意,由于反馈环路的延时对系统性能的影响很大,此时的buffer不能简单的使用传统的FIFO,因为传统的FIFO的状态信号(empty, almost empty)至少存在一个周期的时延,我们需要的是一种能马上反映出状态的缓存,即缓存一被写入,非空状态马上就能出来而不用等到下一个周期才知道。
还有一个重点,在大规模设计中,假设图2系数变换模块的输入只有并行10个数,但是出来的却是并行的128个数,那么此时缓存放置的位置直接影响到了逻辑资源,因为放在系数变换输出端需要128个缓存,但是放在输入端却只需要10个缓存。因此这时候我们肯定会倾向于把缓存放置于系数变换模块的输入端,如下图所示:
此时存在一个问题,即如果系数变换是纯流水线处理的话,那么等到输入数据Din的缺口出现时才开始把数据存到buffer里,那么此时系数变换模块里存在寄存器里的有效的数据都会在下一个时钟周期往前传递,最终都作用到无效的数据上去。因此,有一种方法是采用输入数据的有效信号来控制系数变换模块的寄存器,当输入数据无效时,系数变换模块里的流水线里的寄存器全部保持,不再翻转。但是此种方法存在一个非常大的设计缺陷,系数变换模块如果是全并行且并行度很大,流水线级数很多时,那么此时一个数据有效信号将会控制很多寄存器,扇出将是惊人的,即使通过复制或者增加buffer可以减少扇出,但是对于布线来说也未必能够得到很好的结果。那么有没有一种更好的办法呢?当然有!
此时有一种很好的办法提出:提前把将进入滤波器/均衡器的数据Din的数据状态指示信号拿过来使用。至于要提前多少个时钟周期取决于系数变换模块的延时。假设系数变换模块的延时是3个周期,那么在本次进入滤波器/均衡器的数据Din无效之前的3个周期前,即开始往缓存里写数据,Din的无效指示信号作为缓存的写使能信号。输入到系数变换模块的数据此时将保持不变,因此3个时钟周期后,系数变换模块流水线里所有的有效数据将会出完,此时数据缺口也刚出现。提前7个时钟周期的数据指示信号作为缓存的读使能信号,此时当缺口没有了,数据开始有效时,刚好有效数据填满了所有的流水线,重新进入滤波器/均衡器计算,其时序图如下所示:
该种方法大幅度减少了数据有效信号的扇出,真正做到了逻辑电路的优化,是一种非常好的思路。