在跨时钟域设计中,最容易发生的就是发送时钟域的脉冲信号持续时间过短,这样就会产生下图的一个情况,有效脉冲刚好卡在一个bclk时钟的一个周期内,使得接收域接收不到脉冲信号。
还有一种情况就是持续的时间刚好卡在接收时钟域的建立时间和保持时间,如下图,第一个bclk上升沿的时候,不满足建立时间,而第二个bclk上升沿的时候,不满足保持时间。这样就会影响系统的运行。
所以一般设计时,我们需要保证上图的adat持续的时间足够使得bclk时钟域接收到有效脉冲。
一、开环设计
开环设计方法,一般只在对时钟控制信号有明确规定的时候用这样的设计方法。要求就是使adat信号脉冲持续时间为bclk的1.5倍以上,这样才能保证慢时钟域在采样信号的时候能够满足建立时间和保持时间,避免采样错误。
这种方法可以理解为延长adat的持续时间。
根据快时钟与慢时钟的快慢计算,假设aclk是bclk的三倍,那当aclk下接收到一个脉冲信号时,至少要将脉冲持续时间延长到4.5个aclk周期,这样才能保证bclk接收到信号。
设计代码:
reg flag0,flag1,flag2,flag3,flag4,flag5;
wire flag0a,flag12,flag34;
assign flag0a = flag_a | flag0;
assign flag12 = flag2 | flag1;
assign flag34 = flag3 | flag4;
always@(posedge aclk) //脉冲延迟电路
begin
flag0 <= flag_a;
flag1 <= flag0a;
flag2 <= flag1;
flag3 <= flag12;
flag4 <= flag3;
flag5 <= flag34;
end
wire a_to_b;
assign a_to_b = flag5 | flag34;
//b时钟域接收a时钟域的信号
always@(posedge bclk)
begin
flag_b <= a_to_b;
end
endmodule
综合的电路如图
二、闭环设计
可以理解为一种反馈式设计,我们需要将adat的一次脉冲同步到b时钟域中,将同步到b时钟域的数据再用a时钟域的同步器反馈回a时钟域中,以此来判断adat脉冲是否传输成功。
若要实现一个跨时钟域检测a时钟域的脉冲信号
输入输出:
input aclk, //a时钟
input bclk, //b时钟
input adat, //a时钟下的控制信号
output bout, //b输出
output b_pules; //检测信号,有上升沿脉冲则为1。
设计代码
reg adat1;
reg bq1_dat,bq2_dat,b_buf;
reg aq1_dat,aq2_dat;
//a时钟域中寄存adat脉冲信号寄存器
always@(posedge aclk)
if(adat == 1'b1)
adat1 <= 1'b1;
else if(aq2_dat == 1'b1)
adat1 <= 1'b0;
else
adat1 <= adat1;
//反馈回a时钟域的信号
always@(posedge aclk)
{aq2_dat,aq1_dat} <= {aq1_dat,bq2_dat};
//b时钟域同步器
always@(posedge bclk)
begin
{b_buf,bq2_dat,bq1_dat} <= {bq2_dat,bq1_dat,adat1};
end
//输出bout
assign bout = bq2_dat;
//检测是否为上升沿脉冲,
assign b_pules = (~b_buf) & bq2_dat;