Solution to the HEX Counter Problem


This is the solution I came up with for the HEX Counter problem. The drawing on the right is the "logical" schematic of the result.

The specification called for an 8 bit counter that displayed its count on two hexadecimal displays. The input is again 24Mhz and the counter operates at 10Hz. 

Things I learned from this project:

  • I learned that Synopsys FPGA Express doesn't allow you to specify constants in entity instances.
  • I originally was going to count in decimal, but that is a bit more difficult :-)
  • More complicated circuits are easier if you decompose them into functional blocks.
  • You can't gate a clock with an AND function in the process block.
In the schematic above, the various logical parts are labeled as they are in the VHDL code. The CLOCK_10HZ part is "U1", the HEX_DISPLAY parts are "U2" and "U3." The process block that defines the counter is labeled "INCREMENT."

Note that the BLANK and TEST inputs are not connected. In the VHDL code I had to use a bogus signal declaration in order to achieve that effect. With the WebPACK compiler (XST VHDL) you can just put the constant '0' or '1' in the port map and it does the right thing with them.

VHDL Source Code for the Hex Counter

-- Project 4                               Chuck McManis
--
-- This is a two digit hex counter with direction control
-- and start/stop control. 
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity hex_counter is
    Port ( src_clk : in std_logic;
           dir : in std_logic;
           run : in std_logic;
           clr : in std_logic;
           display0 : out std_logic_vector(6 downto 0);
           display1 : out std_logic_vector(6 downto 0));
end hex_counter;

-- This version was synthesized with the Synopsys VHDL compiler. It was failing
-- in a mysterious way when I had the run pin controlling the clock sensitivity
-- loop. I had expected that it would simply put the clock through an AND gate
-- before driving the counter but that was not what happened. 

architecture behavioral of hex_counter is

	component hex_display port (
		test, blank : in std_logic;
		data : in std_logic_vector(3 downto 0);
		segs : out std_logic_vector(6 downto 0));
	end component;
	
	component clock_10hz port (
		clk_in, reset : in std_logic;
		clk_out : out std_logic);
	end component;

	signal clk : std_logic;
	signal count : std_logic_vector(7 downto 0);
	-- bogus
	signal xx : std_logic;
	
begin
	xx <= '0'; -- this is a "false" constant...
	-- create instances of the clock divider and displays, and then attach
	-- them to the signals we are using.
	u1: clock_10hz port map (clk_in => src_clk, clk_out => clk, reset => clr);
	u2: hex_display port map (test => xx, blank => xx, 
			data => count(7 downto 4), segs => display0);
	u3: hex_display port map (test => xx, blank => xx,
			data => count(3 downto 0), segs => display1);

    increment: process (clk, clr, run, dir) is
    begin
	if (clr = '0') then
	    count <= "00000000";
	elsif rising_edge(clk) then
	    if (run = '1') then
		if (dir = '1') then
		    count <= count + "00000001";
		else
		    count <= count - "00000001";
		end if;
	    end if;
	end if;
    end process;

-- This version of the if loop fails to synthesize. Why? The XST compiler
-- generates logic for it.
--
--	elsif (rising_edge(clk) and (run = '1')) then
--  	    if (dir = '1') then
--		count <= count + "00000001";
--	    else
--		count <= count - "00000001";
--	    end if;
--	end if;

end behavioral;