时钟glich在后仿

项目场景:

时钟分频器支持一分频,此一分频使用CKMUX产生,当divider配置为1时,分频器产生的时钟为输入时钟,否则为寄存器产生的时钟。

问题描述:

时钟分频器的divider默认为1分频,功能验证通过,当divider配置为2分频或者其它分频时,分频器的时钟会产生glitch。初始认为,glitch造成时钟驱动的寄存器的时序错误,即setuphold violation,导致寄存器的Q端输出为“x”态,导致仿真无法进行。后续debug发现,glitch时钟驱动的寄存器D端无数据变化,即一起保持不变,因此不存在采样数据错误的问题,什么导致不定态出现?

原因分析:

在后仿中,最常见的不定态,通常出现在几种情况:一种是,异步时钟之间的数据交互,主要体现在同步处理的datapath上,比如两拍延迟之中的第一拍,或者异步fifo的格雷码转换第一拍,这种通常的处理方法是异步处理的第一拍做notiming处理。另外一种是,同步电路中,出现的setuphold violation,引起寄存器采样错误,导致不定态出现。但是现在寄存器的D端并没有变化,因此没有setuphold问题。仔细看log,应该有类似“width”的violation log,此glitch驱动的寄存器才会出现不定态,寻找lib的相关地方,发现有PWM检查。因此正是glitch加在了寄存器的CK端,导致MPW的violation,因此寄存器输出为不定态。

在这里插入图片描述

解决方案:

首先,时钟上glitch是一种危险的行为,它可能导致后续所有fanout的寄存器处于一种不确定状态。使寄存器处于确定状态,最佳办法就是使寄存器处于(异步)复位状态,因此即使CK端出现glitch,复位仍然有效,寄存器状态仍然可控;或者在glitch发生之后,有足够时间复位此时钟fanout的所有寄存器。

其次,在glitch出现之前,在时钟之后的CG使能,即保证时钟不传递到寄存器,也可以解决。前提是CG在clk switch之后。

结论:

glitch除了引起频率变化导致setuphold violation之外,还有可能由于MPW的造成寄存器的不稳定。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hier ist eine mögliche Implementierung des Konstruktors und Destruktors für die Klasse cData: ```c++ class cData { private: double *data; int size; public: cData() : data(nullptr), size(0) {} ~cData() { if (data != nullptr) { delete[] data; } } bool setSize(int newSize) { if (newSize <= 0) { return false; } double *newData = new double[newSize]; if (newData == nullptr) { return false; } // Copy old data into new data int copySize = std::min(size, newSize); // Only copy up to the smaller size for (int i = 0; i < copySize; i++) { newData[i] = data[i]; } // Clean up old data if (data != nullptr) { delete[] data; } // Set new data and size data = newData; size = newSize; return true; } bool setValue(int index, double value) { if (index < 0 || index >= size) { return false; } data[index] = value; return true; } double getValue(int index) { if (index < 0 || index >= size) { return 0.0; // Or throw an exception } return data[index]; } }; ``` Der Konstruktor initialisiert die Datenmitglieder `data` und `size`. Hier wird `data` auf `nullptr` gesetzt, um anzuzeigen, dass der Vektor derzeit leer ist. Der Destruktor prüft, ob `data` nicht `nullptr` ist, um sicherzustellen, dass es etwas gibt, das freigegeben werden muss. Wenn ja, wird das Array mit `delete[]` freigegeben. `setSize()` ändert die Größe des Vektors. Es überprüft, ob die neue Größe gültig ist und ob es genug Speicher gibt, um das neue Array zu erstellen. Wenn ja, wird das alte Array in das neue Array kopiert (nur so viele Elemente wie möglich), das alte Array wird freigegeben und das neue Array wird dem Datenmitglied `data` zugewiesen. `setValue()` setzt den Wert an einer bestimmten Position im Vektor. `getValue()` gibt den Wert an einer bestimmten Position im Vektor zurück. Es gibt 0.0 zurück, wenn der Index ungültig ist (oder Sie können auch eine Ausnahme werfen).
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值