跨时钟域的设计

参考自fpga4fun.com

part 1.跨时钟域的信号

如果时钟域B需要使用来自时钟域A的信号,那么需要对这个信号进行同步。

image

如果输入信号比起时钟B来讲变化较慢,可以使用两个触发器来完成

 

   1:  module Signal_CrossDomain(
   2:      input clkA,   // we actually don't need clkA in that example, but it is here for completeness as we'll need it in further examples
   3:      input SignalIn_clkA,
   4:      input clkB,
   5:      output SignalOut_clkB
   6:  );
   7:   
   8:  // We use a two-stages shift-register to synchronize SignalIn_clkA to the clkB clock domain
   9:  reg [1:0] SyncA_clkB;
  10:  always @(posedge clkB) SyncA_clkB[0] <= SignalIn_clkA;   // notice that we use clkB
  11:  always @(posedge clkB) SyncA_clkB[1] <= SyncA_clkB[0];   // notice that we use clkB
  12:   
  13:  assign SignalOut_clkB = SyncA_clkB[1];  // new signal synchronized to (=ready to be used in) clkB domain
  14:  endmodule

image

part 2 跨时钟的Flag

当信号是一个短脉冲时

跨时钟域的设计_第1张图片

   1:  module Flag_CrossDomain(
   2:      input clkA,
   3:      input FlagIn_clkA, 
   4:      input clkB,
   5:      output FlagOut_clkB
   6:  );
   7:   
   8:  // this changes level when the FlagIn_clkA is seen in clkA
   9:  reg FlagToggle_clkA;
  10:  always @(posedge clkA) FlagToggle_clkA <= FlagToggle_clkA ^ FlagIn_clkA;
  11:   
  12:  // which can then be sync-ed to clkB
  13:  reg [2:0] SyncA_clkB;
  14:  always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};
  15:   
  16:  // and recreate the flag in clkB
  17:  assign FlagOut_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);
  18:  endmodule
跨时钟域的设计_第2张图片

   1:  module FlagAck_CrossDomain(
   2:      input clkA,
   3:      input FlagIn_clkA,
   4:      output Busy_clkA,
   5:      input clkB,
   6:      output FlagOut_clkB
   7:  );
   8:   
   9:  reg FlagToggle_clkA;
  10:  always @(posedge clkA) FlagToggle_clkA <= FlagToggle_clkA ^ (FlagIn_clkA & ~Busy_clkA);
  11:   
  12:  reg [2:0] SyncA_clkB;
  13:  always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};
  14:   
  15:  reg [1:0] SyncB_clkA;
  16:  always @(posedge clkA) SyncB_clkA <= {SyncB_clkA[0], SyncA_clkB[2]};
  17:   
  18:  assign FlagOut_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);
  19:  assign Busy_clkA = FlagToggle_clkA ^ SyncB_clkA[1];
  20:  endmodule

part3 task

跨时钟域的设计_第3张图片

   1:  module TaskAck_CrossDomain(
   2:      input clkA,
   3:      input TaskStart_clkA,
   4:      output TaskBusy_clkA, TaskDone_clkA,
   5:   
   6:      input clkB,
   7:      output TaskStart_clkB, TaskBusy_clkB,
   8:      input TaskDone_clkB
   9:  );
  10:   
  11:  reg FlagToggle_clkA, FlagToggle_clkB, Busyhold_clkB;
  12:  reg [2:0] SyncA_clkB, SyncB_clkA;
  13:   
  14:  always @(posedge clkA) FlagToggle_clkA <= FlagToggle_clkA ^ (TaskStart_clkA & ~TaskBusy_clkA);
  15:   
  16:  always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};
  17:  assign TaskStart_clkB = (SyncA_clkB[2] ^ SyncA_clkB[1]);
  18:  assign TaskBusy_clkB = TaskStart_clkB | Busyhold_clkB;
  19:  always @(posedge clkB) Busyhold_clkB <= ~TaskDone_clkB & TaskBusy_clkB;
  20:  always @(posedge clkB) if(TaskBusy_clkB & TaskDone_clkB) FlagToggle_clkB <= FlagToggle_clkA;
  21:   
  22:  always @(posedge clkA) SyncB_clkA <= {SyncB_clkA[1:0], FlagToggle_clkB};
  23:  assign TaskBusy_clkA = FlagToggle_clkA ^ SyncB_clkA[2];
  24:  assign TaskDone_clkA = SyncB_clkA[2] ^ SyncB_clkA[1];
  25:  endmodule

跨时钟域的设计_第4张图片

To move a data bus (2 bits wide or more) from one clock domain to another, we have several techniques to our disposal.
Here are a few ideas.

  1. Gray code: If the data bus is a monotonic counter (i.e. only incrementing or decrementing), we can convert it to a gray code, which has the ability to cross clock domains (under certain timing conditions).
  2. Data freeze: If the data bus is non-monotonic, use a flag to signal the other domain to capture the value (while it is frozen in the source clock domain).
  3. Data burst: If the data bus has many consecutive values that need to cross the clock domain, use an FIFO, where you push values from the source clock domain, and read back values from the other domain.

That's all folks!

你可能感兴趣的:(设计)