lib/GlitchFilter: a glitch filter to debounce input pins
This commit is contained in:
parent
07de394ddb
commit
d10a548bc1
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue