|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | // | 
|  | // Pulse synchronizer: synchronizes a pulse from source clock domain (clk_src) | 
|  | // to destination clock domain (clk_dst). Each pulse has the length of one clock | 
|  | // cycle of its respective clock domain. Consecutive pulses need to be spaced | 
|  | // appropriately apart from each other depending on the clock frequency ratio | 
|  | // of the two clock domains. | 
|  |  | 
|  | module prim_pulse_sync ( | 
|  | // source clock domain | 
|  | input  logic clk_src_i, | 
|  | input  logic rst_src_ni, | 
|  | input  logic src_pulse_i, | 
|  | // destination clock domain | 
|  | input  logic clk_dst_i, | 
|  | input  logic rst_dst_ni, | 
|  | output logic dst_pulse_o | 
|  | ); | 
|  |  | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | // convert src_pulse to a level signal so we can use double-flop synchronizer // | 
|  | //////////////////////////////////////////////////////////////////////////////// | 
|  | logic src_level; | 
|  |  | 
|  | always_ff @(posedge clk_src_i or negedge rst_src_ni) begin | 
|  | if (!rst_src_ni) begin | 
|  | src_level <= 1'b0; | 
|  | end else begin | 
|  | src_level <= src_level ^ src_pulse_i; | 
|  | end | 
|  | end | 
|  |  | 
|  | ////////////////////////////////////////////////////////// | 
|  | // synchronize level signal to destination clock domain // | 
|  | ////////////////////////////////////////////////////////// | 
|  | logic dst_level; | 
|  |  | 
|  | prim_flop_2sync #(.Width(1)) prim_flop_2sync ( | 
|  | // source clock domain | 
|  | .d      (src_level), | 
|  | // destination clock domain | 
|  | .clk_i  (clk_dst_i), | 
|  | .rst_ni (rst_dst_ni), | 
|  | .q      (dst_level) | 
|  | ); | 
|  |  | 
|  | //////////////////////////////////////// | 
|  | // convert level signal back to pulse // | 
|  | //////////////////////////////////////// | 
|  | logic dst_level_q; | 
|  |  | 
|  | // delay dst_level by 1 cycle | 
|  | always_ff @(posedge clk_dst_i or negedge rst_dst_ni) begin | 
|  | if (!rst_dst_ni) begin | 
|  | dst_level_q <= 1'b0; | 
|  | end else begin | 
|  | dst_level_q <= dst_level; | 
|  | end | 
|  | end | 
|  |  | 
|  | // edge detection | 
|  | assign dst_pulse_o = dst_level_q ^ dst_level; | 
|  |  | 
|  | endmodule |