Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

How to divide a 24MHz clock to get 1kHz (in Verilog)

  1. Jul 16, 2009 #1
    Hey guys,

    I'm using the Altera Cyclone II FPGA Development Board, with the goal of controlling a relay. I need to divide 24MHz to get 1kHz, but I don't know how to write the code for it. I know one way to divide it, would be to have a 10bit counter, which will allow me to divide it by 1k, then all that's left is to divide it by 24, which can just be another counter that counts to 23. Again, though, I don't know what the code would look like. I looked online but for some reason I couldn't find any help.

    Could anyone point me in the right direction? I don't want any code, just an explanation (if possbile...)

    Thanks in advance.
     
  2. jcsd
  3. Jul 16, 2009 #2

    negitron

    User Avatar
    Science Advisor

    Am I missing something here? All you need is a counter to count your 24 MHz pulses and a bit of code to read that counter; when it gets to 12,000 it toggles an output pin (or whatever it is you need done) then resets the counter back to zero for the next half-cycle.
     
  4. Jul 16, 2009 #3
    There's a wonderful programmable chip called the 8254 which can be instructed to do exactly what you're asking for. You can see its spec sheet at http://jwc.seu.edu.cn/jpkc/declare/08wjjk/louyuwu/jbsc/8254.pdf [Broken].

    You would want to set a counter up in Mode 3: Square Wave Generator, and feed your 24 MHz signal into the clock input. Program the chip to count to 24000, and the output will be a square wave with frequency of 1 kHz.

    I have worked with this chip to provide a timebase for a data acquisition system, so if you have further questions feel free to ask.
     
    Last edited by a moderator: May 4, 2017
  5. Jul 16, 2009 #4

    berkeman

    User Avatar

    Staff: Mentor

    It sounds like he wants to do it in the FPGA, not in a uC or a separate 8254 chip.

    EugP -- what learning resources do you have for Verilog? The wikipedia.org page is a reasonable place to start:

    http://en.wikipedia.org/wiki/Verilog

    .
     
  6. Jul 16, 2009 #5
    Thanks everyone for the replies.

    negitron - it makes sense to me, but I don't know how to implement it

    Fenn - I'm trying to use the FPGA on the development board, but thank you anyway, I might use that for some other project.

    berkeman - I've looked at a bunch of Verilog tutorials, but I can't seem to find a good explanation. I might be able to find the exact code I need, but I want to understand how it works so then I will be able to divide any frequency. I found the code I used to to divide 50MHz to get 38k, by having a counter count till 1302. That makes sense because 50M/1302 = 38kHz. So by following that logic I tried setting the counter to 24k (24M/24k = 1kHz), but that didn't work for some reason
     
  7. Jul 16, 2009 #6

    berkeman

    User Avatar

    Staff: Mentor

    Can you post the code for the 1302 counter/divider? I use HDL mostly, but there are several Verilog guys here that I can ask about this if we can't figure it out quickly.
     
  8. Jul 16, 2009 #7
    Yup. Here is the code I wrote last summer:

    Code (Text):
    module freq_divider(
        clk,                //Clock 50 MHz
        reset_n,            //Active low reset
        divided_frequency,  //Divided frequency
        new_freq,
        current_q           //Current value
    );

    input clk;
    input reset_n;

    output divided_frequency;
    output [11:0] current_q;
    output new_freq;

    reg divided_frequency;
    reg divided_frequency_next;
    reg [11:0] current_q;
    reg [11:0] next_d;
    reg new_freq;

    //Flip Flops
    always @(posedge clk or negedge reset_n)
    begin
        if (!reset_n)
            begin
                divided_frequency <= 1'b0;
                current_q <= 12'b000000000000;
            end

        else
            begin
                divided_frequency <= divided_frequency_next;
                current_q <= next_d;
            end
    end

    //Parallel Counter Logic
    always @(current_q or divided_frequency)
    begin
        if (current_q == 1302)
            begin
                next_d <= 12'b0000_0000_0000;
                divided_frequency_next <= 1'b1;
            end

         else
            begin
                divided_frequency_next <= 1'b0;
                next_d <= current_q + 1;
            end

    end

    always @(posedge divided_frequency)
    begin
        new_freq <= !new_freq;
    end

    endmodule
     
     
  9. Jul 16, 2009 #8

    berkeman

    User Avatar

    Staff: Mentor

    And how did you modify it to try to get the divide-by-24K?
     
  10. Jul 16, 2009 #9
    My clock input is now 24MHz, and the current_q == 1302, I have counter == 24000.
     
  11. Jul 16, 2009 #10

    berkeman

    User Avatar

    Staff: Mentor

    And 12 bits can count how high...?
     
  12. Jul 16, 2009 #11
    Oh no no I changed the counter size as well (naturally) to 15 bits.
     
  13. Jul 16, 2009 #12

    berkeman

    User Avatar

    Staff: Mentor

    Ah, okay. Just checking.

    So what doesn't work? Does it not compile? Or you just do not get the output signal you expect?
     
  14. Jul 16, 2009 #13
    Well the module "freq_divider" is an instance in my top level file. Maybe I defined it wrong or something, because in my simulations, the signals don't do anything. Here is the new frequency divider and top level modules (I tried cleaning up the top level as much as possible, because most of the code has nothing to do with this implementation):

    Top Level
    Code (Text):

    module project_top
        (
            ////////////////////    Clock Inputs        ////////////////////     
            CLOCK_24,                       //  24 MHz
            CLOCK_27,                       //  27 MHz
            CLOCK_50,                       //  50 MHz
            EXT_CLOCK,                      //  External Clock

            ////////////////////    Push Buttons        ////////////////////
            KEY,                            //  Pushbutton[3:0]

            ////////////////////    GPIO    ////////////////////////////
            GPIO_0                          //  GPIO Connection 0
            GPIO_1                          //  GPIO Connection 1
                           
        );

    ////////////////////////    Clock Input     ////////////////////////
    input   [1:0]   CLOCK_24;               //  24 MHz
    input   [1:0]   CLOCK_27;               //  27 MHz
    input           CLOCK_50;               //  50 MHz
    input           EXT_CLOCK;              //  External Clock


    ////////////////////////    Push Button     ////////////////////////
    input   [3:0]   KEY;                    //  Pushbutton[3:0]


    ////////////////////////    GPIO    ////////////////////////////////
    //input [35:0]  GPIO_0;                 //  GPIO Connection 0
    output  [35:0]  GPIO_0;                 //  GPIO Connection 0
    //inout [35:0]  GPIO_1;                 //  GPIO Connection 1


    wire    divided_frequency;
    wire    new_freq;
    wire    boost;
    wire    [7:0]   relay_on, relay_off;
    wire    [4:0]   counter;
    wire    [2:0]   sm_state;
    wire    [14:0]  counter1;

    assign GPIO_0[5] = new_freq;
    assign GPIO_0[6] = divided_frequency;
    assign GPIO_0[7] = boost;
    assign GPIO_0[8] = relay_on[0];
    assign GPIO_0[9] = relay_on[1];
    assign GPIO_0[10] = relay_on[2];
    assign GPIO_0[11] = relay_on[3];
    assign GPIO_0[12] = relay_on[4];
    assign GPIO_0[13] = relay_on[5];
    assign GPIO_0[14] = relay_on[6];
    assign GPIO_0[15] = relay_on[7];
    assign GPIO_0[16] = relay_off[0];
    assign GPIO_0[17] = relay_off[1];
    assign GPIO_0[18] = relay_off[2];
    assign GPIO_0[19] = relay_off[3];
    assign GPIO_0[20] = relay_off[4];
    assign GPIO_0[21] = relay_off[5];
    assign GPIO_0[22] = relay_off[6];
    assign GPIO_0[23] = relay_off[7];
    assign GPIO_0[24] = counter[0];
    assign GPIO_0[25] = counter[1];
    assign GPIO_0[26] = counter[2];
    assign GPIO_0[27] = counter[3];
    assign GPIO_0[28] = counter[4];
    assign GPIO_0[29] = sm_state[0];
    assign GPIO_0[30] = sm_state[1];
    assign GPIO_0[31] = sm_state[2];

    freq_divider divider(
                            .clk(EXT_CLOCK),
                            .rst_n(KEY[0]),
                            .new_freq(new_freq),
                            .divided_frequency(divided_frequency),
                            .counter(counter1)
    );


    project project(
                        .clk(EXT_CLOCK),
                        .rst_n(KEY[0]),
                        .btn_on_n(KEY[3]),
                        .btn_off_n(KEY[2]),
                        .boost(boost),
                        .relay_on(relay_on),
                        .relay_off(relay_off),
                        .counter(counter),
                        .sm_state(sm_state)
    );
    endmodule
     
    Frequency Divider
    Code (Text):
    module freq_divider(
                        clk,                //Clock 24 MHz
                        rst_n,              //Active low reset
                        divided_frequency,  //Divided frequency
                        new_freq,
                        counter             //Current value
    );

    input clk;
    input rst_n;

    output divided_frequency;
    output [14:0] counter;
    output new_freq;

    reg divided_frequency, divided_frequency_next;
    reg [14:0] counter, counter_next;
    reg new_freq;

    //Flip Flops
    always @(posedge clk or negedge rst_n)
    begin
        if (!rst_n)
            begin
                divided_frequency <= 1'b0;
                counter <= 15'b0000000_0000_0000;
            end

        else
            begin
                divided_frequency <= divided_frequency_next;
                counter <= counter_next;
            end
    end

    //Parallel Counter Logic
    always @(counter or divided_frequency)
    begin
        if (counter == 24000)
            begin
                counter_next <= 15'b0000000_0000_0000;
                divided_frequency_next <= 1'b1;
            end

         else
            begin
                divided_frequency_next <= 1'b0;
                counter_next <= counter + 1;
            end

    end

    always @(posedge divided_frequency)
    begin
        new_freq <= !new_freq;
    end

    endmodule
     
     
  15. Jul 17, 2009 #14

    berkeman

    User Avatar

    Staff: Mentor

    You mean you see the clock going in, but in the new code, the counter is not counting?
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: How to divide a 24MHz clock to get 1kHz (in Verilog)
  1. Clock divider (Replies: 6)

Loading...