.. _flag_xdomain_source: flag_xdomain Source File ======================== .. code-block:: verilog :linenos: `timescale 1ns / 1ns module flag_xdomain( input clk1, input flagin_clk1, input clk2, output flagout_clk2 ); // Step 1: generate 1-bit Gray code reg flagtoggle_clk1=0; always @(posedge clk1) if (flagin_clk1) flagtoggle_clk1 <= ~flagtoggle_clk1; // Step 2: cross clock domains wire sync1_clk2; reg_tech_cdc flagtoggle_cdc(.I(flagtoggle_clk1), .C(clk2), .O(sync1_clk2)); // Step 3: detect transitions reg sync2_clk2=0; always @(posedge clk2) sync2_clk2 <= sync1_clk2; assign flagout_clk2 = sync2_clk2 ^ sync1_clk2; // Step 4: (simulation-only) complain if this module is abused // Too many people wire data_xdomain's .gate_in(1'b1) without understanding // how the logic is supposed to work. `ifdef SIMULATE reg old_flagin=0, warning_sent=0; always @(posedge clk1) begin old_flagin <= flagin_clk1; if (flagin_clk1 & old_flagin & ~warning_sent) begin // Don't actually crash, at least not for now. $display("XXXX Warning: flag_xdomain module abuse in %m XXXX"); warning_sent <= 1; end end `endif endmodule