| // 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 |