|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | // | 
|  | // Power Manager module to find slow clock edges | 
|  | // The clock is not used directly to avoid STA issues, instead a toggle | 
|  | // pulse is used. | 
|  |  | 
|  | `include "prim_assert.sv" | 
|  |  | 
|  | module pwrmgr_cdc_pulse ( | 
|  | input clk_slow_i, | 
|  | input clk_i, | 
|  | input rst_ni, | 
|  | input rst_slow_ni, | 
|  | input start_i, | 
|  | input stop_i, | 
|  | output logic pulse_o | 
|  | ); | 
|  |  | 
|  | logic slow_toggle_pq, slow_toggle_nq; | 
|  | logic clk_slow_pq, clk_slow_nq; | 
|  | logic clk_slow_pq2, clk_slow_nq2; | 
|  | logic toggle; | 
|  | logic valid; | 
|  |  | 
|  | // toggle pulse generated on positive edge | 
|  | always_ff @(posedge clk_slow_i or negedge rst_slow_ni) begin | 
|  | if (!rst_slow_ni) begin | 
|  | slow_toggle_pq <= 1'b0; | 
|  | end else begin | 
|  | slow_toggle_pq <= ~slow_toggle_pq; | 
|  | end | 
|  | end | 
|  |  | 
|  | // toggle pulse generated on negative edge | 
|  | always_ff @(negedge clk_slow_i or negedge rst_slow_ni) begin | 
|  | if (!rst_slow_ni) begin | 
|  | slow_toggle_nq <= 1'b0; | 
|  | end else begin | 
|  | slow_toggle_nq <= ~slow_toggle_nq; | 
|  | end | 
|  | end | 
|  |  | 
|  |  | 
|  | prim_flop_2sync # ( | 
|  | .Width(1) | 
|  | ) i_pos_sync ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .d_i(slow_toggle_pq), | 
|  | .q_o(clk_slow_pq) | 
|  | ); | 
|  |  | 
|  | prim_flop_2sync # ( | 
|  | .Width(1) | 
|  | ) i_neg_sync ( | 
|  | .clk_i, | 
|  | .rst_ni, | 
|  | .d_i(slow_toggle_nq), | 
|  | .q_o(clk_slow_nq) | 
|  | ); | 
|  |  | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | clk_slow_pq2 <= 1'b0; | 
|  | clk_slow_nq2 <= 1'b0; | 
|  | end else begin | 
|  | clk_slow_pq2 <= clk_slow_pq; | 
|  | clk_slow_nq2 <= clk_slow_nq; | 
|  | end | 
|  | end | 
|  |  | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | valid <= 1'b0; | 
|  | end else if (valid && stop_i) begin | 
|  | valid <= 1'b0; | 
|  | end else if (!valid && toggle && start_i) begin | 
|  | valid <= 1'b1; | 
|  | end | 
|  | end | 
|  |  | 
|  | // toggle is found on either positive and negative edges of clk_slow_i | 
|  | assign toggle = clk_slow_pq2 ^ clk_slow_pq | clk_slow_nq2 ^ clk_slow_nq; | 
|  | assign pulse_o = valid & toggle; | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  | endmodule // pwrmgr |