hw/ip/prim/rtl/prim_pulse_sync.sv Cov: 100%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // Pulse synchronizer: synchronizes a pulse from source clock domain (clk_src)
6: // to destination clock domain (clk_dst). Each pulse has the length of one clock
7: // cycle of its respective clock domain. Consecutive pulses need to be spaced
8: // appropriately apart from each other depending on the clock frequency ratio
9: // of the two clock domains.
10:
11: module prim_pulse_sync (
12: // source clock domain
13: input logic clk_src_i,
14: input logic rst_src_ni,
15: input logic src_pulse_i,
16: // destination clock domain
17: input logic clk_dst_i,
18: input logic rst_dst_ni,
19: output logic dst_pulse_o
20: );
21:
22: ////////////////////////////////////////////////////////////////////////////////
23: // convert src_pulse to a level signal so we can use double-flop synchronizer //
24: ////////////////////////////////////////////////////////////////////////////////
25: logic src_level;
26:
27: always_ff @(posedge clk_src_i or negedge rst_src_ni) begin
28: if (!rst_src_ni) begin
29: src_level <= 1'b0;
30: end else begin
31: src_level <= src_level ^ src_pulse_i;
32: end
33: end
34:
35: //////////////////////////////////////////////////////////
36: // synchronize level signal to destination clock domain //
37: //////////////////////////////////////////////////////////
38: logic dst_level;
39:
40: prim_flop_2sync #(.Width(1)) prim_flop_2sync (
41: // source clock domain
42: .d (src_level),
43: // destination clock domain
44: .clk_i (clk_dst_i),
45: .rst_ni (rst_dst_ni),
46: .q (dst_level)
47: );
48:
49: ////////////////////////////////////////
50: // convert level signal back to pulse //
51: ////////////////////////////////////////
52: logic dst_level_q;
53:
54: // delay dst_level by 1 cycle
55: always_ff @(posedge clk_dst_i or negedge rst_dst_ni) begin
56: if (!rst_dst_ni) begin
57: dst_level_q <= 1'b0;
58: end else begin
59: dst_level_q <= dst_level;
60: end
61: end
62:
63: // edge detection
64: assign dst_pulse_o = dst_level_q ^ dst_level;
65:
66: endmodule
67: