10Hz Clock Chip Solution


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. 

VHDL Source code for 10Hz Clock Generation Chip

-- 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 declarations, 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
	-- Asynchronous 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;