CodiodeCodiode
Home
Problem Solving
Skill Tracks
My Assignments
Contests
Leaderboard
Community
Settings
Codiode/Problems/Sequential Logic

Full Four Phase Handshake Protocol

HardVerilog / SystemVerilogBuild

Passing multi bit data or critical control signals across asynchronous clock domains without a FIFO requires a robust synchronization mechanism. A full four phase handshake guarantees safe data transfer regardless of the frequency ratio between the source and destination clocks. By strictly verifying the transition of request and acknowledge signals in both directions, the system prevents data corruption and metastability even when the clock frequencies drift or change dynamically.

The module acts as a bridge between a source clock domain and a destination clock domain. The source domain receives an 8-bit data payload and a start pulse. Upon receiving the start pulse, the source FSM captures the data, drives it to the destination, and asserts a request signal (cdc_req). The destination domain synchronizes this request, captures the data, asserts an acknowledge signal (cdc_ack), and pulses a valid signal for exactly one cycle. The source domain synchronizes the acknowledge, deasserts the request, and waits. Finally, the destination domain sees the deasserted request, deasserts the acknowledge, and the source domain returns to an idle state ready for the next transfer.

  • Clock edges: posedge clk_src and posedge clk_dst
  • Reset type: Asynchronous
  • Reset polarity: Active low (rst_src_n and rst_dst_n)
  • Output reset values: src_ready resets to 1; all other outputs reset to 0
  • Data stability: src_data is guaranteed to be stable when src_start is asserted; internal captured data must remain stable while crossing domains

Cycle 1: rst_src_n=0, rst_dst_n=0 → src_ready=1, cdc_req=0, cdc_ack=0, dst_valid=0 Cycle 2: rst_src_n=1, rst_dst_n=1, src_start=1, src_data=8'hA5 → src_ready=0, cdc_req=1 Cycle 3: cdc_req=1 propagates through destination synchronizer → dst_data=8'hA5, dst_valid=1, cdc_ack=1 Cycle 4: dst_valid=0 (pulses for one cycle only); cdc_ack remains 1 Cycle 5: cdc_ack=1 propagates through source synchronizer → cdc_req=0 Cycle 6: cdc_req=0 propagates through destination synchronizer → cdc_ack=0 Cycle 7: cdc_ack=0 propagates through source synchronizer → src_ready=1

flowchart LR
    S_IDLE((S_IDLE)) -->|src_start=1| S_REQ
    S_REQ((S_REQ)) -->|sync_ack=1| S_WAIT
    S_WAIT((S_WAIT)) -->|sync_ack=0| S_IDLE
    D_IDLE((D_IDLE)) -->|sync_req=1| D_ACK
    D_ACK(["D_ACK ★"]):::out -->|sync_req=0| D_IDLE
    classDef out fill:#6C5CE7,stroke:#5B4FE8,color:#fff
{ "signal": [
  { "name": "clk_src",   "wave": "p..........." },
  { "name": "src_start", "wave": "010........." },
  { "name": "src_ready", "wave": "10.........1" },
  { "name": "cdc_req",   "wave": "0.1.....0..." },
  {},
  { "name": "clk_dst",   "wave": "p..........." },
  { "name": "cdc_ack",   "wave": "0...1.....0." },
  { "name": "dst_valid", "wave": "0...10......" },
  { "name": "dst_data",  "wave": "=.==........", "data": ["0", "8'hA5"] }
], "head": { "text": "Four phase handshake sequence across clock domains." } }

| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk_src | input | 1 | Source domain clock | | rst_src_n | input | 1 | Source domain active low asynchronous reset | | clk_dst | input | 1 | Destination domain clock | | rst_dst_n | input | 1 | Destination domain active low asynchronous reset | | src_data | input | 8 | Data payload to transfer | | src_start | input | 1 | Pulse to initiate transfer; valid only when src_ready is 1 | | src_ready | output | 1 | High when source FSM is idle and ready for new data; resets to 1 | | cdc_req | output | 1 | Cross domain request signal driven by source domain | | cdc_ack | output | 1 | Cross domain acknowledge signal driven by destination domain | | dst_data | output | 8 | Data payload captured in destination domain; holds value between transfers | | dst_valid | output | 1 | Single cycle pulse in destination domain indicating dst_data is valid |

Constraints

  • The cdc_req and cdc_ack signals must be synchronized using exactly two flip flops in their respective receiving domains
  • The dst_valid signal must assert for exactly one clk_dst cycle per transfer
  • The source domain FSM must not assert cdc_req for a new transfer until the synchronized acknowledge signal is completely deasserted to 0
  • Data must be captured by the destination domain only on the cycle the synchronized request transitions from 0 to 1
  • All domain specific sequential logic must be clocked by its respective domain clock and reset by its respective domain reset

Topics

FSMClock Domain CrossingSynchronizationHandshake

Solve this problem

Write the module in Verilog, SystemVerilog or VHDL. Your submission is compiled and simulated against a real testbench — you get the waveform back, not a stored answer.

This problem is part of Codiode Pro. The statement above is free to read.

Sign in to solveSee what Pro unlocks

The circuit builder and code editor need a desktop screen. On a phone, read the problem here and open it on a laptop to solve.

Related problems

  • Basic D Flip FlopEasy
  • Debug: Missing Edge in Sensitivity ListMedium
  • Read After Write Hazard DetectionEasy
  • Parameterized Interface with ModportsHard
  • Struct Array PipelineHard
  • T Flip Flop from D Flip Flop TemplateEasy
  • Recursive Generate Reduction TreeHard
  • Four Stage Shift RegisterEasy

Browse all problems · Learning tracks