fpga4fun.comwhere FPGAs are fun

Crossing clock domains 3 - Task

Getting a task done in another clock domain

If the clkA domain has a task that needs to be completed in the clkB domain, you can use the following design.

Here's one way to do it

module TaskAck_CrossDomain(
    input clkA,
    input TaskStart_clkA,
    output TaskBusy_clkA, TaskDone_clkA,

    input clkB,
    output TaskStart_clkB, TaskBusy_clkB,
    input TaskDone_clkB
);

reg FlagToggle_clkA, FlagToggle_clkB, Busyhold_clkB;
reg [2:0] SyncA_clkB, SyncB_clkA;

always @(posedge clkA) FlagToggle_clkA <= FlagToggle_clkA ^ (TaskStart_clkA & ~TaskBusy_clkA);

always @(posedge clkB) SyncA_clkB <= {SyncA_clkB[1:0], FlagToggle_clkA};
assign TaskStart_clkB = ^SyncA_clkB[2:1];
assign TaskBusy_clkB = TaskStart_clkB | Busyhold_clkB;
always @(posedge clkB) Busyhold_clkB <= TaskBusy_clkB & ~TaskDone_clkB;
always @(posedge clkB) if(TaskBusy_clkB & TaskDone_clkB) FlagToggle_clkB <= FlagToggle_clkA;

always @(posedge clkA) SyncB_clkA <= {SyncB_clkA[1:0], FlagToggle_clkB};
assign TaskBusy_clkA = FlagToggle_clkA ^ SyncB_clkA[2];
assign TaskDone_clkA = ^SyncB_clkA[2:1];
endmodule

and here's a matching simulation waveform