Phase Aligned Clock Domain Crossing
Systems on Chip (SoCs) frequently contain integer-multiple clock domains generated by the same PLL, such as a 100 MHz peripheral bus and a 400 MHz processor. Because these clocks are phase-aligned, using standard two-stage synchronizers adds unnecessary latency and wastes area. Instead, engineers use a multicycle path constraint and a phase enable signal to safely sample data across the boundary exactly when it is stable.
The circuit transfers a 32-bit data payload and a valid signal from a slow clock domain to a fast clock domain. The module operates entirely on the fast clock (clk_fast). A phase enable signal (phase_en) is provided by the clock controller, which pulses high for exactly one fast clock cycle when the inputs from the slow domain are guaranteed to be stable.
The module must sample the input data and valid signal only when the phase enable is asserted. When valid data is sampled, the module must output the data and assert a valid output pulse for exactly one fast clock cycle. The output data must remain stable until the next valid data is sampled.
Clock edge: posedge clk_fast Reset type: Asynchronous Reset polarity: Active-low (rst_n) Output values on reset: data_out goes to 0, valid_out goes to 0.
Priority and timing rules: • valid_out must be a single-cycle pulse on clk_fast immediately following a phase_en pulse where valid_in was high. • data_out updates when phase_en is high and valid_in is high. It strictly holds its value during all other cycles.
Cycle 1: rst_n=0 → data_out=0, valid_out=0 Cycle 2: rst_n=1, phase_en=0, valid_in=1, data_in=100 → data_out=0, valid_out=0 Cycle 3: phase_en=1, valid_in=1, data_in=100 → data_out=0, valid_out=0 Cycle 4: phase_en=0, valid_in=1, data_in=100 → data_out=100, valid_out=1 Cycle 5: phase_en=0, valid_in=1, data_in=100 → data_out=100, valid_out=0 Cycle 6: phase_en=1, valid_in=0, data_in=200 → data_out=100, valid_out=0 Cycle 7: phase_en=0, valid_in=0, data_in=200 → data_out=100, valid_out=0
{ "signal": [
{ "name": "clk_fast", "wave": "p......" },
{ "name": "rst_n", "wave": "01....." },
{ "name": "phase_en", "wave": "0.10.10" },
{ "name": "valid_in", "wave": "x1...0." },
{ "name": "data_in", "wave": "x==..=.", "data": ["100", "200"] },
{},
{ "name": "valid_out","wave": "0..10.." },
{ "name": "data_out", "wave": "0..=...", "data": ["100"] }
], "head": { "text": "Phase aligned sampling without synchronizers." } }| Signal | Direction | Width | Description | |--------|-----------|-------|-------------| | clk_fast | input | 1 | Fast domain clock, positive-edge triggered | | rst_n | input | 1 | Asynchronous active-low reset | | data_in | input | 32 | Data from slow clock domain | | valid_in | input | 1 | Valid signal from slow clock domain | | phase_en | input | 1 | Phase enable; pulses high for 1 cycle when slow inputs are stable | | data_out | output | 32 | Registered data in fast clock domain | | valid_out | output | 1 | Single-cycle valid pulse in fast clock domain |
Constraints
- Do not use multi-stage synchronizers (double flopping). The latency from
phase_entovalid_outmust be exactly 1clk_fastcycle. data_outmust only update whenvalid_inis 1 during aphase_enpulse.valid_outmust assert for exactly one clock cycle per valid transfer.
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.