FPGA设计中的跨时钟域问题

摘要:
在第一个设计中,我们假设与CLKA和CLKB的时钟相比,信号的变化非常慢。典型的方法是使用两个触发器将信号同步到CLKB。我们仍然使用同步器,但它是为FLAG信号设计的。诀窍是先将FLAG信号转换为电平信号,然后使用两个触发器进行同步。

转自:http://blog.163.com/sunhuifxd@126/blog/static/55859443201010131042581

跨时钟域问题

在一个FPGA设计中可能会用到多个时钟,每个时钟在FPGA内部形成一个时钟域,如果在一个时钟域中产生的信号需要在另一个时钟域中使用,那么需要特别小心!

到另一个时钟域的信号

假设一个在时钟域CLKA产生的信号需要在时钟域CLKB中使用,那么它需要首先与时钟域CLKB“同步”,也就是说需要一个“同步”设计,它接受来自时钟域CLKA的信号,并产生一个新的信号输出到CLKB。

FPGA设计中的跨时钟域问题(转) - huihui - 辉辉的博客
在第一个设计中,我们假设信号的改变相对于时钟域CLKA和CLKB的时钟都是很慢的,典型的做法是使用两个触发器来将信号同步到时钟域CLKB。(具体原因参考随后我翻译的blog)
module signal_crossdomain(
        clka,
        signalin,
        clkb,
        signalout
        );
input clka;
input signalin;
input clkb;
output signalout;
//信号的跨时钟域传递,使用两个移位寄存器来进行“同步”
reg [1:0] synca_clkb;
always @(posedge clkb) synca_clkb[0] <= signalin;   //注意使用的是clkb
always @(posedge clkb) synca_clkb[1] <= synca_clkb[0];  //注意我们使用的是clkb
assign signalout = synca_clkb[1];
endmodule
由于这两个触发器的使用,会使得信号有一定的延迟,例如下图就是使用两个触发器同步时代波形图:
FPGA设计中的跨时钟域问题(转) - huihui - 辉辉的博客
到另一个时钟域的标志(FLAG)
好了,假设需要跨时钟域传递的信号是一个宽度仅为1个时钟周期的脉冲(称为标志信号FLAG),那么前面的设计可能就不会正常工作了,因为这个FLAG很可能被CLKB错过或者延长(变成多个FLAG),具体是由CLKB的速度决定的。
我们仍然使用一个同步器,但是它是为FLAG信号设计的
FPGA设计中的跨时钟域问题(转) - huihui - 辉辉的博客
 设计的技巧是先把FLAG信号转换为电平信号,然后再使用两个触发器来同步。
module Flag_CrossDomain(
        rst,
        clkA, 
        FlagIn_clkA, 
        clkB, 
        FlagOut_clkB
        );
// 时钟域 clkA 的信号:clkA, FlagIn_clkA;  
// 时钟域 clkB 的信号input clkB;     
input rst;
input clkA;
input FlagIn_clkA;
input clkB;
output FlagOut_clkB;
reg FlagToggle_clkA;
reg [2:0] SyncA_clkB;
always @(posedge clkA or negedge rst)
begin
        if(!rst) begin
                FlagToggle_clkA <= 1'b0;
        end
        else if(FlagIn_clkA) begin
                FlagToggle_clkA <= ~FlagToggle_clkA;  // 当FLAG来到时,改变电平状态
        end
end
doalways @(posedge clkB or negedge rst)
begin
        if(!rst) begin
                SyncA_clkB <= 3'd0;
        end
        else begin
                SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};   // 与clk B同步
        end
end
assign FlagOut_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);  // 重生FLAG信号
endmodule
得到的仿真结果如下:

FPGA设计中的跨时钟域问题(转) - huihui - 辉辉的博客

这种方法来实现不同时钟域之间信号传递会存在一些问题,如当输出信号的两个脉冲之间的clkb需要满足有两个上升沿,负责会出现问题,如下图所示:

FPGA设计中的跨时钟域问题(转) - huihui - 辉辉的博客

这样我们可以在clkA域中设置一个busy信号来指示clkB域正在处理信号,这时候clkA域中再输入信号是无效的:

FPGA设计中的跨时钟域问题(转) - huihui - 辉辉的博客

 

module FlagAck_CrossDomain(      clkA, FlagIn_clkA, Busy_clkA,       clkB, FlagOut_clkB);  // clkA domain signals  
input clkA, FlagIn_clkA;  
output Busy_clkA;  // clkB domain signals  
input clkB;  
output FlagOut_clkB;  
reg FlagToggle_clkA;  
reg [2:0] SyncA_clkB;  
reg [1:0] SyncB_clkA; 
always @(posedge clkA) 
if(FlagIn_clkA & ~Busy_clkA) 
FlagToggle_clkA <= ~FlagToggle_clkA;  
always @(posedge clkB) 
SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};  
always @(posedge clkA) 
SyncB_clkA <= {SyncB_clkA[0], SyncA_clkB[1]};  
assign FlagOut_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);  
assign Busy_clkA = FlagToggle_clkA ^ SyncB_clkA[1];  
endmodule

也可以在clkB中也添加一个完成信号

FPGA设计中的跨时钟域问题(转) - huihui - 辉辉的博客

module TaskAck_CrossDomain(
    clkA, TaskStart_clkA, TaskBusy_clkA, TaskDone_clkA, 
    clkB, TaskStart_clkB, TaskBusy_clkB, TaskDone_clkB);
// clkA domain signals
input clkA;
input TaskStart_clkA;
output TaskBusy_clkA, TaskDone_clkA;
// clkB domain signals
input clkB;
output TaskBusy_clkB, TaskStart_clkB;
input TaskDone_clkB;
reg FlagToggle_clkA, Busyhold_clkB; reg [2:0] SyncA_clkB, SyncB_clkA;
always @(posedge clkA) if(TaskStart_clkA & ~TaskBusy_clkA) FlagToggle_clkA <= ~FlagToggle_clkA;
always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};
assign TaskStart_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);
assign TaskBusy_clkB = TaskStart_clkB | Busyhold_clkB;
always @(posedge clkB) Busyhold_clkB <= ~TaskDone_clkB & TaskBusy_clkB;
always @(posedge clkA) SyncB_clkA <= {SyncB_clkA[1:0], Busyhold_clkB ^ SyncA_clkB[2]};
assign TaskBusy_clkA = FlagToggle_clkA ^ SyncB_clkA[2];
assign TaskDone_clkA = SyncB_clkA[2] ^ SyncB_clkA[1];
endmodule
input
 clkB;
output TaskBusy_clkB, TaskStart_clkB;
input TaskDone_clkB;
reg FlagToggle_clkA, Busyhold_clkB; reg [2:0] SyncA_clkB, SyncB_clkA;
always @(posedge clkA) if(TaskStart_clkA & ~TaskBusy_clkA) FlagToggle_clkA <= ~FlagToggle_clkA;
always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};
assign TaskStart_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);
assign TaskBusy_clkB = TaskStart_clkB | Busyhold_clkB;
always @(posedge clkB) Busyhold_clkB <= ~TaskDone_clkB & TaskBusy_clkB;
always @(posedge clkA) SyncB_clkA <= {SyncB_clkA[1:0], Busyhold_clkB ^ SyncA_clkB[2]};
assign TaskBusy_clkA = FlagToggle_clkA ^ SyncB_clkA[2];
assign TaskDone_clkA = SyncB_clkA[2] ^ SyncB_clkA[1];
endmodule
input
 clkB;
output TaskBusy_clkB, TaskStart_clkB;
input TaskDone_clkB;
reg FlagToggle_clkA, Busyhold_clkB; reg [2:0] SyncA_clkB, SyncB_clkA;
always @(posedge clkA) if(TaskStart_clkA & ~TaskBusy_clkA) FlagToggle_clkA <= ~FlagToggle_clkA;
always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};
assign TaskStart_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);
assign TaskBusy_clkB = TaskStart_clkB | Busyhold_clkB;
always @(posedge clkB) Busyhold_clkB <= ~TaskDone_clkB & TaskBusy_clkB;
always @(posedge clkA) SyncB_clkA <= {SyncB_clkA[1:0], Busyhold_clkB ^ SyncA_clkB[2]};
assign TaskBusy_clkA = FlagToggle_clkA ^ SyncB_clkA[2];
assign TaskDone_clkA = SyncB_clkA[2] ^ SyncB_clkA[1];
endmodule
Links
To learn what is metastablity and why two flip-flops are used to cross clock domains, follow these links. 
What Is Metastability? and Interfacing Two Clock Domains from World of ASIC. 
Crossing the abyss from the EDN magazine. 
Digital Logic Metastability from interfacebus.com 
Metastability in electronics from Wikipedia. 
Synchronization in Digital Logic Circuits from Ryan Donohue. 

That's all folks!
Have fun crossing clock domains

 源地址:http://blog.xdnice.com/blog6i75177.html

03/

免责声明:文章转载自《FPGA设计中的跨时钟域问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Android 隐藏输入法键盘ORM框架:Entity Framework下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

深入理解CPU和异构计算芯片GPU/FPGA/ASIC (上篇)

随着互联网用户的快速增长,数据体量的急剧膨胀,数据中心对计算的需求也在迅猛上涨。诸如深度学习在线预测、直播中的视频转码、图片压缩解压缩以及HTTPS加密等各类应用对计算的需求已远远超出了传统CPU处理器的能力所及。摩尔定律失效的今天,关注“新“成员(GPUFPGAASIC)为数据中心带来的体系架构变革,为业务配上一台动力十足的发动机。 1 异构计算:WHY...

MPEG2-TS音视频同步原理(PCR dts pts)

一、引言MPEG2系统用于视音频同步以及系统时钟恢复的时间标签分别在ES,PES和TS这3个层次中。在TS 层, TS头信息包含了节目时钟参考PCR(Program Clock Reference),用于恢复出与编码端一致的系统时序时钟STC(System Time Clock)。 在PES层, 在PES头信息里包含有表示时间戳PTS(Presentati...

(stm32f103学习总结)—RTC独立定时器—实时时钟实验

一、STM32F1 RTC介绍 1.1 RTC简介   STM32 的实时时钟( RTC)是一个独立的定时器。 STM32 的 RTC 模 块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的 功能。修改计数器的值可以重新设置系统当前的时间和日期。 RTC模块和时钟配置是在后备区域,无论器件状态如何(运行模式、 低功耗模式或处于复位状态),只要...

Synplify9.6.2破解(转帖)

Synplify9.6.2破解(转帖)   转载自:http://www.cnblogs.com/mark-sun/archive/2012/02/26/2368773.html Abstract本文介紹如何破解Synplify Pro 9.6.2。 IntroductionStep 1:安裝Synplify Pro Step 2:選擇Float...

NTP 协议介绍

NTP协议 NTP(Network Time Protocol,网络时间协议)是由RFC 1305定义的时间同步协议,用来在分布式时间服务器和客户端之间进行时间同步。NTP基于UDP报文进行传输,使用的UDP端口号为123。使用NTP的目的是对网络内所有具有时钟的设备进行时钟同步,使网络内所有设备的时钟保持一致,从而使设备能够提供基于统一时间的多种应用。...

【FPGA总线篇章一】FPGA大话总线之AXI总线

欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章 11 在介绍AXI之前,先简单说一下总线、接口以及协议的含义 总线、接口和协议,这三个词常常被联系在一起,但是我们心里要明白他们的区别。 总线是一组传输通道,是各种逻辑器件构成的传输数据的通道,一般由由数据线、地址线、控制线等构成。 接口是一种连接标准,又常常被称之为物理接口。 协议是传输数...