blob: 8bffa1d5575826803a8d7d38510fb365a9bed4e9 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Slow to fast clock synchronizer
// This module is designed to be used for efficient sampling of signals from a slow clock to a much
// faster clock.
//
// The data is captured into flops on the negative edge of the slow clock (when the data should be
// stable). Because the slow clock passes through a two-flop synchronizer, the ratio of clock speeds
// needs to be high to guarantee that the data will be stable when sampled.
//
// A ratio of at-least 10:1 in clock speeds is recommended.
module prim_sync_slow_fast #(
parameter int unsigned Width = 32
) (
input logic clk_slow_i,
input logic clk_fast_i,
input logic rst_fast_ni,
input logic [Width-1:0] wdata_i, // Slow domain
output logic [Width-1:0] rdata_o // Fast domain
);
logic sync_clk_slow, sync_clk_slow_q;
logic wdata_en;
logic [Width-1:0] wdata_q;
// Synchronize the slow clock to the fast domain
prim_flop_2sync #(.Width(1)) sync_slow_clk (
.clk_i (clk_fast_i),
.rst_ni (rst_fast_ni),
.d_i (clk_slow_i),
.q_o (sync_clk_slow));
// Register the synchronized clk
always_ff @(posedge clk_fast_i or negedge rst_fast_ni) begin
if (!rst_fast_ni) begin
sync_clk_slow_q <= 1'b0;
end else begin
sync_clk_slow_q <= sync_clk_slow;
end
end
// Find the negative edge of the synchronized slow clk
assign wdata_en = sync_clk_slow_q & !sync_clk_slow;
// Sample the slow data on the negative edge
always_ff @(posedge clk_fast_i or negedge rst_fast_ni) begin
if (!rst_fast_ni) begin
wdata_q <= '0;
end else if (wdata_en) begin
wdata_q <= wdata_i;
end
end
assign rdata_o = wdata_q;
endmodule