[FPGA] 数字IC/FPGA 跨时钟域问题详解(2)深入理解亚稳态
https://mp.weixin.qq.com/s/fEoX1NFPllI699fvXHEWuw
https://mp.weixin.qq.com/s/AjJGtSi2ez0FvLIRvN0kbw
---------------------------------------------------
在数字电路中,亚稳态问题的本质是触发器(flip-flop)因输入时序不满足而导致输出呈现 “不确定” 状态(x态)。重要的是,该未知状态的影响范围可传播至后续电路,致使整个系统瘫痪。因此,亚稳态问题可以看作是一种低容限情况下的临界状态问题。形象一点,可将电路的当前状态看作是下图的(“峰顶小球”),假定山坡和小球绝对光滑,这时的小球看似静止在山顶,但随机的扰动都可能使处于峰顶的小球滑落至图中1或2的位置。

在数字电路中,上述的非理想外因可能是温度、辐照或静电,图中的位置1和位置0则为电路输出的0/1电平,图中的小球则可类比为双稳态器件。
在FPGA或ASIC设计中,触发器(flip-flop)是一类边沿触发的双稳态器件,其能够实现状态保持、状态切换,并赋予数字电路“记忆能力”。由于组成触发器的逻辑门具备物理时延,因此触发器需要预留足够的时间窗口,确保自己能准确采样输入信号,这里的时间窗口即对应下图中的Setup Time 和 Hold Time。

哪些场景会发生亚稳态现象?
当数据或复位控制信号 处于采样窗口外时即会出现亚稳态现象,比如下面这几种情况:
- 异步信号检测
- 跨时钟域数据传输
- 复位电路
复位电路能够确保设计中的触发器(flip-flop)并置为 “确定” 状态,如SoC的上电启动地址。
若复位过程发生亚稳态,则系统在初始化阶段便发生故障。
从操作时序的角度看,复位信号的动作包括施加和释放两方面。
一、复位信号的凹陷脉宽时间
所谓的凹陷脉宽时间,指的是复位信号被施加后持续的时间段,该时间段的起点相对于时钟采样沿通常是异步的(如POR复位、按键复位),该时间段的终点为复位被撤销的时刻(如POR的电容充电后、按键被松开)。
这里的复位凹陷脉宽时间与时钟脉宽的概念相似,但由于复位信号通常会持续多个时钟周期,因此一般无需在约束中对复位信号的凹陷脉宽时间进行检查。
二、复位信号的恢复时间及撤销时间
与数据采样过程的建立时间和保持时间窗口类似,触发器对复位信号的撤销同样有着严格的时间间隔要求(相对于时钟采样沿)。

- 恢复时间(recovery time)
- 在释放复位后,能保证触发器(的输出状态)在下一个时钟采样沿恢复为置位状态的最小时间间隔。
- 撤销时间(removal time)
- 在释放复位前,能保证触发器(的输出状态)在下一个时钟采样沿稳定为复位状态的最小时间间隔。
需要注意的是,removal time和recovery time描述的都是复位信号的上升沿(即复位释放时刻)与时钟采样沿的关系。
三、不同类型复位电路及其亚稳态
3.1 异步复位
对于异步复位,对应综合出的电路及对应的RTL代码如下图所示

always @(posedge clk or negedge rst_n) begin if(!rst_n) a <= 1’b0; else a <= b; end
若异步复位的释放时间处于removal time和recovery time之间,则会导致亚稳态现象产生,即触发器的输出在经过决断时间后稳定为“不确定” 状态。

3.2 同步复位
同步复位的电路实现是将复位信号与数据相与作为触发器的输入,但在复位释放过程中仍可能会发生亚稳态现象。
always @(posedge clk) begin if(!rst_n) a <= 1’b0; else a <= b; end

如上图所示的同步复位电路,由于复位信号与数据相与,当复位释放时刻处于该触发器的数据采样窗口(Tsetup 或 Thold内),相当于数据不满足建立时间或保持时间要求,也会产生亚稳态。
除此之外,同步复位的缺点还包括:
1) 大多数逻辑器件的目标库内的DFF都只有异步复位端口,当适用同步复位时,综合器就会在寄存器的数据输入端插入组合逻辑,消耗更多的逻辑资源;
2) 同步复位依赖于时钟,如果电路中的时钟信号出现问题,无法完成复位。
3) 对复位信号的脉冲宽度有要求,必须大于指定的时钟周期,由于线路上的延迟,可能需要多个时钟周期的复位脉冲宽度,且很难保证复位信号到达各个寄存器的时序;
3.3 异步复位、同步释放
所谓的异步复位、同步释放的表现为:
- 复位施加与时钟边沿无关;
- 复位释放过程(由0->1)与时钟边沿同步;

module sync_async_reset ( input clk, input rst_i, input data_a, input data_b, output out_a, output out_b ); reg d1, d2; reg d3, d4; assign out_a = d3; assign out_b = d4; assign rst_o = d2; always @ (posedge clock, negedge rst_i) begin if (!rst_i) begin d1 <= 1'b0; end else begin d1 <= 1'b1; end end always @(posedge clock, negedge rst_i) begin if(irst_i) begin d2 <= 1'b0; end else begin d2 <= d1; end end always @ (posedge clock, negedge rst_o) begin if (!rst_o) begin d3 <= 1'b0; d4 <= 1'b0; end else begin d3 <= data_a; d4 <= data_b; end end endmodule
浙公网安备 33010602011771号