📖 Scenario: In digital circuits, signals often move between different clock domains. This can cause errors if not handled carefully. We will build a simple Verilog module that safely transfers a signal from one clock domain to another using a two-stage synchronizer.
🎯 Goal: Create a Verilog module that transfers a single-bit signal from a source clock domain to a destination clock domain using a two-flip-flop synchronizer to avoid metastability.
📋 What You'll Learn
Create a module named cdc_sync with inputs src_clk, dst_clk, src_signal and output dst_signal
Add two flip-flops in the destination clock domain to synchronize the src_signal
Use non-blocking assignments inside always blocks triggered by the destination clock
Output the synchronized signal as dst_signal
💡 Why This Matters
🌍 Real World
Clock domain crossing is common in hardware designs where different parts run on different clocks. Proper synchronization prevents errors and data corruption.
💼 Career
Understanding clock domain crossing is essential for FPGA and ASIC engineers to design reliable digital systems.
Progress0 / 4 steps
1
Create the module and inputs
Write a Verilog module named cdc_sync with inputs src_clk, dst_clk, and src_signal (1-bit). Also declare an output dst_signal (1-bit).
Verilog
Hint
Define the module and declare the inputs and output exactly as specified.
2
Declare internal registers for synchronization
Inside the cdc_sync module, declare two 1-bit registers named sync_ff1 and sync_ff2 to hold the synchronized signal in the destination clock domain.
Verilog
Hint
Declare two registers to hold the signal as it passes through the destination clock domain.
3
Implement the two-stage synchronizer logic
Add an always block triggered on the rising edge of dst_clk. Inside it, use non-blocking assignments to first assign sync_ff1 to src_signal, then assign sync_ff2 to sync_ff1.
Verilog
Hint
Use non-blocking assignments inside the always block triggered by dst_clk.
4
Assign the synchronized output signal
Assign the output dst_signal to the value of sync_ff2 using a continuous assignment statement.
Verilog
Hint
Use a continuous assignment to connect dst_signal to the last synchronizer flip-flop.
Practice
(1/5)
1. What is the main purpose of using a synchronizer in clock domain crossing?
easy
A. To safely transfer signals between different clock domains
B. To increase the clock frequency
C. To reduce power consumption
D. To generate a new clock signal
Solution
Step 1: Understand clock domain crossing
Signals crossing from one clock domain to another can cause timing errors if not handled properly.
Step 2: Role of synchronizers
Synchronizers, typically two flip-flops in series, help avoid metastability by safely transferring signals between different clock domains.
Final Answer:
To safely transfer signals between different clock domains -> Option A
Quick Check:
Synchronizer = Safe signal transfer [OK]
Hint: Synchronizers prevent timing errors between clocks [OK]
Common Mistakes:
Thinking synchronizers increase clock speed
Confusing synchronizers with power-saving methods
Assuming synchronizers generate clocks
2. Which Verilog code snippet correctly implements a 2-flip-flop synchronizer for a single-bit signal async_signal crossing into clk domain?
easy
A. reg sync_0, sync_1; always @(posedge clk) begin sync_1 <= async_signal; sync_0 <= sync_1; end
B. reg sync_0, sync_1; always @(posedge clk) begin sync_0 <= async_signal; sync_1 <= sync_0; end
C. reg sync_0, sync_1; always @(posedge async_signal) begin sync_0 <= clk; sync_1 <= sync_0; end
D. reg sync_0, sync_1; always @(negedge clk) begin sync_0 <= async_signal; sync_1 <= sync_0; end
Solution
Step 1: Identify correct clock edge and signal assignment
The synchronizer must sample the asynchronous signal on the positive edge of the destination clock (clk), so posedge clk is correct.
Step 2: Check flip-flop chaining order
The first flip-flop captures async_signal, the second captures the output of the first. This is correctly done as sync_0 <= async_signal; then sync_1 <= sync_0;.
Final Answer:
reg sync_0, sync_1; always @(posedge clk) begin sync_0 <= async_signal; sync_1 <= sync_0; end -> Option B
Quick Check:
Correct clock edge and flip-flop order = reg sync_0, sync_1; always @(posedge clk) begin sync_0 <= async_signal; sync_1 <= sync_0; end [OK]
Hint: Use posedge clk and chain flip-flops in order [OK]
Common Mistakes:
Using negedge instead of posedge
Swapping flip-flop assignments
Triggering on async_signal edge
3. Given the following Verilog code snippet crossing a signal data_in from clk_a domain to clk_b domain using a 2-flip-flop synchronizer, what is the expected output of data_sync after several clock cycles?
reg sync_0, sync_1;
always @(posedge clk_b) begin
sync_0 <= data_in;
sync_1 <= sync_0;
end
assign data_sync = sync_1;
medium
A. The code will cause a synthesis error
B. data_sync will always match data_in immediately
C. data_sync will never change from initial value
D. data_sync will be a delayed and synchronized version of data_in
Solution
Step 1: Understand synchronizer behavior
The 2-flip-flop synchronizer delays the asynchronous input by two clock cycles of clk_b and reduces metastability risk.
Step 2: Analyze output data_sync
data_sync reflects data_in but delayed and synchronized to clk_b domain, not immediate.
Final Answer:
data_sync will be a delayed and synchronized version of data_in -> Option D
Quick Check:
Synchronizer output = delayed synchronized signal [OK]
Hint: Synchronizer delays and syncs signals, no immediate match [OK]
Common Mistakes:
Expecting immediate signal match
Assuming no delay in synchronization
Thinking code causes synthesis error
4. Identify the problem in this Verilog code crossing a multi-bit signal data_bus[7:0] from clk_a to clk_b domain:
reg [7:0] sync_0, sync_1;
always @(posedge clk_b) begin
sync_0 <= data_bus;
sync_1 <= sync_0;
end
medium
A. The clock edge should be negedge instead of posedge
B. The code is correct and safe for multi-bit crossing
C. Multi-bit signals require handshake or FIFO, not simple flip-flop synchronizers
D. Missing reset signals causes metastability
Solution
Step 1: Recognize multi-bit signal crossing issues
Multi-bit signals crossing clock domains can cause data corruption if bits change at different times.
Step 2: Understand proper methods for multi-bit crossing
Simple flip-flop synchronizers are not safe for multi-bit buses; handshake protocols or FIFOs are needed.
Final Answer:
Multi-bit signals require handshake or FIFO, not simple flip-flop synchronizers -> Option C
Quick Check:
Multi-bit crossing needs handshake/FIFO [OK]
Hint: Use handshake or FIFO for multi-bit signals [OK]
Common Mistakes:
Assuming flip-flops alone are safe for buses
Changing clock edge without reason
Ignoring metastability risks
5. You need to transfer a 16-bit data word from clk_fast domain to clk_slow domain safely. Which method best ensures data integrity and avoids metastability?
hard
A. Use a handshake protocol with data valid and acknowledge signals
B. Directly assign the data bus without synchronization
C. Use a 2-flip-flop synchronizer on each bit individually
D. Use asynchronous reset on the data bus
Solution
Step 1: Consider multi-bit data crossing challenges
Transferring 16-bit data across clock domains risks partial updates and metastability if not handled properly.
Step 2: Evaluate synchronization methods
Using handshake protocols with valid and acknowledge signals ensures complete and safe data transfer between different clock domains.
Final Answer:
Use a handshake protocol with data valid and acknowledge signals -> Option A