aboutsummaryrefslogtreecommitdiffstats
path: root/atk16_fpga/foo.v
blob: f6ff33c4f538e990423fd99bd57c8eef6f361bb1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Top-level module
module foo (
    LED1,
    LED2,
    BUT1,
    BUT2,
    SYSCLK
);
    output LED1;
    output LED2;
    input BUT1;
    input BUT2;
    input SYSCLK;

    // 2-bit counter register
    reg [1:0] val;
    initial val = 2'b00;

    // Wires for debounced button signals
    wire db_but1;
    wire db_but2;

    // Instantiate debounce modules for each button.
    // Adjust the DEBOUNCE_LIMIT parameter as needed based on SYSCLK frequency.
    debounce #(
        .DEBOUNCE_LIMIT(500000)
    ) debounce_but1 (
        .clk(SYSCLK),
        .button(BUT1),
        .db_out(db_but1)
    );

    debounce #(
        .DEBOUNCE_LIMIT(500000)
    ) debounce_but2 (
        .clk(SYSCLK),
        .button(BUT2),
        .db_out(db_but2)
    );

    // Edge detection registers to trigger a single count change per button press.
    reg prev_db_but1;
    reg prev_db_but2;
    initial begin
        prev_db_but1 = 1'b0;
        prev_db_but2 = 1'b0;
    end

    // Drive LEDs from the counter bits.
    assign LED1 = val[0];
    assign LED2 = val[1];

    // Synchronous logic to detect rising edges and update counter.
    always @(posedge SYSCLK) begin
        // If a rising edge is detected on db_but1, increment the counter.
        if (db_but1 && !prev_db_but1) val <= val + 1;
        // Else, if a rising edge is detected on db_but2, decrement the counter.
        else if (db_but2 && !prev_db_but2) val <= val - 1;

        // Store the current debounced states for edge detection on the next clock.
        prev_db_but1 <= db_but1;
        prev_db_but2 <= db_but2;
    end

endmodule

// Debounce module written in plain Verilog.
module debounce (
    clk,
    button,
    db_out
);
    parameter DEBOUNCE_LIMIT = 500000;  // Adjust as needed for your clock frequency.
    input clk;
    input button;
    output db_out;
    reg db_out;

    reg [31:0] counter;  // Counter width chosen to comfortably count up to DEBOUNCE_LIMIT.
    reg button_sync;

    initial begin
        counter     = 32'd0;
        db_out      = 1'b0;
        button_sync = 1'b0;
    end

    always @(posedge clk) begin
        // First, synchronize the raw button input to the clock domain.
        button_sync <= button;

        // If the synchronized value equals the debounced output,
        // reset the counter.
        if (button_sync == db_out) counter <= 32'd0;
        else begin
            // Otherwise, increment the counter.
            counter <= counter + 1;
            // If the counter reaches the limit, update the debounced output.
            if (counter >= DEBOUNCE_LIMIT) begin
                db_out  <= button_sync;
                counter <= 32'd0;
            end
        end
    end

endmodule