对于不同的时钟域要传递数据的话,需要采用一定的手段,来防止数据传递时产生亚稳态等问题
1、慢时钟域向快时钟域传递数据
module low2fast(clk,reset,asyn_in,syn_out,); input clk,reset; input asyn_in; output syn_out; reg q1,q2; always@(posedge clk or posedge reset) if(reset) q1<=2'b0; else q1<=asyn_in; always@(posedge clk or posedge reset) if(reset) q2<=2'b0; else q2<=q1; assign syn_out=!q1 & q2; endmodule
对于持续时间较短的脉冲一般情况下无法捕捉到,只有脉冲宽度较时钟周期大才可被捕捉到,该电路实际上我一般用来作为控制信号的边沿检测,此处为下降沿检测,把反相器放到q3的输出即可用来检测上升沿。
但是需要注意的是该方法只适用于单个数据的同步,如果是多位数据的话可能会出现问题:
多路数据传输的时候由于不同数据的路径不一样,因此到达寄存器输入端的时间不同,如果一个数据的到达时间满足建立时间而例外一个不满足寄存器的建立时间,则会导致数据与数据间相差一个或多个时钟。
2、快时钟域向慢时钟域传递数据
对于单个的数据:锁存反馈法
module fast2low(clk,asyn_in,syn_out);//pulse asyn_in is short than one clock time input clk; input asyn_in; output syn_out; reg q1,q2,q3; always@(posedge asyn_in or posedge q3) if(q3) q1<=0; else q1<=1; always@(posedge clk) q2<=q1; always@(posedge clk) q3<=q2; assign syn_out=!q2 & q3; endmodule
可见在同步电路的作用下,较窄的脉冲也可以被电路捕捉到。
在不同时钟域间传递数据一般不采用以上方法,因为多位数据传递时会使同步器的采样率错误率大大增加,一般采用的是异步FIFO.
跨时钟域时可以采用的方法:
1 如果时钟间存在着固定的频率倍数,这种情况下它们的相位一般具有固定关系,可以采用下 述方法处理:
1)使用高频时钟作为工作时钟,使用低频时钟作为使能信号,当功耗不作为首要因素时建议使用这种方式。
2)在仔细分析时序的基础上描述两个时钟转换处的电路。
2 如果电路中存在两个不同频率的时钟,并且频率无关,可以采用如下策略:
1)利用高频时钟采样两个时钟,在电路中使用高频时钟作为电路的工作时钟,经采后的低频时钟作为使能。
2)在时钟同步单元中采用两次同步法
3)使用握手信号
4)使用双时钟FIFO 进行数据缓冲
在构件由两个不同系统时钟控制工作的模块之间的同步模块时,应该遵守下面原则:两个采用不同时钟工作的寄存器之间不应该再出现逻辑电路,而应该仅仅是一种连接关系,这种方法有利于控制建立保持时间的满足。