跨时钟域传递数据实例分析

0. 介绍

  跨时钟域传递的方法,Cummings的论文(见附录)中讲的很详细,之前自己也详细看过,除了他的论文还从网上看了一些其他人讲的关于跨时钟域的东西,以为自己已经掌握了跨时钟域的基本方法,面试、笔试完全不虚了,但是呢,前几天去某AI芯片公司二面,在跨时钟域问题上露怯,当然,面试过程全程被吊打,早已懵逼。

  问题是:有一个APB接口的计数器IP,CPU可以通过写数据,控制计数器技术到5或者10等等任意数,但是写数据和计数器接受数据的时钟是异步的,并且希望在计数器最大值切换的时候,当前计数结束才可以切换,比如最大值为10,计数到6的时候来了一个新值5,必须计数到10之后,才能替换成5,应该怎么实现这个功能,根据APB的接口具体说一下信号都是怎么给的?

1. 方法

  当时他提示我用握手信号,但我不太敢说,当时又想到通过握手信号来解决,但没有给出让他满意的方案,现在想想CPU可以将写的数据和一bit的valid信号打包成一个数据,最高位是valid信号,其他位是要写的数据,CPU先将要写的数据放到pwdata上,下一个时钟周期再让valid有效,计数器IP采样到写入的数据并保存起来,当前计数结束的时候,加载新的计数值,之后计数器IP通过prdata给CPU发一个应答信号。

2. 分析

  一开始CPU将数据放到pwdata上,待数据稳定后将pwdata最高位的valid拉高,计数器IP通过两级寄存器采样valid信号,这里可能采样出现亚稳态,采样到0,但这不影响功能,只是会使采样延迟一个周期而已。接着计数器将新的计数值保存下来,待当前计数结束之后加载新的计数值。然后通过prdata将应答传给CPU。

  这样的话似乎可以实现所需要的功能。 

 3. 资讯别人

在一个IC的qq群里,问的群主,他给的方案:

流程可能是(看你的spec):
1:CPU写数据,要更新cnt值。
2:cnt值同步到counter clk。同时CPU一直读(pooling方式)某个地址的flag,看cnt值更新没有(开始一直读到0)
3:counter更新后,再把这个事件更新会apb clk domain。
4:这时CPU可以读到flag为1,表示更新完成。

 但我觉得第二布中cnt值同步到counter clk,即便是用两级寄存器,也是多位跳变,容易发生亚稳态,导致未预期的采样值。感觉我那种方法比较好,等到apb

 clk 上的新的cnt值稳定后,才通知counter采样。

 4. EETOP求助

http://bbs.eetop.cn/forum.php?mod=viewthread&tid=867640&pid=10107316&page=1&extra=#pid10107316

这个用握手就好。

  1. 当cpu重新配置一个数值时,在apb clock domain监测到配置有变化,latch注,拉起一个pulse,并同步到counter的clock domain。

  2. counter clock domain看到这个脉冲,拉起一个hold电平,当后续counter计数到上一次配置的threshold,看到hold信号拉起来,直接latch apb clock domain的那个寄存器,就行。

附录

1. Synthesis and Scripting Techniques for Designing MultiAsynchronous Clock Designs

2. Simulation and Synthesis Techniques for Asynchronous FIFO Design

3. Simulation and Synthesis Techniques for Asynchronous FIFO Design with Asynchronous Pointer Comparisons

真理剑客是个武功高强的朝圣者,独自战胜了三个匪徒,在基督徒到达终点之前加入了他的朝圣队伍。
原文地址:https://www.cnblogs.com/east1203/p/11521568.html