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