Two Phase Handshake Protocol
Clock domain crossing (CDC) often relies on handshake protocols to pass data safely between asynchronous domains. While a four-phase handshake is robust, it wastes clock cycles returning the request and acknowledge signals to zero. High-performance systems use a two-phase (toggle) handshake where any transition on the request line indicates new data, and any transition on the acknowledge line signals completion.
The solution module acts as a unidirectional CDC bridge. On the transmit (TX) side, when tx_valid is asserted and the module is ready (tx_ready is high), it captures the 8-bit tx_data and toggles an internal request signal. This request signal crosses into the receive (RX) clock domain where it is synchronized using a standard two-flip-flop synchronizer.
The RX domain detects any edge (rising or falling) on the synchronized request, registers the captured data to rx_data, and pulses rx_valid high for exactly one rx_clk cycle. Simultaneously, the RX domain toggles an internal acknowledge signal. This acknowledge signal crosses back to the TX domain, gets synchronized, and upon edge detection, signals that the bridge is ready for the next transaction by driving tx_ready high again.
Timing and Reset Rules: • tx_clk and rx_clk are asynchronous, positive-edge triggered clocks. • tx_rst_n and rx_rst_n are asynchronous, active-low resets for their respective domains. • On tx_rst_n assertion, tx_ready becomes 1. All internal TX states and toggle signals reset to 0. • On rx_rst_n assertion, rx_valid becomes 0 and rx_data becomes 8'h00. All internal RX states and toggle signals reset to 0. • Data captured from tx_data must remain stable in the TX domain until the next transaction begins. • tx_valid must be ignored if tx_ready is 0.
Worked Trace (Idealized Clock Alignment): • Cycle 1: tx_rst_n=0 → tx_ready=1, internal tx_req=0. • Cycle 2: tx_rst_n=1, tx_valid=1, tx_data=8'hAA → tx_ready=0, internal tx_req=1 (toggled). • Cycle 3: RX domain synchronizes tx_req (first stage). • Cycle 4: RX domain synchronizes tx_req (second stage). • Cycle 5: RX domain detects edge → rx_data=8'hAA, rx_valid=1, internal rx_ack=1 (toggled). • Cycle 6: RX domain rx_valid=0. TX domain synchronizes rx_ack (first stage). • Cycle 7: TX domain synchronizes rx_ack (second stage). • Cycle 8: TX domain detects edge → tx_ready=1.
| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | tx_clk | input | 1 | TX domain positive-edge triggered clock | | tx_rst_n | input | 1 | TX domain asynchronous active-low reset | | tx_valid | input | 1 | High indicates valid data on tx_data | | tx_data | input | 8 | Data to be transferred across domains | | tx_ready | output | 1 | High indicates TX domain is ready for new data; resets to 1 | | rx_clk | input | 1 | RX domain positive-edge triggered clock | | rx_rst_n | input | 1 | RX domain asynchronous active-low reset | | rx_valid | output | 1 | Pulses high for one cycle when new data is received; resets to 0 | | rx_data | output | 8 | Received data; resets to 8'h00 |
Constraints
- The design must use exactly two clock domains; no logic may be clocked by a combination of
tx_clkandrx_clk. - Synchronizers must use two consecutive flip-flops clocked by the receiving domain's clock.
- The
tx_datapayload must not be passed through a synchronizer; it must be held stable in a register while the request toggle propagates. - Output
tx_readyresets to 1; all other outputs reset to 0. - Resets are purely asynchronous and active-low.
Topics
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.
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.