题记:Uncle donkey的『闺中』挚友,在项目中踩了一个异步信号同步的坑,经过呕心沥血Debug 后找到问题的根结,拿出来分享给各位同仁。
『亚稳态』是数字同步电路中的暗雷,如果在设计时处理不好,随时炸裂。多数时候就是那一个小小的遗漏,芯片变成了石块,你再深情的看他,他就是不理不睬不翻转。『亚稳态』是由信号在不同时钟域间穿越引起的,常用的解决办法有:插入同步器,握手信号,异步fifo,每种方式都有其对应的应用场景。今天不讲async原理,分享一个async问题的实例。
如上图,要把clk\_b domain 的多bit信号的sig\_b 传到clk\_a domain, 下面是一些补充条件:
- enable 维持clk\_b 的2个周期,clk\_b的频率要比clk\_a的频率低,所以不会因为enable的脉冲宽度过小而导致clk\_a采样不到。
- 在enable拉高的前后过程中,sig\_b 都不会改变,set\_max\_delay有约束sig\_b -> si\_a 的延时,保证采样前data已经稳定。
原始的设计用如下方式实现,但这段code在最终IC上,是有问题的,代码中的clear 是clk\_a domain 中用来清0的信号,在采样过程中不会跳变为1。
always @(posedge clk_a or negedge rst_n)
_ if(~rst_n)_
_ sig_a <= 8'b0;_
_ elseif(enable)_
_ sig_a <= sig_b;_
_ elseif(clear)_
_ sig_a <= 8'd0;_
对于以上代码,构想的电路结构是图一或图二。
如图一所示,在enable 拉高后,sig\_b 会被采样至sig\_a, 当enable 拉底时,因为sig\_b 保持不变,所以能够保证sig\_a 锁存的是对的值。
如图二所示,enable 拉高后,clk\_a 对应的g\_clk 被放开正常跳转,sig\_b 被采样至sig\_a, enable拉底后,因为此时clear不会动,且g\_clk 被关断,所以sig\_a 保持。
然而人算不如工具算,实际上这段代码综合出的电路如下:
Enable 会被拉到D端做逻辑,在enable 拉高后可以正确采样到sig\_b, 但是在enable 拉低时,因为enable 相对clk\_a 是异步的,enable 到D 的时间与到g\_clk 的时间有差异,而且STA 时不会对其做check, 当到D端的时间比到g\_clk 的时间快,就会导致D端已经变0,而clk还有最后一个pluse, 会把0 锁存进去。
对于以上的错误,在芯片验证阶段只会看到data都变0,或部分变0,起初是不会联想到是同步问题导致的,跟常规认知上异步信号同步做错后既有 0->1 又有 1->0 的情况不同,很难被发现。在此建议大家在同步电路设计时,所有影响到 g\_clk 的异步时钟域的信号,一定要做同步处理。
跋:十分感谢亲爱的你分享,这是一种十分好的方式,在此Uncle donkey 倡导一下:在做项目的过程中难免不遇到千奇百怪的坑,如果您有时间,如果您开心,就拿出来与大家一起分享,予人玫瑰手留余香,除了余香还有Uncle donkey 深深的爱。
作者:陌上风骑驴
来源:https://mp.weixin.qq.com/s/wYX8ymSB9UX-RIw\_8-qG6w
作者微信公众号
相关文章推荐
更多IC设计技术干货请关注IC设计技术专栏。