diff --git a/lib/GlitchFilter.bsv b/lib/GlitchFilter.bsv new file mode 100644 index 0000000..e608dbd --- /dev/null +++ b/lib/GlitchFilter.bsv @@ -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 diff --git a/lib/GlitchFilter_Test.bsv b/lib/GlitchFilter_Test.bsv new file mode 100644 index 0000000..72b401d --- /dev/null +++ b/lib/GlitchFilter_Test.bsv @@ -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