2
\$\begingroup\$

Is it possible to create a 41.67Hz clock from a 100MHz clock on an FPGA in VHDL using the following VHDL, by changing the count value?

And what is the maths to calculate an output clock frequency?


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

Entity One_Hundred_to_Ten_MHz_Clock_Divider is
 Port (Clock_in : in std_logic;   --100MHz in
       Clock_out : out std_logic  --50Hz out
      );
end One_Hundred_to_Ten_MHz_Clock_Divider;

Architecture Behavioral of One_Hundred_to_Ten_MHz_Clock_Divider is

signal Count : integer := 1;    
signal Temp : std_logic := '0';

begin

    Process (Clock_in)

    begin

    if (rising_edge(Clock_in)) then
           Count <= Count + 1;

            if (Count = 2500000) then 
                   Temp <= not Temp;
                   Count <= 1;

            end if;

        end if;

        Clock_out <= Temp;

    end Process;

end Behavioral;

```
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Why's the entity called One_Hundred_to_Ten_MHz_Clock_Divider when it doesn't actually output a 10 MHz clock? Do look up generics to make things like this more obvious and generalizable. Also, in FPGAs, if you want something happen at a slow frequency, you typically don't generate and use slow "clocks" like this; instead you'd use a single clock domain, and you generate enable signals that are 1 main clock period wide, with tonsa dead time in between, as much as you need. There are good reasons for this, routing and glitches/hazards to name a few. \$\endgroup\$ Apr 22, 2021 at 11:45
  • \$\begingroup\$ What family of FPGA are you using? Many families have built in clock generator tiles. Some of which might be able to make what you need. \$\endgroup\$
    – user4574
    Apr 22, 2021 at 12:56
  • \$\begingroup\$ That's quite a slow clock, so yes, but may not be 'so accurate'. \$\endgroup\$
    – Mitu Raj
    Apr 22, 2021 at 14:13
  • \$\begingroup\$ If you don't need the frequency to be exactly 41.67Hz, then you simply divide by the closest integer value, it will be a little higher or lower. This is by far the easiest implementation. As mentioned elsewhere, count to 1199904 (half a period), and toggle the output clock signal. Repeat forever. If you want the output frequency to have the same error as your input 100e6 clock, you will need to implement a 32-bit fractional-N divider. This will have some cycle-to-cycle jitter, but can be exact over time. 32-bit because the LCM is just over 4 billion. \$\endgroup\$
    – Troutdog
    Apr 22, 2021 at 21:50

3 Answers 3

2
\$\begingroup\$

You can produce a periodic signal that way but it is NOT a clock in the FPGA sense of the term.

Basically for most modern parts the clock plane has only limited interaction with the signal routing fabric, and while you CAN do this sort of thing, it is usually better to make it a clock enable pulse then a clock in its own right.

As near as you can get with integer maths is a divisor of 1199904, which with a 100Mhz reference gets you 41.67000027Hz in your code. If you need more precision you could add a larger number then one on every clock and recalculate the divider to match or do some sort of fractional N thing, for example if every clock added 2000 to the accumulator, then 4799616031 is exact for 41.67Hz (as a single cycle pulse for clock enable) but you may need something longer then integer for the accumulator, note that if playing that game you subtract the divisor from the accumulator on acc > divisor rather then looking for equality and setting to 1 (or zero), the pulse timing will vary a little as 41.67 does not divide cleanly into 100M.

What you are far better off doing however is setting a clock enable signal to one for a single cycle on a match, else zero. Your downstream doings then do 'if (rising_edge (clk) and clk_enble)....' which means the timing analysis will actually work properly, most FPGA registers have a clock enable input so this costs no logic.

\$\endgroup\$
6
  • \$\begingroup\$ If I want something much more accurate, should I generate another clock in the DCM, say a 24MHz clock that can be divided down evenly? \$\endgroup\$
    – David777
    Apr 22, 2021 at 11:58
  • \$\begingroup\$ 24MHz is actually worse for the frequency you requested, but if a DCM can generate something that works as an exact multiple then yea that works. \$\endgroup\$
    – Dan Mills
    Apr 22, 2021 at 12:02
  • \$\begingroup\$ Should I pick something divisible by 2? Even 41.67MHz? \$\endgroup\$
    – David777
    Apr 22, 2021 at 12:03
  • \$\begingroup\$ You want to be careful with having a number of clock sources - this avoids having to traverse clock domains. Dan alluded to a DDS technique to give fractional division by adding a value to a n bit accumulator. Issue an enable each time it overflows. \$\endgroup\$
    – Kartman
    Apr 22, 2021 at 12:08
  • \$\begingroup\$ Depends totally on your actual design requirements, resource availability and what will be useful for other things. For example if I had a spare DSP block that can do long word length addition at 100MHz and can also do compare, then I might well just use that to do an exact generation from a 100MHz clock, job done. If I was short on DSP but had a DCM available... Maybe I got neither, but have loads of logic available... Maybe my precision requirements are not all that? You get different solutions depending on your constraints. \$\endgroup\$
    – Dan Mills
    Apr 22, 2021 at 12:08
1
\$\begingroup\$

In short, yes, this is possible.

Since you need to toggle twice in that period, you need to count up to the number of cycles the input clock would do divided by two, between the two clock toggles.

So, you could just replace your 2500000 constant with something else. That something else would likely be 1_199_904. One nice thing VHDL lets you do is that you can make your numeric literals more legible by introducing underscores where you want stuff to be spaced out.

However, this is AFAIK not the best practice for generating slow "clocks". You probably might want to think of it as triggering events at a longer interval instead. (TODO: explain why.)

See perhaps this answer to learn more.


Basically, what you'd do instead of

slow_stuff: process(clk_50Hz)
begin
    if(rising_edge(clk_50Hz)) then
      -- your magic that happens every clock period, ie. 50x a second
    end if;
end process;

is something like this:

slow_stuff: process(clk_fast)
begin
    if(rising_edge(clk_fast) and enable_50Hz) then
      -- your magic that happens every enable period, ie. still 50x a second
    end if;
end process;

A convenient way of generating these signals may be perhaps something like this:

entity enable_timer is
  generic (
    divide_by : integer := 5_000_000
  );
  port (
    clk : in std_logic;
    srst : in std_logic; -- sync reset
    enable : out std_logic
  );
end entity enable_timer;

architecture I_took_this_from_stackexchange of enable_timer is
  signal counter : integer := 0;
begin
  magic: process(clk) is
    enable <= '0';
    if(rising_edge(clk)) then
      if(srst = '1') then
        counter <= 0;
      elsif(counter >= divide_by) then
        counter <= 0;
        enable <= '1';
      else
        counter <= counter + 1;
      end if;
    end if;
  end process;
end architecture I_took_this_from_stackexchange;

You could instantiate this with a generic map mapping the divide_by parameter to whatever suits your needs at any particular moment (like 2_399_808 to get your 41.67Hz out of your 100MHz clock), and you'll almost* never have to write this timing's entity's implementation again! Reuse it for all your slow* timings! Amazing, isn't it.

An example for instantiation, for the sake of completeness:

my_awesome_41_67Hz_timer: enable_timer 
   generic map (count_to => 2_399_808)
   port map (
     clk => clk_100MHz,
     srst => reset, -- or '0' if not used
     enable => enable_41_67Hz
   );

With a counter like this, you can generate about any frequency with 1-period of your main clock resolution, that is 10ns resolution for your 100MHz clock. So yes, 41.67Hz is doable, with about 0.024% error in this case. You can get this constant by dividing the frequency of the input clock and the output clock and rounding. The error comes from exactly this rounding.

*) The error may not always be this low, for example when the output frequency is much closer to the main clock's frequency, and it does not divide quite cleanly. In those cases you could use a fractional clock divider of some sort. I'll say those are beyond the scope of this answer. :)


I have not actually checked the syntax of the above examples yet, so take them more as a guidance than a straight-up copy-pasta.

\$\endgroup\$
2
  • \$\begingroup\$ You sure, you seem to be taking a period as the generic not a frequency, pretty sure the constant in the generic map is wrong. \$\endgroup\$
    – Dan Mills
    Apr 22, 2021 at 12:16
  • \$\begingroup\$ Yeah, I've goofed up the math in there. Oopsie. Should be fixed now. \$\endgroup\$ Apr 22, 2021 at 12:16
1
\$\begingroup\$

The simplest way to generate a 41.67 Hz clock is a phase accumulator or what is also called NCO (numerically controlled oscilator). This is usually used to generate a sinus or cosine signal in FPGA.

The MSB of the accumulator is a clock like signal. The benefit of this technique is that the average clock is what you ask and you don't have to update value of the counter.

For 41.67 Hz, a 32 bit accumulator and 100 MHz of processing frequency, the increment step is: 41.67 x 2^32 / 100e6 = 1789.71 or 1790 rounded

Reversing the formula gives the precision of the generated clock signal.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.