【Chips】跨时钟域的亚稳态处理、为什么要打两拍不是打一拍、为什么打两拍能有效?

本文解析了跨时钟域中亚稳态的处理方法,解释了为何采用“打两拍”而非“打一拍”。通过实例分析,探讨了不同情况下亚稳态的影响及对策。

Title: 跨时钟域的亚稳态处理、为什么要打两拍不是打一拍、为什么打两拍能有效?

  • 前言

    个人颜色习惯:

    黑色加粗:突出显示;

    红色:重要;

    洋红色:产生的疑问 question;

    蓝色:个人思考 或 针对问题的Solution

1 个人疑惑

在学习 “跨时钟域的亚稳态的应对措施” 时,常会看到有三种解决方案:

  1. 单bit信号,用:打两拍
  2. 多bit信号,用:异步FIFO
  3. 多bit信号,用:格雷码
  4. 多bit信号,用:握手

记是记住了,但我有好几个疑惑一直没理解,网上冲浪却搜不到答案、还是非常困惑…
以下是我的疑惑:

  1. 为什么用“打两拍”来应对跨时钟域的亚稳态,“打一拍” 不行吗

  2. 为什么说,用“打两拍”只是降低了亚稳态的概率,但也有可能导致亚稳态的传递呢

    若后接了个FF,随着posedge clk的出现,触发器不应该直接就采到0或1了吗,为啥亚稳态还有一定概率传递呢?

  3. 假设是DFF(D触发器),其亚稳态稳定后的值,会恢复为正确的预期输出值吗? 还是就算稳定了也是无效输出?

  4. 即使 “打两拍”能阻止“亚稳态的传递”,但亚稳态导致后续FF sample到的值依然不一定是符合预期的值,那 “错误的值” 难道不依然会向后传递,从而造成错误的后果吗

  5. 多bit的跨时钟域情况用 异步FIFO处理,好理解;格雷码有啥用嘞?
    格雷码可以让相邻二进制数变化只改变1位,但在多bit的data传输过程中,data value不都是随机变化么,格雷码有啥用嘞?

主要是前面关于打两拍的疑惑,网上冲浪找不到解答的帖子。
网上只有两个核心的回答,但对我这样的数电小白,完全是没有回答到我个人解惑的点子上,但解惑后再看,会有新的收获

  1. 打两拍的目的第一拍是异步信号转同步,第二拍是防止亚稳态的传递。

    我听了还是很迷。( ̄▽ ̄)"

  2. 打一拍和打两拍和打三拍的区别用触发器进入亚稳态的平均故障时间间隔MTBF进行计算,证明打拍数增加,产生亚稳态的可能性递减:打一拍直接用,很可能出现亚稳态输出;打两拍再直接用,出现亚稳态的概率是109年出现一次(具体计算参数见reference);打三拍再直接俄用,出现的概率更低,但是除非超高频率不然没必要。

    可见reference:跨时钟域同步,为什么两级寄存器结构能够降低亚稳态? —— 知乎 龚黎明

那我个人疑惑呢,最后在外网 stack exchange 上解答了——这个老哥居然和我的疑问一毛一样! 实在是欣慰,久旱逢甘霖…( ̄▽ ̄)"

Stack Exchange上的回答:How does 2-ff synchronizer ensure proper synchonization?
(不知为什么用firefox不显示问题图片,用chrome才显示图片…)

于是,我打算用自己的话,记录一下它的问题与回答,也回答我个人的疑惑~

2 概念补充

什么是亚稳态 metastable state?

首先要阐述一下亚稳态的概念。
元器件在现实运行时,触发器输出的逻辑0/1需要时间跳变,而不是瞬发的。因此,若未满足此cell的建立时间、保持时间,其输出值则为中间态,那在logic上可能算成0也可能算成1很难讲(波形显示上可能是毛刺、振荡、固定值等),这就是亚稳态。

一般波形图像上,1是高电平,0是低电平;但微观的亚稳态波形如下:

在这里插入图片描述
如图所示:亚稳态的输出波形会卡在中间,过一段时间后,可能稳定成1,也可能稳定成0,但都和原预期值没啥关系了,是无效的!

单bit信号,应用“打两拍”的电路结构图

在这里插入图片描述

这张图,给出了两个点:

  1. “打两拍”后可以直接接组合逻辑电路。

    我之前以为后面必接时序电路,相当于后面的电路也是触发器,于是产生了:“把打两拍改成打一拍,算上后面的时序电路,不也是相当于打两拍吗” 这样的愚蠢困惑…( ̄▽ ̄)"

  2. 下方的波形给了“打两拍能大概率防止亚稳态传递”的图示

    由于异步data变的太突然,第一拍sample后出现亚稳态,第三拍sample后把亚稳态堵住了,得到正常电平(但值不一定和原预期相同)。

3 解惑环节

综上,可以解答我之前的3个疑惑了:

  1. 为什么用“打两拍”来应对跨时钟域的亚稳态,“打一拍” 不行吗

    如打两拍的电路结构图所示:打一拍的话,若第一拍sample到亚稳态,则后续组合逻辑电路的输入直接就是亚稳态波形,肯定会把亚稳态传递下去,就完犊子了。

  2. 为什么说,用“打两拍”只是降低了亚稳态的概率,但也有可能导致亚稳态的传递呢

    如前面的两张亚稳态的波形所示,亚稳态如果在1T内稳定成高电平或低电平了(概率80%),那第2拍就sample到正常的0或1;若亚稳态1T最后还是中间态,那第2拍还是可能出现亚稳态的,但概率低。

    亚稳态稳定需要多久,具体时间由工艺决定。

  3. 假设是DFF(D触发器),其亚稳态稳定后的值,会恢复为正确的预期输出值吗? 还是就算稳定了也是无效输出?

    如前面的亚稳态微观波形所说:即使亚稳态稳定了,值也无效。

剩下俩疑惑,大头讲。见下文。

打两拍的sample到错误数据怎么办

  • sample亚稳态,结果可能多样

    sample亚稳态,得到的结果可能取决于亚稳态最后稳定于什么状态,如下图表示出各种sample的可能:

在这里插入图片描述

如图所示,adat是实际的异步data、bq1_dat是两级触发器中的第一个寄存器sample的数据、bq2_dat是第二个寄存器sanple到的数据,bclk是同步时钟。
则:

a)中,异步data持续2T;FF1 sample到亚稳态时,FF2在下一cycle 对亚稳态的sample是0;但最终sample到了正确的data值。

b)中,异步data持续2T;FF1 sample到亚稳态时,FF2在下一cycle 对亚稳态的sample是1;但最终sample到了正确的data值。

c)中,异步data马上结束,等价于只持续1T(相当于没sample到就错过了);FF1 sample到亚稳态时,FF2在下一cycle 对亚稳态的sample是1;运气好,最终sample到了正确的data值。

d)中,异步data马上结束,等价于只持续1T;FF1 sample到亚稳态时,FF2在下一cycle 对亚稳态的sample是0;相当于最终错过了data值,没sample到…

那咋办,岂不是说明“打两拍”的方法不行???

  • 答案:

    因为 “打两拍” 的目的,是为了在单bit传输时,尽可能的防止亚稳态的传递,至于这个sample的正确性,本来就不是重点。这种“sample的正确性如何保证”得根据信号的具体类型、目的、应用场景,来进行具体的讨论。

    1. Trigger Signals:一个脉冲信号,用来开机、启动什么的。它没什么数据信息量,早一个clk、晚一个clk都ok,反正能起作用就行。那上面这个问题就无所谓了。唯一要保证的是,原始异步脉冲信号至少保持2T!(保证打两拍后,能sample到有效信号)
    2. Control Buses:因为有多bit数据需要进行同步,关系比较复杂。那就不能用 “打两拍” 的方法,得用 “握手机制“。
    3. Data Buses:这种情况,非常在乎上面提到的正确性问题。所以就 更不应该用 ”打两拍“方法,得用 异步FIFO的好吧… 在异步FIFO中的指针使用格雷码,可以降低指针在跳变时出现的亚稳态风险、冒险现象。也就说,格雷码和异步FIFO是结合使用的… ( ̄▽ ̄)"
  • 总结:

    1. 当你在乎跨时钟域 “用打两拍解决亚稳态,导致后续sample可能未sample到正确结果” 的case,那就不该用 “打两拍” 的方案,可以考虑异步FIFO和握手机制!而格雷码,和异步FIFO是联合使用的。
    2. “打两拍”的方法,若应用于“从快速时钟域同步到慢速时钟域”,数据得多保持几T,不然会漏采数据。
<think> 在用户查询中,用户希望解决“配置使用USB打印报错的解决方案”。结合引用内容,尤其是引用[1]和引用[3],可以提取关键信息。 引用[1]详细描述了USB模式配置错误导致的udc-core报错问题,并提供了三种可能的解决方案:检查驱动、修改USB模式为设备模式(而非OTG模式)、禁用USB网卡功能。引用[3]则提供了Android设备上打印调试日志的方法,尤其是通过adb logcat命令查看Unity相关日志。 用户的问题核心是“USB打印报错”,但未明确具体场景。根据引用内容推测,可能涉及类场景: 1. Android系统启动时USB模式配置错误导致的循环报错(引用[1])。 2. 安卓应用(如Unity开发的APK)运行时需要通过USB打印调试日志(引用[3])。 考虑到用户上次请求是查找配置USB打印报错的方案,这里应优先解决硬件/驱动层的USB配置问题(即引用[1]的案例),同时补充应用层日志打印方法(引用[3])作为辅助排查手段。 解决方案需分步骤呈现: 1. 针对USB模式冲突问题:修改设备树文件,将USB口设置为设备模式(device mode),避免与ADB所需的模式冲突。 2. 针对驱动问题:检查UDC驱动状态和硬件识别情况。 3. 针对虚拟网卡/串口冲突:在内核配置中禁用USB网卡功能。 4. 日志收集方法:通过adb logcat命令捕获具体报错信息,便于进步分析。 最后生成相关问题需围绕USB配置、日志调试、内核设置等方向设计。 </think> 基于引用内容和USB打印报错的常见解决方案,以下是系统性的解决步骤: ### 、核心问题排查 1. **USB模式冲突(主因)** Android系统启动ADB时需要**设备模式**(device mode),但硬件可能默认设置为**OTG模式**,导致冲突循环报错: ```bash udc-core: couldn't find an available UDC ``` **解决方法**: - 修改设备树文件,强制设为设备模式 ```c // 文件路径:longan/device/config/chips/t527/.../board.dts &usb0 { dr_mode = "peripheral"; // 将"otg"改为"peripheral"(设备模式) }; ``` - **注意**:修改后该USB口将无法读取U盘[^1] 2. **驱动状态验证** ```bash # 检查UDC驱动状态 zcat /proc/config.gz | grep CONFIG_USB_DWC3 # 确认硬件识别 ls /sys/class/udc/ # 正常应显示udc设备名 ``` 若无输出,需在内核配置中启用: ```bash ./build.sh menuconfig > Device Drivers > USB support > USB Gadget Support > 启用DWC3驱动 ``` 3. **功能冲突处理** 当同时启用**虚拟网卡**(CDC Ethernet)和**虚拟串口**时会导致冲突: ```bash ./build.sh menuconfig > Device Drivers > USB support > USB Gadget Support 取消勾选 [*] Ethernet Control Model (CDC ECM) ``` ### 二、日志捕获与分析 通过ADB获取详细报错(需开启USB调试模式): ```bash adb logcat -s Unity | grep "E Unity" # 过滤Unity引擎错误 adb logcat | grep "usb" # 检查USB相关内核日志 ``` 关键错误示例: ``` E AndroidRuntime: USB configuration failed: EP conflict E udc-core: failed to start usb_peripheral ``` ### 三、补充解决方案 1. **固件更新** 检查全志平台最新SDK包,修复已知USB控制器Bug: ```bash git clone https://github.com/allwinner-dev/linux.git -b t527-android13-lts ``` 2. **硬件排查** 使用万用表检测USB数据线D+/D-引脚阻抗(正常值45Ω±10%) ### 四、典型错误案例 ```diff - 错误配置:dr_mode = "otg"; + 正确配置:dr_mode = "peripheral"; ``` 修改后需彻底重新编译内核: ```bash ./build.sh -k clean # 清理内核缓存 ./build.sh -k # 重新编译内核 ```
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值