73 lines
2.7 KiB
Verilog
73 lines
2.7 KiB
Verilog
//
|
|
// Copyright 2021 Ettus Research, a National Instruments Brand
|
|
//
|
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
//
|
|
// Module: synchronizer.v
|
|
//
|
|
// Description:
|
|
//
|
|
// This is a double-synchronizer module. However, it can can implement a
|
|
// synchronizer of any depth (double, triple, etc.) and width.
|
|
//
|
|
// A double synchronizer is typically used to cross a single-bit glitch-free
|
|
// signal from one clock domain to another.
|
|
//
|
|
// *WARNING*: The input signal must be glitch-free. In other words, it should
|
|
// be driven by a register and NOT combinational logic. Otherwise
|
|
// you could capture a glitch instead of the intended signal.
|
|
//
|
|
// *WARNING*: When WIDTH is not 1, the multiple bits are not guaranteed to be
|
|
// coherent. In other words, they can arrive on the output at
|
|
// different times. This module should not usually be used to
|
|
// cross a multi-bit signal. Consider using the handshake module
|
|
// instead.
|
|
//
|
|
// When crossing between unrelated clock domains, we typically don't want the
|
|
// timing analyzer to consider the path between clock domains. To make
|
|
// writing this constraint easier, the FALSE_PATH_TO_IN parameter controls
|
|
// the name of the synchronizer_impl instance. The following XDC constraint
|
|
// is used to ignore all instances of this false path.
|
|
//
|
|
// set_false_path -to [get_pins -hierarchical -filter \
|
|
// {NAME =~ */synchronizer_false_path/stages[0].value_reg[0][*]/D}]
|
|
//
|
|
// Parameters:
|
|
//
|
|
// WIDTH : Width of the synchronizer (1 by default).
|
|
// STAGES : Number of synchronizer stages (2 by default, for a
|
|
// standard double-synchronizer).
|
|
// INITIAL_VAL : Initial value of the output register (0 by default).
|
|
// FALSE_PATH_TO_IN : Set to 1 if the input should be considered a false path
|
|
// and ignored by the timing analyzer. Set to 0 to let the
|
|
// tool analyze this path.
|
|
//
|
|
|
|
module synchronizer #(
|
|
parameter WIDTH = 1,
|
|
parameter STAGES = 2,
|
|
parameter INITIAL_VAL = 0,
|
|
parameter FALSE_PATH_TO_IN = 1
|
|
)(
|
|
input clk,
|
|
input rst,
|
|
input [WIDTH-1:0] in,
|
|
output [WIDTH-1:0] out
|
|
);
|
|
|
|
generate if (FALSE_PATH_TO_IN == 1) begin
|
|
synchronizer_impl #(
|
|
.WIDTH(WIDTH), .STAGES(STAGES), .INITIAL_VAL(INITIAL_VAL)
|
|
) synchronizer_false_path (
|
|
.clk(clk), .rst(rst), .in(in), .out(out)
|
|
);
|
|
end else begin
|
|
synchronizer_impl #(
|
|
.WIDTH(WIDTH), .STAGES(STAGES), .INITIAL_VAL(INITIAL_VAL)
|
|
) synchronizer_constrained (
|
|
.clk(clk), .rst(rst), .in(in), .out(out)
|
|
);
|
|
end endgenerate
|
|
|
|
endmodule //synchronizer
|