Electronic – Toggling between 3 frequencies

verilog

I currently have a program that runs at X frequency, with the clock input generated by a slow clock module that divides the default clock via the counter increment method.

However, I wish to be able to switch between 3 frequencies, X, Y and Z using button presses. I have debounced the buttons with a single pulse signal generator module (using d flip flops). How can I go about doing it using rudimentary concepts only (multiplexer, etc)? Also, should the logic be implemented inside the slow clock module or in the main module?

Thank you.

schematic

simulate this circuit – Schematic created using CircuitLab

Best Answer

Since you tagged your question with , I'll assume that you're really looking for an HDL solution targeted at an FPGA. In this case, using a single programmable divider makes a whole lot more sense than having multiple dividers followed by a multiplexer. Something like this:

module clockdiv (
  input         master_clock,
  input         reset,
  input   [1:0] select,
  output reg    clock_out
)

  reg    [15:0] divider;

  always @* begin
    case (select)
      2'b00: divider <= X; // defined elsewhere
      2'b01: divider <= Y; //
      2'b10: divider <= Z; //
      2'b11: divider <= W; // ... etc.
    endcase
  end

  reg    [15:0] counter;

  always @(posedge master_clock) begin
    if (reset) begin
      counter <= 0;
      clock_out <= 0;
    end else begin
      if (counter >= divider) begin
        counter <= 0;
        clock_out <= !clock_out;
      end else begin
        counter <= counter + 1;
      end
    end
  end
endmodule

Define X, Y, Z, etc. to give you the clock division ratios you're looking for, keeping in mind that the output clock is further divided by 2 to produce a square wave.

This solution will never produce a bad clock pulse, even if the select input changes in the middle of an output cycle.


Addressing your secondary problem of controlling the select lines, the key here is to bring the two debounced pushbutton signals into the same clock domain as the rest of the logic. Something like this:

module up_down (
  input            master_clock,
  input            reset,
  input            button_up,
  input            button_down,
  output reg [1:0] count
)

  // Synchronizers and edge detectors for asynchronous inputs
  reg              button_up_a, button_up_b, button_up_c;
  reg              button_down_a, button_down_b, button_down_c;

  always @(posedge master_clock) begin
    button_up_a <= button_up;
    button_up_b <= button_up_a;
    button_up_c <= button_up_b;

    button_down_a <= button_down;
    button_down_b <= button_down_a;
    button_down_c <= button_down_b;

    if (reset) begin
      count <= 0;
    end else begin
      if (button_up_b && !button_up_c) begin
        //rising edge on button_up detected
        count <= count + 1;
      end else if (button_down_b && !button_down_c) begin
        //rising edge on button_down detected
        count <= count - 1;
      end
    end
  end
endmodule

Connect the count output of this module to the select input of the previous module.