How to divide 50MHz down to 2Hz in VHDL on Xilinx FPGA

vhdl

I have a Xilinx FPGA board, with a 50MHz crystal. I need to divide that down to 2Hz in VHDL. How do I do this?

Best Answer

Basically, there are two ways of doing this. The first is to use the Xilinx native clock synthesizer core. One of the advantages of this is that the Xlinx tools will recognise the clock as such and route it through the required pathways. The tools will also handle any timing constraints (not really applicable in this case, since it's a 2Hz clock)

The second way is to use a counter to count the number of faster clock pulses until half of your slower clock period has passed. For example, for your case, the number of fast clock pulses that make up one clock period of a slow clock cycle is 50000000/2 = 25000000. Since we want half a clock period, that's 25000000/2 = 12500000 for each half-cycle. (the duration of each high or low).

Here's what it looks like in VHDL:

library IEEE;
use IEEE.STD_LOGIC_1164.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.all;

entity scale_clock is
  port (
    clk_50Mhz : in  std_logic;
    rst       : in  std_logic;
    clk_2Hz   : out std_logic);
end scale_clock;

architecture Behavioral of scale_clock is

  signal prescaler : unsigned(23 downto 0);
  signal clk_2Hz_i : std_logic;
begin

  gen_clk : process (clk_50Mhz, rst)
  begin  -- process gen_clk
    if rst = '1' then
      clk_2Hz_i   <= '0';
      prescaler   <= (others => '0');
    elsif rising_edge(clk_50Mhz) then   -- rising clock edge
      if prescaler = X"BEBC20" then     -- 12 500 000 in hex
        prescaler   <= (others => '0');
        clk_2Hz_i   <= not clk_2Hz_i;
      else
        prescaler <= prescaler + "1";
      end if;
    end if;
  end process gen_clk;

clk_2Hz <= clk_2Hz_i;

end Behavioral;

Things to note:

  • The generated clock is zero during reset. This is ok for some applications, and not for others, it just depends what you need the clock for.
  • The generated clock is going to be routed as a normal signal by the Xilinx synthesis tools.
  • 2Hz is very slow. Simulating for a second is going to take a while. It's a small amount of code, so it should be relatively quick to simulate even for 1 second, but if you start adding code, the time taken to simulate a clock cycle of 2 Hz could be significantly long.

EDIT: clk_2Hz_i is used to buffer the output signal. VHDL doesn't like to use a signal on the right of an assignment when it is also an output.