Created
September 20, 2019 17:51
-
-
Save wdevore/911b3b1c4e8e646b662d729b809a5f4d to your computer and use it in GitHub Desktop.
Verilog Pulse FSM for debouncing. Use a .pcf for tinyFPGA-B2.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FSM Event based debounce circuit - top.v | |
// | |
// The FSM should be reset prior to usage. | |
// "c" or clock should be around 100Hz = 10ms cycle or 5ms period. | |
// | |
// An excerpt from "FSB Based Digital Design Using Verilog" Chp 9. | |
// | |
// To see this verilog in action you will need at least 10 LEDs or a 10-bit | |
// bargraph and 2 switches. | |
// Your FPGA breakout board will need 12-14 pins available. | |
// -------------------------------------------------------------------------- | |
// An async switch debouncer FSM | |
// -------------------------------------------------------------------------- | |
module pulse_fsm ( | |
input S, // Active High | |
input C, | |
input Reset, | |
output Pulse | |
); | |
wire A; // Event cell = ((/B & S & /C) | (A & /B) | (A & C)) & Reset | |
wire B; // Event cell = ((A & C) | (A & B) | (B & S)) & Reset | |
wire BNot; | |
wire CNot; | |
wire a1, a2, a3; | |
wire b1, b2, b3; | |
// Note: some toolchains will issue "logic loops" as warnings. There are | |
// 6 of them in this module. | |
not N1(BNot, B); | |
not N2(CNot, C); | |
and And1(a1, S, CNot, BNot, Reset); | |
and And2(a2, BNot, A, Reset); | |
and And3(a3, C, A, Reset); | |
or Or1(A, a1, a2, a3); | |
and And4(b1, A, C, Reset); | |
and And5(b2, A, B, Reset); | |
and And6(b3, B, S, Reset); | |
or Or2(B, b1, b2, b3); | |
// Output signal | |
and And7(Pulse, A, B); | |
endmodule | |
// -------------------------------------------------------------------------- | |
// Main module | |
// -------------------------------------------------------------------------- | |
module top ( | |
output pin1_usb_dp,// USB pull-up enable, set low to disable | |
output pin2_usb_dn, | |
input pin3_clk_16mhz, // 16 MHz on-board clock | |
// pins 13-4 should be connected to 10 LEDs | |
output pin13, | |
output pin12, | |
output pin11, | |
output pin10, | |
output pin9, | |
output pin8, | |
output pin7, | |
output pin6, | |
output pin5, | |
output pin4, | |
input pin14_sdo, // Button input: Active High | |
input pin17_ss, // Reset button: Active Low | |
output pin15_sdi, // Control clock. Provided for visual inspection. | |
output pin16_sck // Pulse output used to drive FSM | |
); | |
reg [22:0] clk_1hz_counter = 23'b0; // Hz clock generation counter | |
reg clk_cyc = 1'b0; // Hz clock | |
reg[9:0] shift = 1; // 4 bit shift register that shifts at each button press | |
reg direction = 0; // Initial direction is from pin4 to pin7 | |
reg[3:0] counter = 0; | |
// 100Hz gives a 10ms/5ms cycle/period | |
// 50Hz gives a 20ms/10ms cycle/period | |
// 25Hz gives a 40ms/20ms cycle/period | |
// 10Hz gives a 100ms/50ms cycle/period | |
localparam FREQUENCY = 23'd50; | |
// Debouncer for pin14 input button | |
pulse_fsm debounce(.S(pin14_sdo), .C(clk_cyc), .Reset(pin17_ss), .Pulse(pin16_sck)); | |
// Clock divder and generator | |
always @(posedge pin3_clk_16mhz) begin | |
if (clk_1hz_counter < 23'd7_999_999) | |
clk_1hz_counter <= clk_1hz_counter + FREQUENCY; | |
else begin | |
clk_1hz_counter <= 23'b0; | |
clk_cyc <= ~clk_cyc; | |
end | |
end | |
// Ping/Pong effect, driven by pulse output of the debouncer FSM | |
always @(posedge pin16_sck) begin | |
if (counter == 9) begin | |
direction = ~direction; | |
counter = 0; | |
end | |
// Shift active LED | |
if (direction == 0) begin | |
shift <= shift << 1; | |
end | |
else begin | |
shift <= shift >> 1; | |
end | |
counter <= #1 counter + 1; | |
end | |
// Route to pins | |
assign | |
pin13 = shift[9], | |
pin12 = shift[8], | |
pin11 = shift[7], | |
pin10 = shift[6], | |
pin9 = shift[5], | |
pin8 = shift[4], | |
pin7 = shift[3], | |
pin6 = shift[2], | |
pin5 = shift[1], | |
pin4 = shift[0]; | |
// Convenience for visual inspection. | |
assign pin15_sdi = clk_cyc; | |
assign | |
pin1_usb_dp = 1'b0, | |
pin2_usb_dn = 1'b0; | |
endmodule // top |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Logic diagram