diff --git a/tdc/rtl/debounce.v b/tdc/rtl/debounce.v new file mode 100644 index 0000000..aea1ead --- /dev/null +++ b/tdc/rtl/debounce.v @@ -0,0 +1,115 @@ +// Listing 5.6 +module debounce + ( + input wire clk, reset, + input wire sw, + output reg db + ); + + // symbolic state declaration + localparam [2:0] + zero = 3'b000, + wait1_1 = 3'b001, + wait1_2 = 3'b010, + wait1_3 = 3'b011, + one = 3'b100, + wait0_1 = 3'b101, + wait0_2 = 3'b110, + wait0_3 = 3'b111; + + // number of counter bits (2^N * 10ns = 10ms tick) + localparam N =20; + + // signal declaration + reg [N-1:0] q_reg; + wire [N-1:0] q_next; + wire m_tick; + reg [2:0] state_reg, state_next; + + // body + + //============================================= + // counter to generate 10 ms tick + //============================================= + always @(posedge clk) + q_reg <= q_next; + // next-state logic + assign q_next = q_reg + 1; + // output tick + assign m_tick = (q_reg==0) ? 1'b1 : 1'b0; + + //============================================= + // debouncing FSM + //============================================= + // state register + always @(posedge clk, posedge reset) + if (reset) + state_reg <= zero; + else + state_reg <= state_next; + + // next-state logic and output logic + always @* + begin + state_next = state_reg; // default state: the same + db = 1'b0; // default output: 0 + case (state_reg) + zero: + if (sw) + state_next = wait1_1; + wait1_1: + if (~sw) + state_next = zero; + else + if (m_tick) + state_next = wait1_2; + wait1_2: + if (~sw) + state_next = zero; + else + if (m_tick) + state_next = wait1_3; + wait1_3: + if (~sw) + state_next = zero; + else + if (m_tick) + state_next = one; + one: + begin + db = 1'b1; + if (~sw) + state_next = wait0_1; + end + wait0_1: + begin + db = 1'b1; + if (sw) + state_next = one; + else + if (m_tick) + state_next = wait0_2; + end + wait0_2: + begin + db = 1'b1; + if (sw) + state_next = one; + else + if (m_tick) + state_next = wait0_3; + end + wait0_3: + begin + db = 1'b1; + if (sw) + state_next = one; + else + if (m_tick) + state_next = zero; + end + default: state_next = zero; + endcase + end + +endmodule diff --git a/tdc/rtl/tdc.v b/tdc/rtl/tdc.v index da94770..d62dca2 100644 --- a/tdc/rtl/tdc.v +++ b/tdc/rtl/tdc.v @@ -12,6 +12,21 @@ module tdc #(parameter COUNTER_WIDTH=16)( reg [COUNTER_WIDTH-1:0] counter; assign o_data = counter; +reg db_start, db_stop; +debounce db1 ( + // Outputs + .db (db_start), + // Inputs + .clk (i_clk), + .reset (i_reset), + .sw (i_start)); +debounce db2 ( + // Outputs + .db (db_stop), + // Inputs + .clk (i_clk), + .reset (i_reset), + .sw (i_stop)); // states localparam state_idle = 2'b00; localparam state_started = 2'b01; @@ -20,7 +35,7 @@ localparam state_stopped = 2'b11; reg [1:0] current_state, next_state; // ensure that state changes each clock -always @(posedge i_clk) begin +always @(posedge i_clk, posedge i_reset) begin if (i_reset) begin current_state <= state_idle; end else begin @@ -33,19 +48,19 @@ end always @(*) begin case (current_state) state_idle: begin - if (i_start && (~i_stop)) + if (db_start && (~db_stop)) next_state <= state_started; else next_state <= state_idle; end state_started: begin - if (~i_start && (~i_stop)) + if (~db_start && (~db_stop)) next_state <= state_running; else next_state <= state_started; end state_running: begin - if (~i_start && (i_stop)) + if (~db_start && (db_stop)) next_state <= state_stopped; else next_state <= state_running;