Search code examples
vhdlfrequencydivider

How to set frequency in vhdl at 0.01 Hz?


I need to divide frequency in vhdl so the resulting frequency will be 0.01 Hz,but I Don't know how to do it. I tried by using generic map, but then I got error. I am using Nexys3. I know Nexys3's frequency is 100 MHz, so I tried to divide it to 0.01.

entity stotinkasekunde is
port (
    izlaz: out std_logic_vector(3 downto 0);
    led: out std_logic_vector(6 downto 0);
    clk, ss: in std_logic
);
end stotinkasekunde;

architecture Behavioral of stotinkasekunde is
signal clk_o: std_logic;
signal temp: std_logic_vector(3 downto 0);
begin
s1: entity work.frekdiv generic map(10000000000) port map(clk, clk_o);
process (clk_o)
begin
    if (clk_o'event and clk_o='1') then
        if (ss='1') then
            temp <= temp+1;
            if (temp >= 1010) then
                temp <= "0000";
            end if;
        end if;
    end if;
end process;

ERROR: Line 18: Literal 10000000000 exceeds maximum integer value.


Solution

  • For 100Mhz specifically start by a break down of the problem into two parts

    1. Divide the frequency by a highest divisible power of 2 so that it divides the input clock to an integer highest power of 2 by using an approach from here using a bit magic expression (n & (~(n - 1))) to find that number or trying all series from 1st power till the 26th power of 2 closest to the number but off by a factor below 2, in other words 100000000 / 2^26 = 1.490116 as the upper bound of the series ( https://www.geeksforgeeks.org/highest-power-of-two-that-divides-a-given-number/ )

    2. Then by non integer power of 2 ( https://www.slideshare.net/DeepakFloria/divide-by-n-clock, https://en.wikipedia.org/wiki/Frequency_divider )

      • By dividing by powers of 25
      • Then by a power of 10

    So, the resulting clock frequency division calculation could be written as 100000000 Hz / ((2^8)* (25 ^ 4) * (10)) which exactly equals 0.1 Hz

    Notes:

    How do we find a number that has same rightmost set bit and all other bits as 0?

    Remember: The overall scheme is to take 100000000Hz then divide by largest even power of 2 (why even, since power of 2 are already even, hint base 2...)

    Then proceed to divide 390625 Hz which is its self a power of 25, specifically because of 625 as the lowest portion of the number 625, 25^2, and 2 390000, the upper remaining portion when you subtract 25, a nice power of 625 itself, making the original divisible by 25.

    Take that divide 25, divide by 25, divide by 25, divide by 25 And then divide by 10 to get 0.1 Hz

    How to implement:

    Divide by 2 can be done by using mod-n counter where n is a power of 2 in our case, or some sort of shift register, Johnson Counter, etc...

    Divide by either 25 (or powers of 25), or Divide by 10

    Both use example scheme seen below in the link, but not using same numbers though

    https://electronics.stackexchange.com/a/61607/20332

    Or, use the Xilinx Clocking wizard to generate this block

    https://electronics.stackexchange.com/a/61620/20332

    Divide by 25 might be available as an existing resource on the FPGA, but if not refer to wiki (https://en.wikipedia.org/wiki/Frequency_divider) for more information.

    Finally, make sure to run a behavioral simulation to find the markers to place on the zoomed out resulting clock rising edge, to next rising edge to be able to measure the period of the resulting clock generated in your output waveform, and verify it is correct, based on your VHDL time scale if I am using the right terminology since this is a terminology in Verilog HDL, for sure when I was using Verilog.