blob: 713bf5a651c39236848f1b93f2ac4332505c4cac [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Handle clock manager bypass requests
module clkmgr_byp import clkmgr_pkg::*; import lc_ctrl_pkg::lc_tx_t; # (
parameter int NumDivClks = 1
) (
input clk_i,
input rst_ni,
input lc_tx_t en_i,
input lc_tx_t byp_req_i,
input lc_tx_t step_down_req_i,
output lc_tx_t ast_clk_byp_req_o,
input lc_tx_t ast_clk_byp_ack_i,
input lc_tx_t lc_clk_byp_req_i,
output lc_tx_t lc_clk_byp_ack_o,
input [NumDivClks-1:0] step_down_acks_i,
output lc_tx_t step_down_req_o
);
lc_tx_t reg_clk_byp_req;
lc_tx_t on_val;
assign on_val = lc_ctrl_pkg::On;
// Generate qualified reg clk bypass request
for (genvar i = 0; i < $bits(lc_tx_t); i++) begin : gen_clk_byp
prim_buf u_buf (
.in_i(on_val[i] ? byp_req_i[i] & en_i[i] : byp_req_i[i] | en_i[i]),
.out_o(reg_clk_byp_req[i])
);
end
lc_tx_t ast_clk_byp_req;
always_comb begin
ast_clk_byp_req = lc_ctrl_pkg::Off;
if (lc_clk_byp_req_i == lc_ctrl_pkg::On) begin
ast_clk_byp_req = lc_ctrl_pkg::On;
end else if (reg_clk_byp_req == lc_ctrl_pkg::On) begin
ast_clk_byp_req = lc_ctrl_pkg::On;
end
end
prim_lc_sender u_clk_byp_req (
.clk_i,
.rst_ni,
.lc_en_i(ast_clk_byp_req),
.lc_en_o(ast_clk_byp_req_o)
);
lc_tx_t ast_clk_byp_ack;
prim_lc_sync u_rcv (
.clk_i,
.rst_ni,
.lc_en_i(ast_clk_byp_ack_i),
.lc_en_o(ast_clk_byp_ack)
);
// if switch request came from software, let software dictate whether to step down
assign step_down_req_o =
lc_clk_byp_req_i == lc_ctrl_pkg::On ? ast_clk_byp_ack :
reg_clk_byp_req == lc_ctrl_pkg::On ? ast_clk_byp_ack & step_down_req_i :
lc_ctrl_pkg::Off;
// only ack the lc_ctrl if it made a request.
prim_lc_sender u_send (
.clk_i,
.rst_ni,
.lc_en_i((&step_down_acks_i) ? lc_clk_byp_req_i : lc_ctrl_pkg::Off),
.lc_en_o(lc_clk_byp_ack_o)
);
endmodule // clkmgr_byp