clk divider

Discussion in 'VHDL' started by Schmigz, Feb 9, 2004.

  1. Schmigz

    Schmigz Guest

    I am trying to write a clock divider that will be used for input from
    a serial port that is outputting data at 115200 baud. This means I
    would need a clk that runs at 115.2 kHz. My on board clk is currently
    running at 50 MHz (oscillator). One option is to add another clk to
    my design using a second oscillator but I would prefer to find another
    option since this will drive up costs. Is there an easy way to divide
    50 MHz downto 115.2 kHz using VHDL?
    Schmigz, Feb 9, 2004
    #1
    1. Advertising

  2. Schmigz wrote:
    > I am trying to write a clock divider that will be used for input from
    > a serial port that is outputting data at 115200 baud. This means I
    > would need a clk that runs at 115.2 kHz. My on board clk is currently
    > running at 50 MHz (oscillator). One option is to add another clk to
    > my design using a second oscillator but I would prefer to find another
    > option since this will drive up costs. Is there an easy way to divide
    > 50 MHz downto 115.2 kHz using VHDL?


    If you can live with a frequency of 115207 Hz, then you can use a
    counter to generate the clock signal. That's pretty easy.

    50 MHz gives a cycle time of 20 ns, 115.2 KHz gives aprox. a cycle time
    of 8680 ns. A cycle of the ouput clock needs to be 434 times longer than
    the input clock, so the output clock can be generated in this way:

    process(clk,reset)
    begin
    if (reset = '0') then
    clk_o <= '0';
    cnt <= 0;
    elsif (rising_edge(clk)) then
    if (cnt = 217) then
    cnt <= 0;
    clk_o <= not clk_o;
    else
    cnt <= cnt + 1;
    end if;
    end if;
    end process;

    I just wrote this of the top of my head, so odds are it's full of
    errors. And anyway it doesn't give exactly the right frequency, but if
    you need that, then I think you will have to use DLL's or some other
    stuff to generate it.

    -- Anders
    Anders Hellerup Madsen, Feb 9, 2004
    #2
    1. Advertising

  3. Schmigz

    jussi l Guest

    hi,

    the ration between the two frequencies is pretty close to 434 if I
    calculated correctly. So, keep the baud clock low for say 216 clock cycles
    and high for 217 cycles. Then repeat. Addtional accuracy can be gained by
    letting every mth clock cycle have 216-218 cycles of the fast clock. So,
    basically, all you need is a few counters and a little control...

    regards,
    juza
    "Schmigz" <> wrote in message
    news:...
    > I am trying to write a clock divider that will be used for input from
    > a serial port that is outputting data at 115200 baud. This means I
    > would need a clk that runs at 115.2 kHz. My on board clk is currently
    > running at 50 MHz (oscillator). One option is to add another clk to
    > my design using a second oscillator but I would prefer to find another
    > option since this will drive up costs. Is there an easy way to divide
    > 50 MHz downto 115.2 kHz using VHDL?
    jussi l, Feb 9, 2004
    #3
  4. jussi l wrote:

    > hi,
    >
    > the ration between the two frequencies is pretty close to 434 if I
    > calculated correctly. So, keep the baud clock low for say 216 clock cycles
    > and high for 217 cycles. Then repeat. Addtional accuracy can be gained by
    > letting every mth clock cycle have 216-218 cycles of the fast clock. So,
    > basically, all you need is a few counters and a little control...
    >
    > regards,
    > juza
    >


    It depends on the COM port scills.
    Many COM ports operate well when the
    frequency error is in range 1-3 %.
    Therefore take it easy to keep this frequency precisely.

    A.Ser.
    Vladislav Vasilenko, Feb 9, 2004
    #4
  5. Schmigz

    Schmigz Guest

    I would like to thank everyone who helped me out. I ended combining
    some of the suggestions into my final solution. Here is my final
    code. Works well. I actually like this solution because the clock
    input is not finalized yet. We have an ideal clock of 50 Mhz so that
    is the timing I used, but if for some reason it changes, I only have
    to change the two comparison values.

    cts is the Clear to Send bit from the serial and ser_in is the data
    line.

    if(clk'event and clk='1') then
    if(cts = '1') then
    case cur_s is

    when IDLE_S =>
    if(ser_in = '0') then
    cur_s <= READ_S;
    ser_rd_en <= '1';
    cnt <= "000000001";
    bit_cnt <= "0001";
    end if;

    when READ_S =>
    if(ser_rd = '1') then
    case bit_cnt is

    when "0001" =>
    if(ser_in = '1') then -- Should be start bit
    error <= '1'; -- If not set error
    end if;

    when "0010" =>
    ser_buf(0) <= ser_in;

    when "0011" =>
    ser_buf(1) <= ser_in;

    when "0100" =>
    ser_buf(2) <= ser_in;

    when "0101" =>
    ser_buf(3) <= ser_in;

    when "0110" =>
    ser_buf(4) <= ser_in;

    when "0111" =>
    ser_buf(5) <= ser_in;

    when "1000" =>
    ser_buf(6) <= ser_in;

    when "1001" =>
    ser_buf(7) <= ser_in;
    if(tmpcolor = "00") then

    when "1010" =>
    cur_s <= IDLE_S;
    if(ser_in = '0') then -- Should be stop bit
    error <= '1'; -- If not set error
    end if;


    when others =>
    cur_s <= IDLE_S;

    end case;

    bit_cnt <= bit_cnt + '1';

    end if;
    end case;

    -- 50Mhz clk / 115200 baud rate = 434.028
    -- Generates high pulse for a single read
    -- Every 217 clocks, resets after 434
    if(ser_rd_en ='1') then
    cnt <= cnt + '1';
    if(cnt = "011011001") then -- High for clock 217
    ser_rd <= '1';
    elsif(cnt > "110110010") then -- Reset after 434
    ser_rd <= '0';
    cnt <= "000000001";
    else
    ser_rd <= '0';
    end if;
    end if;
    end if;
    Schmigz, Feb 11, 2004
    #5
  6. Schmigz

    Ray Andraka Guest

    Use a phase accumulator approach rather than a divider. That way, you can
    set the exact frequency. It will introduce some jitter with a peak
    deviation of 1/2 your master clock period. The phase accumulator
    (sometimes described as a direct digital synthesizer) is simply a
    registered adder with one input coming from its output and the other set
    to a constant increment value. The adder output represents a fraction of
    a cycle of your desired oscillator. For a square wave output, you use
    just the MSB of the output as your clock or as a clock enable. The width
    of the adder determines the frequency resolution. The output frequency is

    Fo= Fc * N/ (2^bits)

    In the case of generating a 115.2Khz clock from a 50 MHz master:

    Lets assume you want 0.1% accuracy, which is to say 115.2KHz +/- 115 Hz.
    You need enough bits to have at least 230Hz resolution, so

    230 = 50,000,000 * 1/(2^bits) tells us we need 18 bits in the
    accumulator. 18 bits gives us a frequency resolution of 191 Hz.

    Now, find the constant N that provides the 115.2KHz
    115200 = 50M * N/2^18 ===> N=604.

    plugging that back in you get an output frequency of 115203.9Hz. If you
    needed more accuracy, you could increase the width of the accumulator.

    signal accum:unsigned(17 downto 0);
    begin
    process(clk,reset)
    if reset='1' then
    accum<=(others=>'0');
    elsif rising_edge(clk) then
    accum<= accum+to_unsigned(604,18);
    end if;
    end process;
    baud_clk<= accum(accum'left);




    Now if you want to change the baud rate, all you need to do is change the
    constant. The baud_clock is proportional to the constant. The output
    taken from the msb of the accumulator is a square wave with approximately
    50% duty cycle (there is a little bit of jitter +/- a half master clock
    cycle) if the constant results in a non-integer division of the master
    clock. That little bit of jitter is quite acceptable for serial comms.

    Schmigz wrote:

    > I am trying to write a clock divider that will be used for input from
    > a serial port that is outputting data at 115200 baud. This means I
    > would need a clk that runs at 115.2 kHz. My on board clk is currently
    > running at 50 MHz (oscillator). One option is to add another clk to
    > my design using a second oscillator but I would prefer to find another
    > option since this will drive up costs. Is there an easy way to divide
    > 50 MHz downto 115.2 kHz using VHDL?


    --
    --Ray Andraka, P.E.
    President, the Andraka Consulting Group, Inc.
    401/884-7930 Fax 401/884-7950
    email
    http://www.andraka.com

    "They that give up essential liberty to obtain a little
    temporary safety deserve neither liberty nor safety."
    -Benjamin Franklin, 1759
    Ray Andraka, Feb 13, 2004
    #6
  7. Schmigz

    Clyde Guest

    Ray,

    Thanks for a very enlightening example of solving this problem.

    Clyde Shappee

    Ray Andraka wrote:
    > Use a phase accumulator approach rather than a divider. That way, you can
    > set the exact frequency. It will introduce some jitter with a peak
    > deviation of 1/2 your master clock period. The phase accumulator
    > (sometimes described as a direct digital synthesizer) is simply a
    > registered adder with one input coming from its output and the other set
    > to a constant increment value. The adder output represents a fraction of
    > a cycle of your desired oscillator. For a square wave output, you use
    > just the MSB of the output as your clock or as a clock enable. The width
    > of the adder determines the frequency resolution. The output frequency is
    >
    > Fo= Fc * N/ (2^bits)
    >
    > In the case of generating a 115.2Khz clock from a 50 MHz master:
    >
    > Lets assume you want 0.1% accuracy, which is to say 115.2KHz +/- 115 Hz.
    > You need enough bits to have at least 230Hz resolution, so
    >
    > 230 = 50,000,000 * 1/(2^bits) tells us we need 18 bits in the
    > accumulator. 18 bits gives us a frequency resolution of 191 Hz.
    >
    > Now, find the constant N that provides the 115.2KHz
    > 115200 = 50M * N/2^18 ===> N=604.
    >
    > plugging that back in you get an output frequency of 115203.9Hz. If you
    > needed more accuracy, you could increase the width of the accumulator.
    >
    > signal accum:unsigned(17 downto 0);
    > begin
    > process(clk,reset)
    > if reset='1' then
    > accum<=(others=>'0');
    > elsif rising_edge(clk) then
    > accum<= accum+to_unsigned(604,18);
    > end if;
    > end process;
    > baud_clk<= accum(accum'left);
    >
    >
    >
    >
    > Now if you want to change the baud rate, all you need to do is change the
    > constant. The baud_clock is proportional to the constant. The output
    > taken from the msb of the accumulator is a square wave with approximately
    > 50% duty cycle (there is a little bit of jitter +/- a half master clock
    > cycle) if the constant results in a non-integer division of the master
    > clock. That little bit of jitter is quite acceptable for serial comms.
    >
    > Schmigz wrote:
    >
    >
    >>I am trying to write a clock divider that will be used for input from
    >>a serial port that is outputting data at 115200 baud. This means I
    >>would need a clk that runs at 115.2 kHz. My on board clk is currently
    >>running at 50 MHz (oscillator). One option is to add another clk to
    >>my design using a second oscillator but I would prefer to find another
    >>option since this will drive up costs. Is there an easy way to divide
    >>50 MHz downto 115.2 kHz using VHDL?

    >
    >
    > --
    > --Ray Andraka, P.E.
    > President, the Andraka Consulting Group, Inc.
    > 401/884-7930 Fax 401/884-7950
    > email
    > http://www.andraka.com
    >
    > "They that give up essential liberty to obtain a little
    > temporary safety deserve neither liberty nor safety."
    > -Benjamin Franklin, 1759
    >
    >
    Clyde, Feb 14, 2004
    #7
  8. Schmigz

    radu Guest

    Hello Ray,

    Very clever your idea. Congratulation !!!
    radu, Apr 15, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rakesh Sharma
    Replies:
    2
    Views:
    2,920
    Thomas Rudloff
    Oct 22, 2004
  2. Matt Clement

    MCU clock divider vs. VHDL divider

    Matt Clement, Apr 20, 2006, in forum: VHDL
    Replies:
    3
    Views:
    4,233
    Marcus Harnisch
    Apr 28, 2006
  3. Wojtek

    Signal Set-up Before CLK Rise

    Wojtek, Jul 2, 2006, in forum: VHDL
    Replies:
    12
    Views:
    1,512
    Pascal Peyremorte
    Jul 5, 2006
  4. Replies:
    18
    Views:
    6,588
  5. chema15

    Frequency divider with clk en.

    chema15, Aug 12, 2008, in forum: VHDL
    Replies:
    1
    Views:
    1,366
    jeppe
    Aug 13, 2008
Loading...

Share This Page