blob: a9d5dcdcaa898d1063a17ab4d2e038e2929513ea [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// Primitive input filter, with enable. Configurable number of cycles.
//
// when in reset, stored vector is zero
// when enable is false, output is input
// when enable is true, output is stored value,
// new input must be opposite value from stored value for
// #Cycles before switching to new value.
module prim_filter #(
// If this parameter is set, an additional 2-stage synchronizer will be
// added at the input.
parameter bit AsyncOn = 0,
parameter int unsigned Cycles = 4
) (
input clk_i,
input rst_ni,
input enable_i,
input filter_i,
output logic filter_o
);
logic [Cycles-1:0] stored_vector_q, stored_vector_d;
logic stored_value_q, update_stored_value;
logic unused_stored_vector_q_msb;
logic filter_synced;
if (AsyncOn) begin : gen_async
// Run this through a 2 stage synchronizer to
// prevent metastability.
prim_flop_2sync #(
.Width(1)
) prim_flop_2sync (
.clk_i,
.rst_ni,
.d_i(filter_i),
.q_o(filter_synced)
);
end else begin : gen_sync
assign filter_synced = filter_i;
end
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
stored_value_q <= 1'b0;
end else if (update_stored_value) begin
stored_value_q <= filter_synced;
end
end
assign stored_vector_d = {stored_vector_q[Cycles-2:0],filter_synced};
assign unused_stored_vector_q_msb = stored_vector_q[Cycles-1];
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
stored_vector_q <= '0;
end else begin
stored_vector_q <= stored_vector_d;
end
end
assign update_stored_value =
(stored_vector_d == {Cycles{1'b0}}) |
(stored_vector_d == {Cycles{1'b1}});
assign filter_o = enable_i ? stored_value_q : filter_synced;
endmodule