在基于FPGA的数字系统设计中,异步时序是指时序逻辑电路内部寄存器的时钟来自两个及以上的时钟源,如图1所示,而且时钟源之间没有确定的相位关系。 相应地,把信号从寄存器FF1传输到寄存器 FF2,称为跨时钟域传输 (Clock Domain Crossing,CDC),其中FF1称为源寄存器,FF2称为目的寄存器 。
图1 异步时序电路示例
信号在跨时钟域传输时,由于源寄存器的时钟和目的寄存器的时钟之间相位没有确定的相位关系,所以数据从源寄存器FF1发出后,有可能在任何时刻到达目的寄存器,因此无法保证能够满足目的寄存器FF2的建立时间和保持时间要求。 如果信号不能在目的寄存器的建立时间和保持时间定义的窗口内保持稳定,那么目的寄存器的输出有可能进入 非0非1 (介于VOHmin和VOLmax之间)的不确定状态,如图2所示,这个状态称为亚稳态 (metastability)。 相应的,把目的寄存器脱离亚稳态进入稳态的时间称为决断时间 (resolution time),用tmet表示。 经过决断时间后,目的寄存器的输出最终稳定到0还是1是随机的,与输入信号没有必然的关系。
图2 时序违规导致亚稳态
处于亚稳态的寄存器在决断时间前输出电压在高电平与低电平之间振荡时,可能会导致后续的数字部件作出不同的判断,可能判断为0、可能判断为1,也可能进入亚稳态,从而引发数字系统产生错误。
除了信号的跨时钟域传输外,异步时序还有另外两种情况。
第一种情况是系统复位时,无论是异步复位还是同步复位。
对于异步复位来说,复位信号如果不能在触发器的恢复时间和撤除时间窗口内保持稳定,如图3所示,那么就可能影响触发器输入数据的锁存过程而产生亚稳态。 触发器的输出在Tco后可能会进入亚稳态,最终可能稳定到0,也可能稳定到1,从而导致系统发生错误。
图3 异步复位电路及时序图
对于同步复位来说,当输入信号D为高电平时,如果复位信号不能在触发器的建立时间和保持时间定义的窗口内保持稳定,如图4所示,同样可能产生亚稳态。
图4 同步复位电路及时序图
第二种情况是系统对外部信号的采集。
对于按键和外部中断等输入信号,由于信号的作用时间不受系统时钟的控制,因此在采集过程中,外部信号可能在任何时刻发生变化,所以也无法保证满足寄存器建立时间和保持时间的要求。
综上分析,亚稳态产生的原因是 :触发器的输入信号变化不满足寄存器建立时间和保持时间的要求,或者复位信号不满足触发器恢复时间和撤除时间的要求。
亚稳态是触发器固有的特性。 在基于FPGA的数字系统设计中,主要应用三种方法减小亚稳态传播的概率 :①引入同步器来减小单bit信号亚稳态传播的概率,实现异步信号与目的时钟域的同步; ②应用异步FIFO实现多bit数据的跨时域传输; ③应用异步复位同步释放信号改善纯异步复位信号的特性,提高系统复位的可靠性。
下面分别讲述这三种方法。
01单bit信号的跨时钟域同步
单bit信号跨时钟传输产生亚稳态的原因是因为信号与目的时钟不同步,导致信号不能满足目的寄存器建立时间和保持时间的要求,从而导致寄存器不能输出正确的逻辑值。
亚稳态传播的概率与采集延迟时间之间近似为指数关系。 延迟时间越长,亚稳态传播的概率越小。 对于单bit信号的采集,减小亚稳态发生概率最简单的方法是应用由移位寄存器构成的 两级同步器(double-flop synchronizer)来延长信号的采集时间,如图5所示。 其中同步器输入的异步信号为 async_signal ,第一级完成触发器的输出为 reg1 ,第二级触发器的输出为同步信号 sync_out 。
图5 两级同步器
同步器在第一个时钟脉冲作用后,第一级触发器的输出reg1可能会产生亚稳态,但是reg1有机会在被第二级触发器锁存之前稳定下来,所以在第二个时钟脉冲作用后,输出的同步信号sync_out能够保持稳定。
需要注意的是,组合逻辑电路的输出不能直接应用同步器进行同步。 这是因为组合电路的输出可能存在竞争-冒险现象,会增加同步器中第一级触发器产生亚稳态的概率,从而影响同步器输出信号的可靠性。 所以,在跨时钟域同步之前,还需要在源时钟域先将组合电路的输出信号锁存后输出,如图5中所示,然后再进行同步。
图5所示的同步器适合于将慢时钟域的单bit信号同步到快时钟域,要求异步信号async_signal的脉冲宽度至少应维持一个同步器的时钟周期,才能保证信号在目的时钟域被采集到,输出同步信号sync_out的宽度取决于信号在目的时钟域被采集到的次数。
同步器的级数以2~3级为宜。 因为级数越多,将导致异步信号同步到目的时钟域的延迟时间越长,因此对异步信号的变化反应越慢。 对于只关心信号边沿跳变的应用场合,还可以应用同步器提取脉冲的边沿。 描述信号边沿检测电路的Verilog HDL代码参考如下:
module edge_detector (
input det_clk, // 时钟,50MHz
input rst_n, // 复位信号,低电平有效
input x_signal, // 被测信号
output wire rising_edge, // 上升沿标志,高电平有效
output wire fall_edge // 下降沿标志,高电平有效
);
// 3级同步寄存器定义
reg [0:2] sync_reg;
// 同步移存过程
always @( posedge det_clk or negedge rst_n )
if ( !rst_n )
sync_reg <= 3'b000;
else
sync_reg[0:2] <= { x_signal, sync_reg[0:1] };
// 边沿检测逻辑
assign rising_edge = sync_reg[1] & ~sync_reg[2];
assign fall_edge = ~sync_reg[1] & sync_reg[2];
endmodule
02多bit数据的跨时钟域传输
对于多bit数据,普遍的方法是应用图6所示的异步FIFO实现跨时域传输。
图6 跨时域异步FIFO结构
应用异步FIFO最关键的问题是如何判断FIFO的状态,产生空/满标志。 因为异步FIFO的读/写操作在不同的时钟域,所以无法像同步FIFO那样,通过统计存储数据的个数来产生empty和full标志。
1)异步FIFO空/满的检测方法
FIFO为空有两种情况:①FIFO复位时; ②当读指针rp追上了写指针wp,读/写指针相同时。 FIFO已满只有一种情况:当写指针wp多走了一圈, 折回来(wrapped around)追上了读指针rp,读/写指针再次相同时。
综上所述,FIFO为空和已满时读/写指针都相同。 为了区分指针相同时FIFO为空还是已满,需要在FIFO的读/写指针前再多加一个标志位来区分写指针是否比读指针多写了一圈。 所以,对于存储深度为2^n的异步FIFO,读/写指针应定义为n+1位 (标志位+n位地址),即对于深度为8的异步FIFO,需要定义4位地址指针,取值为0000~0111和1000~1111,其中最高位为折回标志,低3位为地址值。
添加了标志位后,每当读/写指针递加并越过FIFO的最后一个存储单元后,将读/写指针的最高位翻转,其余位回零。 因此,判断异步FIFO空/满的方法是:当读/写指针的所有位均相同时,说明FIFO为空; 当读/写地址的最高位不同而其余均相同时,说明写指针比读指针多走了一圈,说明FIFO已满。
2)读/写指针的同步方法
由于异步FIFO的读/写在不同的时钟域,所以还需要将读/写指针同步到另一个时钟域与写/读指针进行比较才能产生空/满标志。 但是,二进制读/写指针不能直接同步到另一个时钟域。 这是因为,当n+1位二进制读/写地址有多位同时发生变化(如地址从0111变化到1000)时,如果直接应用同步器进行同步,则可能会因不同数位亚稳态决断时间的差异而导致同步后的指针值产生中间值而造成同步后的地址发生错误。
为了解决这一问题, 一般的处理方法是,先将二进制读/写指针值转换为格雷码后再进行同步。 因为格雷码的相邻码之间只有一位发生变化,其余位不变,如表1所示,而不像二进制地址那样,存在多位同时发生变化的情况。 由于FIFO的读/写通过地址加1实现的,因而应用格雷码能够有效地避免同步后的指针产生中间值而造成地址错误。
表1 4位格雷码与二进制码比较表
将读/写地址转换为格雷码后,能不能直接应用同步后的格雷码产生空/满标志呢? 下面再进行分析。
深度为2^n的异步FIFO共有n+1位读/写指针。 设格雷码写指针用 wptr[n:0] 表示,读指针用 rptr[n:0]表示,FIFO为空用rempty表示,为满用wfull表示。
判断FIFO是否为空比较简单: 当读/写指针值完全相同时,无论用二进制指针还是用格雷码指针 。 因此,空标志产生的Verilog代码为
empty = ( rptr == wptr );
FIFO为满时二进制读/写指针的最高位不同而其余位相同。 从表1中的二进制码和格雷码的对应关系可以看出,FIFO为满时格雷码指针的最高位和次高位不同,其余位相同。 因此,基于格雷码判断FIFO已满的Verilog代码为
wfull = ( wptr[n:n-1] == ~rptr[n:n-1])&&( wptr[n-2:0] == rptr[n-2:0]);
3)跨时钟域异步FIFO的工作原理
对于图6所示的跨时钟域异步FIFO,在 写时钟域(wclk)收到写指令 (write instruction,简写为winc)时,需要根据wfull标志判断FIFO是否已满,因为FIFO已满时不能再写。 在FIFO不满的情况下,使写允许信号wclken有效,将数据wdata写入FIFO后写地址(waddr)加1,同时将格雷码写指针(wptr)同步到读时钟域与格雷码读指针(rptr)进行比较,产生rempty标志 。 在读时钟域(rclk)收到读指令(read instruction,简写为rinc)时,需要根据rempty标志判断FIFO是否为空,因为FIFO为空时不能再读。 在FIFO非空的情况下,读出数据rdata后读地址 (raddr)加1,同时将格雷码读指针(rptr)同步到写时钟域与格雷码写指针(wptr)进行比较,产生wfull标志 。
需要注意的是,由于异步FIFO通过比较读/写指针产生空/满标志,而读/写指针属于不同的时钟域,所以在比较时需要将读/写指针经过两级同步器同步到另一个时钟域,因此产生的满/空标志会延迟两个时钟周期。 如果在同步时间内有新的数据写入,则同步后的写指针一定小于当前实际的写地址,所以判断FIFO为空时实际上不一定为空,因此不会出现读空的情况。 同样的道理,如果在同步时间内有数据读出,则同步后的读指针一定小于当前的读指针,所以判断FIFO已满时不一定真满,因此不会出现写满的情况。 因此,异步FIFO空/满标志的延迟会导致空/满的判断更趋于保守,虽然会影响FIFO性能,但是不会出错。
03应用同步释放电路改善异步复位信号的特性
异步复位信号不受时钟的控制,具有直接快速的优点。 但是,当异步复位信号的释放时间不满足触发器的恢复时间和撤除时间要求时,有可能产生亚稳态。 改进方法是应用异步复位信号对系统内部所有的寄存器复位后,释放时再经过时钟脉冲进行同步。 这样做的好处是既能够应用异步复位信号对系统进行快速复位,又避免了异步复位信号直接释放时带来的亚稳态风险。
异步复位信号的同步释放电路原理如图7所示。 当异步复位信号async_rst_n有效时,能够直接将两个触发器复位,因此第二个触发器的输出rstn_sync_out=0 ,当复位信号async_rst_n释放后,两个触发器的复位信号转为无效,第一个触发器输入的高电平经过两个时钟脉冲后才能使rstn_sync_out=1,因此第二个触发器的输出rstn_sync_ out具有异步复位同步释放特性。 因此,应用rstn_sync_out作为系统的全局复位信号时,既能够对系统中的所有寄存器直接复位,又能够避免了复位信号直接释放时带来的亚稳态风险。
图7 异步复位信号同步释放原理电路
-
FPGA
+关注
关注
1629文章
21729浏览量
602960 -
寄存器
+关注
关注
31文章
5336浏览量
120224 -
触发器
+关注
关注
14文章
2000浏览量
61130 -
亚稳态
+关注
关注
0文章
46浏览量
13268 -
异步时序
+关注
关注
0文章
6浏览量
8637
发布评论请先 登录
相关推荐
评论