FPGA-跨时钟域问题
这两天调试图像,有一个模块输出图像出现闪屏现象,模块环境定义如下:

由于涉及到进出内存操作,为了排除进出内存问题,先屏蔽掉帧缓存模块,发现图像不闪,因此可以定位帧缓存引入的问题。
再看帧缓存模块,由于该模块已经过测试,复用性强稳定性高,不会出现大问题,这时对端口信号进行监测发现问题。
输入控制信号是36MHz,帧缓存模块内部工作时钟是100MHz,因此需要对输入控制信号同步到100MHz下。
输入时序如下:

输入i_a,i_b(脉冲信号),同时c = i_a && i_b;
因为后面模块需要同时用到同步后的i_a信号以及c信号,所以需要对i_a,以及c信号同时跨时钟域,经过同步模块后,抓信号发现2个信号不再同步了。而每次抓信号看,同步后的i_a与c相差一个周期,而不同的综合版本,相差的一个周期前后不一致。
这里我就犯了一个很严重的错误,就是多个信号分别跨时钟域后进行交汇,存在节拍上的不确定性。
即对于同样的同步器,输入信号a和b经过同步以后,o_a与o_b不再保持原有的时序关系。

因此,为了解决该问题,不再对i_a和i_b分别同步,而是只对i_a进行同步,由o_a生成o_b信号。
这时就到了第二步操作:
assign o_b = o_a && flag;
其中,o_a与flag均为目标时钟域(100MHz)。此时再抓信号,依然发现当o_b为1时,存在o_a为0的情况,这从逻辑上是怎么也解释不通的,而且,两个信号主要存在差一个周期的情况,因此还是怀疑同步问题。
再看同步代码,发现如下设计:

最普通的做法,对输入信号进行延展,再用目标时钟采样,得到同步后脉冲。
由于是慢时钟域同步到快时钟域,所以不存在采样不到的问题,但这里仍然有个很大的问题,就是同步器的第一级寄存器会由于不满足建立保持时间而产生亚稳态:

一般情况,跨时钟域信号经过第二个寄存器后会趋于稳定,因此前面用d1与d2信号做同步输出信号必然会因亚稳态问题导致输出也呈亚稳态。
因此简要修改代码:

此时再抓信号看,各控制信号正常,再看图像,也不再闪烁。
跨时钟域问题很多数字逻辑设计的教科书都有讲到,对于芯片设计有专门的CDC检查,但对于FPGA开发来说,一般很少使用相关CDC工具,只能靠开发者在设计的时候就考虑全面。
脉冲信号跨时钟域最常用的就是NDFF方式:

(1)因为输入sig_in不一定在rx_clk的第一个时钟沿采样到,同时考虑到建立保持时间,输入脉冲的持续时间必须大于2*Prx_clk;
(2)为了避免综合工具对同步电路的优化造成节拍上的不确定性以及亚稳态,输入sig_in最好为时序逻辑,而synchronizer内部不能有任何组合逻辑;
(3)多个不同信号进行跨时钟域后进行交汇,则无法保证输出信号的时序,上面第一个问题就是这个道理;
(4)NDFF的第一级触发器输出信号存在不稳定性,即亚稳态,一般要经过第二级寄存器后信号会趋于稳定,因此如果用第一级输出作为最终输出,结果依然会存在亚稳态问题,见上面第二个问题。
跨时钟域当然还有很多其他方式,同步器只是最简单最常用的一种,常见的还有握手、FIFO等,也各有注意事项。
对于视频流来说,数据路径常用FIFO,而控制信号往往采用帧头信号同步后,重新生成其他控制信号。
以上遇到的问题,也是在设计中没有考虑全面导致,以后还需多注意。
浙公网安备 33010602011771号