如果需要跨时钟域处理的是一个脉冲信号,那么之前的模型和方案便不不再适合。我们将信号只持续一个时钟周期的脉冲信号称之为“标志”。如果还是采用之前的设计方案的话可能,会由于两个时钟之间的比率太大而导致该脉冲标志消失或者显示的时间太长。
一、模型
当我们需要在clk_b(clk_a)时钟下使用到clk_a(clk_b)时钟下的flagin脉冲信号时,就绪要对脉冲信号进行跨时钟域处理。依旧采用计数器,但是适合脉冲的信号转换。主要诀窍就是将脉冲转换为电平更改,这样可以轻松跨越时钟域。模型如下
二、处理模板
模块 Flag_CrossDomain( 输入 clkA, 输入 FlagIn_clkA,//这是来自clkA域的一个时钟脉冲 输入 clkB, 输出 FlagOut_clkB //从中我们在clkB域中生成一个时钟脉冲 ); reg FlagToggle_clkA; 总是 @(posedge CLKA)FlagToggle_clkA <= FlagToggle_clkA ^ FlagIn_clkA; //当标志置位时,此信号切换(clkA域) reg [2:0] SyncA_clkB; 总是 @(posedge CLKB)SyncA_clkB <= {SyncA_clkB [1:0],FlagToggle_clkA}; //现在我们跨时钟域 分配 FlagOut_clkB =(SyncA_clkB [2] ^ SyncA_clkB [1]); //并创建clkB标志 endmodule
三、拓展
现在,如果希望clk_a域接收到确认(该clk_b接收到该标志),则只需添加一个忙碌信号即可。
三、(1)拓展的模板
模块 FlagAck_CrossDomain(
输入 clkA,
输入 FlagIn_clkA,
输出 Busy_clkA,
输入 clkB,
输出 FlagOut_clkB
);
reg FlagToggle_clkA;
总是 @(posedge CLKA)FlagToggle_clkA <= FlagToggle_clkA ^(FlagIn_clkA&〜Busy_clkA);
reg [2:0] SyncA_clkB;
总是 @(posedge CLKB)SyncA_clkB <= {SyncA_clkB [1:0],FlagToggle_clkA};
reg [1:0] SyncB_clkA;
总是 @(posedge CLKA)SyncB_clkA <= {SyncB_clkA [0],SyncA_clkB [2]};
分配 FlagOut_clkB =(SyncA_clkB [2] ^ SyncA_clkB [1]);
分配 Busy_clkA = FlagToggle_clkA ^ SyncB_clkA [1];
终端模块