-----------------------------------------------------------------------------
---                                                                  
---                                                           Up Down Counter
-----------------------------------------------------------------------------
--- File Name:  top_level.vhd
---
--- Description:
--- This block is the top level for the UP/Down counter
--- 
--- This block is for the simple logic to manage the up down counter. The
--- counter is to run on the lattice ispExpert board. This is just the
--- same as the example that is given on the lattice site. This version is
--- just written entirly from VHDL and is to test that the tools will do
--- as expected. (before I spend a lot of time and effort using tnem to
--- out they dont work.
---
--- The one difference between the Lattice implimentation and this one is
--- the clock wont start running until one of the up or down buttons have
--- been pressed.
---
--- Limitations:
--- The pin assignments have to be done by the lattice tools. They cannot
--- be specified here.
---
--- Errors:
---  None known.
---
--- Dependancies:
---  None.
---
--- Current Target: M4-32/64
--- Simulator:      Symphony EDA - Sonata
--- Target Builder: Latice ispExpert
---
--- Author: Peter Antoine       Date: 07 Jul 2004
----------------------------------------------------------------------------
---                                         Copyright (c) 2004 Peter Antoine
----------------------------------------------------------------------------
--- Version   Author Date        Changes
--- -------   ------ ----------  -------------------------------------------
--- 0.1       PA     07.07.2004  Initial revision
--- 1.0       PA     08.07.2004  Working version. This Lattice board sets
---                              the lines low for the leds and the decoder
---                              was also wrong. This version has been run.
----------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;

entity counter is
    port (  clock   : in std_logic;
            reset   : in std_logic;
            dec     : in std_logic;
            count   : out std_logic_vector(11 downto 0));
end entity counter;

architecture rtl of counter is

    signal int_count : std_logic_vector (11 downto 0);

    ----------------------------------------------------
    --- decrement
    ---
    --- This function will decrement the counter
    ----------------------------------------------------
    procedure decrement (   signal  din :   in  std_logic_vector (11 downto 0);
                                    dout:   out std_logic_vector (11 downto 0)) is

        variable x : std_logic := '1';
    begin
        x := '0';

        for i in 0 to 11 loop

            dout(i) := din(i) xnor x;

            x := x or din(i);
        end loop;

    end decrement;

    ----------------------------------------------------
    --- increment
    ---
    --- This function will increment the counter
    ----------------------------------------------------
    procedure increment (   signal  din :   in  std_logic_vector(11 downto 0);
                                    dout:   out std_logic_vector(11 downto 0)) is

        variable x : std_logic := '1';
    begin
        x := '1';

        for i in 0 to 11 loop

            dout(i) := din(i) xor x;

            x := x and din(i);
        end loop;

    end increment;

begin

    --- reset case
    count <= (others => '0') when reset = '1' else int_count;

    process (clock,reset,dec)
        variable tcount : std_logic_vector(11 downto 0);
    begin
        if (reset = '1') then
            tcount := (others => '0');

        elsif (clock'event and clock = '1') then
            if (dec = '0') then
                increment(int_count,tcount);
            else
                decrement(int_count,tcount);
            end if;
        end if;

        int_count <= tcount;
    end process;

end architecture rtl;

library IEEE;
use IEEE.std_logic_1164.all;

entity eight_seg_decoder is
    port( input : in std_logic_vector (3 downto 0);
            seg_disp: out std_logic_vector (7 downto 0));
end eight_seg_decoder;

architecture esd_behv of eight_seg_decoder is
begin
    process (input)
    begin
        case input is
            when "0000" => seg_disp <= "11000000";      -- 0
            when "0001" => seg_disp <= "11111001";      -- 1
            when "0010" => seg_disp <= "10100100";      -- 2
            when "0011" => seg_disp <= "10110000";      -- 3
            when "0100" => seg_disp <= "10011001";      -- 4
            when "0101" => seg_disp <= "10010010";      -- 5
            when "0110" => seg_disp <= "10000010";      -- 6
            when "0111" => seg_disp <= "11111000";      -- 7
            when "1000" => seg_disp <= "10000000";      -- 8
            when "1001" => seg_disp <= "10011000";      -- 9
            when "1010" => seg_disp <= "10001000";      -- a
            when "1011" => seg_disp <= "10000011";      -- b
            when "1100" => seg_disp <= "11000110";      -- c
            when "1101" => seg_disp <= "10100001";      -- d
            when "1110" => seg_disp <= "10000110";      -- e
            when "1111" => seg_disp <= "10001110";      -- f
            when others => seg_disp <= "11111111";
        end case;
    end process;
end esd_behv;


library ieee;
use ieee.std_logic_1164.all;

entity UpDownCounter is
    port (  reset   : in std_logic;
            clock   : in std_logic;
            up      : in std_logic;
            down    : in std_logic;
            seg_1   : out std_logic_vector(7 downto 0);
            seg_2   : out std_logic_vector(7 downto 0);
            seg_3   : out std_logic_vector(7 downto 0));
end entity UpDownCounter;

architecture rtl of UpDownCounter is

    component counter
        port (  clock   : in std_logic;
                reset   : in std_logic;
                dec     : in std_logic;
                count   : out std_logic_vector(11 downto 0));
    end component counter;

    component eight_seg_decoder
        port(   input   : in std_logic_vector (3 downto 0);
                seg_disp: out std_logic_vector (7 downto 0));
    end component eight_seg_decoder;

    --- internal signals
    signal int_count    : std_logic_vector(11 downto 0);
    signal decrement    : std_logic;
    signal reset_reg    : std_logic;
    signal button_state : std_logic;
    signal int_clock    : std_logic;

begin

    --- wait for one of the buttons the be pressed (go low)
    button_state <= reset and up and down;
    int_clock    <= not reset_reg and clock;

    process (button_state,reset,up,down)
    begin
        if (button_state'event and button_state = '0') then

            if (reset = '0') then
                reset_reg <= '1';
                decrement <= '0';

            elsif (up = '0') then
                reset_reg <= '0';
                decrement <= '0';

            else
                reset_reg <= '0';
                decrement <= '1';
            end if;

        end if;
    end process;

    udcnt:  counter port map(clock=>int_clock,reset=>reset_reg,dec=>decrement,count=>int_count);

    seg1:   eight_seg_decoder port map(input=>int_count(11 downto 8),seg_disp=>seg_1);
    seg2:   eight_seg_decoder port map(input=>int_count(7 downto 4),seg_disp=>seg_2);
    seg3:   eight_seg_decoder port map(input=>int_count(3 downto 0),seg_disp=>seg_3);


end architecture rtl;

--- vi:ai:nocin:ts=4 sw=4