TITLE: 10 Hz Clock Source
AUTHOR: Chuck McManis
LAST UPDATE: 6-Mar-2001

Description

This was the solution I came up with (about the third iteration however) for my simple clock chip exercise. Again the specification is to take a 24Mhz clock input and output a 10Hz square wave. A schematic symbol for this "chip" is shown on the right. The interesting things I learned on this first step of the FPGA journey were:

  • You can only assign once in a process.
  • The WebPACK tools are pretty cool and easy to use.
  • You can't use I/O pins in your implementation to hold state, instead you have to assign them to connect to the signal lines in the model that do hold state.

Figure 1: 10Hz Clock 'unit'

The Source Code

-- 10HZ CLOCK GENERATOR                                    Chuck McManis, 6-Mar-2001
--
-- This is a simple "clock generation" circuit for the Xilinx FPGA series
-- chips. 
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

--
-- Standard clock with a reset pin
--      clk_in  This is the source clock, on the SPARTAN+ board its 24Mhz
--      clk_out This is the "generated" clock, in this case fixed at 10hz
--      reset       This stops the clock, forces its output "high"
--
entity clock_10hz is
    Port ( reset : in std_logic;
           clk_in : in std_logic;
           clk_out : out std_logic);
end clock_10hz;

-- Generate a 10Hz clock derived from a 24Mhz clock. This is done by dividing
-- 24Mhz by 1,200,000 and flipping a bit each time it reaches that value.
architecture behavioral of clock_10hz is

    -- Signal declartions, one counter and one "bit" register.
    -- Counter is 21 bits so that it can count to 1,199,999.
    signal clk_cnt : unsigned(20 downto 0);
    signal clk_bit : std_logic;

begin
    gen_clock: process (clk_in, reset) is
    begin
        -- Asynchronouse RESET forces clock state to 0
        if (reset = '0') then
            clk_cnt <= "000000000000000000000";
            clk_bit <= '0';
       elsif rising_edge(clk_in) then
            -- Divisor is 12E5 (24Mhz -> 10Hz) using 1,199,999 because
            -- at the "next" state we want it to reset to zero. 
            if (clk_cnt = 1199999) then
                clk_cnt <= "000000000000000000000";
                clk_bit <= not clk_bit;
            else
                clk_cnt <= clk_cnt + 1;
            end if;
        end if;
    end process;

    -- concurrent assignment to connect CLK to clk_out, this acts as a wire
    -- to bond the clk_out signal to the clk pin.
    clk_out <= clk_bit;

end behavioral;

License

This code is public domain, I can't vouch for it actually working but I've played with it quite a bit. No warranty expressed or implied, use at your own risk.