一、前言
当单bit信号由快时钟域传递给慢时钟域时,快时钟域的异步信号最小可为快时钟信号的一个时钟周期脉冲,快时钟域的单时钟周期脉冲长度小于慢时钟域的时钟周期,很有可能该脉冲信号在慢时钟域的两个时钟上升沿之间,导致该脉冲没有被慢时钟域采集到,从而导致信号数据丢失。
因此与单bit信号从慢时钟域到快时钟域直接打两拍不同,单bit信号从快时钟域到慢时钟域还需要特殊的处理。
二、脉冲同步器
脉冲同步器的原理为将快时钟域的脉冲拓展为电平信号,使得该电平的宽度大于慢时钟域的时钟周期,从而可以使用两级同步器进行同步,然后在同步后的时钟域进行脉冲恢复,从而完成将信号(尤其是脉冲信号)从快时钟域传递到慢时钟域。
脉冲同步器的电路结构如上图所示。
在快时钟域,待同步信号低电平,寄存器Q端输出保持不变,待同步信号高电平时,寄存器的输出取反。在慢时钟域,首先进行两级寄存器同步,接着通过双边沿检测电路将脉冲信号恢复出来。
该电路具有如下特点:
1.该电路只能传递脉冲信号(也还能传递一直是0的信号,只不过工程意义不大),对于输入信号一直是1,或是只有0到1阶跃信号,只有1到0的变化的信号均无法正确传输;
2.该电路将输入端的脉冲传输给慢时钟域,无论输入端的脉冲有多宽,都只能在慢时钟域恢复成一个时钟周期宽度的脉冲;
3.输入信号的脉冲之间间隔要大于1倍的慢时钟周期,否则连着的两个脉冲问题会在慢时钟域合并为一个脉宽为2个慢时钟周期的脉冲,导致丢失一个脉冲。
三、脉冲同步器代码
`timescale 1ns/1ns
module pulse_detect(
input clk_fast ,
input clk_slow ,
input rst_n ,
input data_in ,
output dataout
);
//第一部分,脉冲电平转换
reg data_in_r;
always@(posedge clk_fast or negedge rst_n)begin
if(~rst_n)
data_in_r <= 1'b0;
else if(data_in)
data_in_r <= ~data_in_r;
else
data_in_r <= data_in_r;
end
//第二部分,两级同步
reg data_in_rt0,data_in_rt1;
always@(posedge clk_slow or negedge rst_n)begin
if(~rst_n) begin
data_in_rt0 <= 1'b0;
data_in_rt1 <= 1'b0;
end
else begin
data_in_rt0 <= data_in_r;
data_in_rt1 <= data_in_rt0;
end
end
//第三部分,电平转换脉冲(边沿检测)
reg data_in_m;
always@(posedge clk_slow or negedge rst_n)begin
if(~rst_n)
data_in_m <= 1'b0;
else
data_in_m <= data_in_rt1;
end
assign dataout = data_in_m ^ data_in_rt1;
endmodule