组合逻辑电路存在竞争冒险的风险,使用寄存器的时序逻辑电路同样存在一些不稳定态。
只包含一个触发器的寄存器不会出现输出的不稳定,包含多个触发器的寄存器会出现不稳定态。寄存器输出的不稳定态包含了若干次看似随机的中间值,实际上任意两个相邻的中间值是有一定联系的,即它们之间只发生了 1 bit 的变化。造成多触发器寄存器输出不稳定态的原因,就是组成寄存器的各个寄存器变化不一致。更为精确的描述是——由于线延迟的存在,导致时钟信号到达各个寄存器的时间可能不一样,也导致各个触发器的输出端口到信号接收端所需的时间可能不一样,再加上各个触发器的 tco 等参数不可能精确一致,所以当我们改变多触发器的输出时,就会出现不稳定态。
如果寄存器的输出用于产生同步逻辑中另一个或多个寄存器的输人,那么其不稳定态对FPGA设计的影响并不大。因为寄存器仅要求其输入在时钟有效沿时刻稳定即可(其实是在时钟有效沿附近一个比较小的范围内稳定即可),所以只要通过规范时钟信号的使用以及时序分析等手段,确保寄存器时钟有效沿到来的时刻及其需要数据稳定的时间窗口不要落人寄存器出现不稳定态的时间窗口内,就可以保证FPGA设计行为的正确性。
不过对于异步逻辑来说,不稳定态的危害就会凸显出来。
首先,如果一个寄存器的输出用于产生另一个时钟域中寄存器的输人,那么另一个时钟域的有效时钟沿几乎必定会落人不稳定态的窗口中(注意,不是每次时钟有效沿都会采样到不稳定态)。
其次,如果寄存器的输出用于产生一个电平敏感的信号,那么肯定会导致出错。例如,下图中电路的设计初衷是当计数器的输出b等于3(二进制为11)时对后续电路进行异步复位,不过很可惜,由于寄存器输出不稳定态的存在,导致后续电路在计数器的输出从1变到2(二进制为从01变到10)时,如果计数器的高位稍微先于低位发生变化,就可能发生复位。
特定情况下去除不稳定态的方法
只要能够保证再时钟有效沿时刻,寄存器的输入端与输出端的数据最多只有 1 bit 不同,就可以消除寄存器输出时的不稳定态。
格雷码(Gray code)是一种数字排序系统,其中的所有相邻整数在它们的二进制表示中仅有一位不同。
格雷码在任意两个相邻的数之间转换时,只有 1 bit 发生变化,所以它有效地避免了寄存器由一个数值到下一个数值时的不稳定态。并且由于格雷码中最大数与最小数之间也仅有 1 bit 不同,因此通常又被称为循环二进制码或者反射二进制码。
格雷码缺点,相比于自然二进制码来说,格雷码是一种无权码(自然二进制码实际上是“8421”码),因此很难直接进行比较和数学运算,所以一般都需要将采集到的以格雷码为表现形式的数据先转换成自然二进制码,再参与运算。
常用的格雷码编解码方法
-
编码(从自然二进制码到格雷码):方法是从二进制码的最右边一位(最低为)起,依次将每一位与左边一位进行异或运算,作为对应格雷码该为的值,而最左边的一位(最高位)不变。公式:
g[n] = b[n] (b-二进制码,g-格雷码)
g[i] = b[i] xor b[i+1] (n-1>= i >= 0)
-
解码(从格雷码到自然二进制码):从格雷码的左边第二位(次高位)起,将每一位与其左边的一位解吗后的值异或,作为该位解码后的值,最左边的一位(最高位)的解码结果就是它本身。公式:
b[n] = g[n]
b[i] = g[i] xor b[i+1] (n-1>= i >= 0)
可以利用格雷码来消除一些特定情况下的不稳定态。
将上文中的自然二进制计数器改为格雷码计数器,并在其输出等于格雷码“3”时给出后续电路的复位信号,则复位行为就不会出现任何问题。