Search code examples
verilogfpgafsm

FSM implementation of a debouncing circuit in verilog ( error in time tick)


I need to solve an issue in FPGA Prototyping By Verilog Examples Pong

If its Autor mistake or I'm doing sth wrong when i simulate on vivado i dont find any change in

    q_reg <= q_next;    //   ? q_next never initialised ???
   // next-state logic    //  How he wants to set time tick ?
   assign q_next = q_reg + 1;
   // output tick

State diagram of a debouncing circuit. is defined as picture

consider section
// counter to generate 10 ms tick

enter image description here

module db_fsm
   (
    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 * 20ns = 10ms tick)
   localparam N =19;

   // 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

Solution

  • q_next does not need to be initialized, it is a combinational logic derived from q_reg. q_reg is not explicitly initialized, therefore it will take the default value.

    The default value of a flop on FPGA is 0 but for simulators the default is X. The reason for this discrepancy is because Verilog is also used for simulating integrated circuits (IC); who flops can have an initial value that seem random due to the technology node, manufacturing process and variations, temperature, etc.

    Since your target is FGPA, the simple solution is to add the line initial q_reg = {N{1'b0}}; or change reg [N-1:0] q_reg; to reg [N-1:0] q_reg = {N{1'b0}}; Either way of initializing q_reg will have you Verilog simulation and FPGA matching.

    BTW: for a ASIC as the target, the FPGA solution will not work (initializer is ignored by ASIC synthesizers). An ASIC solution would be to add a reset condition (synchronous or asynchronous) to the always block that assigns the flop. The ASIC solution does work for FPGA, however FPGA's typically have a limited number (if any) of flops with asynchronous reset/set