☰
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
