From aba62d96c9f7e49494cc9bc584f2a59036e89149 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Thu, 18 May 2017 15:13:45 +0200 Subject: [PATCH] util_cdc: Add multi-bit data synchronization module The sync_data module can be used to continuously transfer multi-bit signals like status signals safely from the source to the destination clock domain. A transfer takes 2 source and 2 destination clock cycles. It is not guaranteed that all transitions on the source side will be visible on the target side if the signal is changing faster than this. Logic using this block should be aware of it. The primary intention is for it to be used for slowly changing status signals. Signed-off-by: Lars-Peter Clausen --- library/util_cdc/sync_data.v | 83 ++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 library/util_cdc/sync_data.v diff --git a/library/util_cdc/sync_data.v b/library/util_cdc/sync_data.v new file mode 100644 index 000000000..c0e321ff6 --- /dev/null +++ b/library/util_cdc/sync_data.v @@ -0,0 +1,83 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2014 - 2017 (c) Analog Devices, Inc. All rights reserved. +// +// Each core or library found in this collection may have its own licensing terms. +// The user should keep this in in mind while exploring these cores. +// +// Redistribution and use in source and binary forms, +// with or without modification of this file, are permitted under the terms of either +// (at the option of the user): +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory, or at: +// https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html +// +// OR +// +// 2. An ADI specific BSD license as noted in the top level directory, or on-line at: +// https://github.com/analogdevicesinc/hdl/blob/dev/LICENSE +// +// *************************************************************************** +// *************************************************************************** + +module sync_data #( + parameter NUM_OF_BITS = 1, + parameter ASYNC_CLK = 1 +) ( + input in_clk, + input [NUM_OF_BITS-1:0] in_data, + input out_clk, + output reg [NUM_OF_BITS-1:0] out_data +); + +generate +if (ASYNC_CLK == 1) begin + +wire out_toggle; +wire in_toggle; + +reg out_toggle_d1 = 1'b0; +reg in_toggle_d1 = 1'b0; + +reg [NUM_OF_BITS-1:0] cdc_hold; + +sync_bits i_sync_out ( + .in(in_toggle_d1), + .out_clk(out_clk), + .out_resetn(1'b1), + .out(out_toggle) +); + +sync_bits i_sync_in ( + .in(out_toggle_d1), + .out_clk(in_clk), + .out_resetn(1'b1), + .out(in_toggle) +); + +wire in_load = in_toggle == in_toggle_d1; +wire out_load = out_toggle ^ out_toggle_d1; + +always @(posedge in_clk) begin + if (in_load == 1'b1) begin + cdc_hold <= in_data; + in_toggle_d1 <= ~in_toggle_d1; + end +end + +always @(posedge out_clk) begin + if (out_load == 1'b1) begin + out_data <= cdc_hold; + end + out_toggle_d1 <= out_toggle; +end + +end else begin + always @(*) begin + out_data <= in_data; + end +end +endgenerate + +endmodule