Close Menu
VLSI Web
  • Home
    • About Us
    • Contact Us
    • Privacy Policy
  • Digital Design
    • Digital Circuits
    • Verilog
    • VHDL
    • System Verilog
    • UVM
  • VLSI Roles
    • RTL Design
    • Design Verification
    • Physical Design
    • DFT
    • STA
  • Interviews
  • Informative
  • VLSI Forge
Instagram LinkedIn WhatsApp Telegram
Instagram LinkedIn WhatsApp Telegram
VLSI Web
  • Home
    • About Us
    • Contact Us
    • Privacy Policy
  • Digital Design
    • Digital Circuits
    • Verilog
    • VHDL
    • System Verilog
    • UVM
  • VLSI Roles
    • RTL Design
    • Design Verification
    • Physical Design
    • DFT
    • STA
  • Interviews
  • Informative
  • VLSI Forge
VLSI Web
RTL Design

Handshake Synchronisers for CDC: Four-Phase and Two-Phase Explained

Raju GorlaBy Raju Gorla6 September 2026Updated:11 October 2026No Comments5 Mins Read
Handshake synchronisers for clock domain crossing
Share
Facebook Twitter LinkedIn Email Telegram WhatsApp

The short answer: a handshake synchroniser moves a multi-bit value between clock domains safely. The source puts the data on a bus and holds it stable, then raises a request. The request is synchronised into the destination, which samples the now-stable data and raises an acknowledge. The acknowledge is synchronised back to the source, which only then changes the data. It is simple and robust, but slow, so it suits occasional transfers rather than data streams.

Handshakes are the go-to answer when you need to send a configuration word, a status value or an occasional command across a clock boundary. They are also a favourite interview topic. Here is how they work, with Verilog you can use.

  1. Why a handshake is needed
  2. The four-phase handshake
  3. Verilog example
  4. Two-phase vs four-phase
  5. When to use something else

Table of Contents

  • Part 1: Why a handshake is needed
  • Part 2: The four-phase handshake
  • Part 3: Verilog example
  • Part 4: Two-phase vs four-phase
  • Part 5: When to use something else
  • FAQ
    • How many cycles does a four-phase handshake take?
    • Why must data be stable before req rises?
    • Is a handshake the same as valid/ready?
    • How do I verify a handshake?

Part 1: Why a handshake is needed

You cannot synchronise a multi-bit bus bit by bit, because each bit may resolve on a different cycle and the destination may see a value that was never sent. The handshake avoids this by keeping the data completely stable while it is sampled, and synchronising only single-bit control signals (req and ack). See the CDC guide for the basics of synchronisers.

Part 2: The four-phase handshake

Waveform of a four-phase req and ack handshake across two clock domains
Four phases: req rises, ack rises, req falls, ack falls.
  • Source drives the data and raises req.
  • Destination sees req_sync, captures the data (it has been stable for at least two cycles), and raises ack.
  • Source sees ack_sync, drops req and may now change the data.
  • Destination sees req drop and drops ack. When the source sees ack_sync low, it can start the next transfer.

Part 3: Verilog example

// Source side (clk_a): send one word per handshake
module hs_src #(parameter W = 8) (
  input  wire         clk_a, rst_a_n,
  input  wire         send,        // request to send data_in
  input  wire [W-1:0] data_in,
  input  wire         ack_async,   // from destination
  output reg  [W-1:0] data_bus,    // held stable while req is high
  output reg          req,
  output wire         busy
);
  reg ack_s1, ack_s2;
  always @(posedge clk_a or negedge rst_a_n)
    if (!rst_a_n) {ack_s2, ack_s1} <= 2'b00;
    else          {ack_s2, ack_s1} <= {ack_s1, ack_async};

  assign busy = req | ack_s2;

  always @(posedge clk_a or negedge rst_a_n)
    if (!rst_a_n) begin
      req <= 1'b0; data_bus <= {W{1'b0}};
    end else if (!busy && send) begin
      data_bus <= data_in;          // load, then raise req
      req      <= 1'b1;
    end else if (req && ack_s2) begin
      req      <= 1'b0;             // ack seen: release
    end
endmodule

// Destination side (clk_b)
module hs_dst #(parameter W = 8) (
  input  wire         clk_b, rst_b_n,
  input  wire         req_async,
  input  wire [W-1:0] data_bus,
  output reg          ack,
  output reg  [W-1:0] data_out,
  output reg          valid        // one-cycle pulse in clk_b
);
  reg req_s1, req_s2;
  always @(posedge clk_b or negedge rst_b_n)
    if (!rst_b_n) {req_s2, req_s1} <= 2'b00;
    else          {req_s2, req_s1} <= {req_s1, req_async};

  always @(posedge clk_b or negedge rst_b_n)
    if (!rst_b_n) begin
      ack <= 1'b0; valid <= 1'b0; data_out <= {W{1'b0}};
    end else begin
      valid <= 1'b0;
      if (req_s2 && !ack) begin
        data_out <= data_bus;       // stable: safe to sample
        ack      <= 1'b1;
        valid    <= 1'b1;
      end else if (!req_s2 && ack) begin
        ack <= 1'b0;
      end
    end
endmodule

Notice that data_bus is loaded one cycle before or together with req rising, and never changes while req or the synchronised ack is high.

Part 4: Two-phase vs four-phase

Four-phase (return to zero) Two-phase (toggle)
Signalling req and ack go high, then low each transfer toggles req and ack once
Speed Slower: four synchronisation trips Faster: two trips per transfer
Logic Simpler to understand and verify Needs edge detection on both sides

Four-phase is the more common choice when transfers are rare and simplicity matters most.

Part 5: When to use something else

  • For a continuous stream of data, use an asynchronous FIFO instead; a handshake takes several cycles per word.
  • For a single control bit, a two-flop or toggle synchroniser is enough.
  • For counters, use Gray code.

Practise this on VLSI Forge

I built VLSI Forge so you can write RTL in your browser, run it on a real simulator and check every signal in the waveform. Free, nothing to install.

CDC and RDC problems · RTL Design problems

FAQ

How many cycles does a four-phase handshake take?

Roughly four synchronisation delays (about two destination plus two source cycles each way), so typically around 8 to 10 cycles in total, depending on the clocks.

Why must data be stable before req rises?

Because the destination samples the data as soon as it sees the synchronised request. If the data changes then, the destination could capture a mix of old and new bits.

Is a handshake the same as valid/ready?

No. Valid/ready is a flow-control protocol within one clock domain. A CDC handshake synchronises req and ack between two unrelated clocks.

How do I verify a handshake?

Add assertions that the data bus never changes while req is high or ack has not returned, and run structural CDC checks to confirm req and ack are properly synchronised.

Share. Facebook Twitter LinkedIn Email Telegram WhatsApp
Previous ArticleClock Domain Crossing (CDC) Explained: Metastability and Synchronisers
Next Article Asynchronous FIFO Design: Gray Code Pointers, Full and Empty, with Verilog
Raju Gorla
  • Website

Related Posts

RTL Design

Low-Power Design Techniques: Clock Gating, Power Gating, Multi-Vt and UPF

12 September 2026
RTL Design

CDC Verification: Constraints, Tools and Sign-off

11 September 2026
RTL Design

Reset Domain Crossing (RDC) and Reset Synchronisers Explained

10 September 2026
Add A Comment
Leave A Reply Cancel Reply

Topics
  • Digital Circuits
  • Informative
  • Interview Questions
  • Physical Design
  • RTL Design
  • STA
  • System Verilog
  • UVM
  • Verilog
Instagram LinkedIn WhatsApp Telegram
  • About
  • Contact
  • Privacy Policy
  • VLSI Forge
  • Courses
  • Feedback
© 2026 VLSI Web

Type above and press Enter to search. Press Esc to cancel.