blob: 08a0f4b2ad93d97ced95317e1a0063dcb5fad4a3 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// This module stretches the POR
//
`include "prim_assert.sv"
module rstmgr_por #(
parameter int FilterStages = 3,
parameter int StretchCount = 32
) (
input clk_i,
input rst_ni,
input pok_i, // TODO: This should not be an actual separate port but the POR itself
// However, this cannot be done until AST integration is done.
output logic rst_no
);
localparam int CtrWidth = $clog2(StretchCount+1);
logic rst_root_n;
logic [FilterStages-1:0] rst_filter_n;
logic rst_stable;
logic rst_clean_n;
logic [CtrWidth-1:0] cnt;
logic cnt_en;
// sync the POR
prim_flop_2sync #(
.Width(1),
.ResetValue('0)
) rst_sync (
.clk_i(clk_i),
.rst_ni(rst_ni),
.d_i(1'b1),
.q_o(rst_root_n)
);
// filter the POR
always_ff @(posedge clk_i or negedge rst_root_n) begin
if (!rst_root_n) begin
rst_filter_n <= '0;
end else if (pok_i) begin // once AST is in, this conditional should not be here.
rst_filter_n <= {rst_filter_n[0 +: FilterStages-1], 1'b1};
end
end
// The stable is a vote of all filter stages.
// Only when all the stages agree is the reset considered stable and count allowed.
assign rst_clean_n = rst_filter_n[FilterStages-1];
assign rst_stable = &rst_filter_n;
assign cnt_en = rst_stable & !rst_no;
// stretch the POR
always_ff @(posedge clk_i or negedge rst_clean_n) begin
if (!rst_clean_n) begin
cnt <= '0;
rst_no <= '0;
end else if (!rst_stable) begin
cnt <= '0;
rst_no <= '0;
end else if (cnt_en && cnt == StretchCount) begin
rst_no <= 1'b1;
end else if (cnt_en) begin
cnt <= cnt + 1'b1;
end
end
endmodule // rstmgr_por