lib/GlitchFilter: a glitch filter to debounce input pins

This commit is contained in:
David Anderson 2024-09-09 12:47:19 -07:00
parent 07de394ddb
commit d10a548bc1
2 changed files with 106 additions and 0 deletions

30
lib/GlitchFilter.bsv Normal file
View File

@ -0,0 +1,30 @@
package GlitchFilter;
import Cntrs::*;
(* always_enabled="_write",always_ready="_read" *)
module mkGlitchFilter(Integer hysteresis, bit init_value, Reg#(bit) ifc);
Wire#(bit) in <- mkBypassWire();
UCount cnt <- mkUCount(init_value == 0 ? 0 : hysteresis, hysteresis);
Reg#(bit) out[2] <- mkCReg(2, init_value);
(* no_implicit_conditions, fire_when_enabled *)
rule incr (cnt.isLessThan(fromInteger(hysteresis)) && in == 1);
cnt.incr(1);
endrule
(* no_implicit_conditions, fire_when_enabled *)
rule decr (cnt.isGreaterThan(0) && in == 0);
cnt.decr(1);
endrule
(* no_implicit_conditions, fire_when_enabled *)
rule set_out (cnt.isEqual(0) || cnt.isEqual(fromInteger(hysteresis)));
out[0] <= cnt.isEqual(0) ? 0 : 1;
endrule
method _write = in._write;
method _read = out[1]._read;
endmodule
endpackage

76
lib/GlitchFilter_Test.bsv Normal file
View File

@ -0,0 +1,76 @@
package GlitchFilter_Test;
import Assert::*;
import StmtFSM::*;
import GlitchFilter::*;
import Testing::*;
module mkTB();
let testflags <- mkTestFlags();
let cycles <- mkCycleCounter();
let dut <- mkGlitchFilter(3, 0);
// Slight indirection to appease the compiler: GlitchFilter
// requires a write on every cycle, and with just the test FSM, the
// compiler can't prove that this is satisfied. So, give it a
// default value when the test isn't driving the input, on the
// first few cycles of the test.
Wire#(bit) pin_in <- mkDWire(0);
(* no_implicit_conditions,fire_when_enabled *)
rule push_in;
dut <= pin_in;
endrule
function Action check_dut(bit in, bit want_out);
return action
if (testflags.verbose)
$display("%0d: GlitchFilter(%0d) => %0d, want %0d", cycles.all, in, dut, want_out);
dynamicAssert(dut == want_out, "wrong GlitchFilter output");
pin_in <= in;
endaction;
endfunction
runTest(100,
mkTest("GlitchFilter", seq
// Simple 0->1 transition
check_dut(0, 0);
check_dut(1, 0);
check_dut(1, 0);
check_dut(1, 0);
check_dut(1, 1);
check_dut(1, 1);
// Simple 1->0 transition
check_dut(0, 1);
check_dut(0, 1);
check_dut(0, 1);
check_dut(0, 0);
check_dut(0, 0);
// Glitchy 0->1
check_dut(1, 0);
check_dut(1, 0);
check_dut(0, 0);
check_dut(1, 0);
check_dut(0, 0);
check_dut(1, 0);
check_dut(1, 0);
check_dut(1, 1);
check_dut(1, 1);
// Glitchy 1->0
check_dut(0, 1);
check_dut(0, 1);
check_dut(1, 1);
check_dut(0, 1);
check_dut(1, 1);
check_dut(0, 1);
check_dut(0, 1);
check_dut(0, 0);
check_dut(0, 0);
endseq));
endmodule
endpackage