-------------------------------------------------------------------------------
--	FILE:			BASYS_7_seg.vhd
--
--	DESCRIPTION:	This design is used to control the 7 segment display on  
--					the BASYS 2 or 3 FPGA development board.
--
-- 	ENGINEER:		Jordan Christman
-------------------------------------------------------------------------------
-- Libraries
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Entity
entity Seg_Display_16 is
generic(
	input_clk_freq	: integer := 100000000;	-- Input clock rate in Hz
	refresh_rate 	: integer := 50000);    -- Refresh rate in Hz
port(
	-- 7 Segment Display Output
	seg 			: out std_logic_vector(6 downto 0);	
	-- 7 Segment Display Decimal Point
	dp				: out std_logic;
    -- Selects Digit	
	an				: out std_logic_vector(15 downto 0);
	-- Input segments 0 through 3
	digit_1 		: in std_logic_vector(6 downto 0);
	digit_2 		: in std_logic_vector(6 downto 0);
	digit_3 		: in std_logic_vector(6 downto 0);
	digit_4 		: in std_logic_vector(6 downto 0);
	digit_5			: in std_logic_vector(6 downto 0);
	digit_6 		: in std_logic_vector(6 downto 0);
	digit_7 		: in std_logic_vector(6 downto 0);
	digit_8 		: in std_logic_vector(6 downto 0);
	digit_9 		: in std_logic_vector(6 downto 0);
	digit_10 		: in std_logic_vector(6 downto 0);
	digit_11 		: in std_logic_vector(6 downto 0);
	digit_12		: in std_logic_vector(6 downto 0);
	digit_13 		: in std_logic_vector(6 downto 0);
	digit_14 		: in std_logic_vector(6 downto 0);
	digit_15 		: in std_logic_vector(6 downto 0);
	digit_16 		: in std_logic_vector(6 downto 0);
	-- Input decimal points
	-- in_dp			: in std_logic_vector(15 downto 0);
	-- Input Clock
	clk				: in std_logic);
end Seg_Display_16;

architecture behavior of Seg_Display_16 is
-------------------------------------------------------------------------------
-- 								Constants
-------------------------------------------------------------------------------
-- 7 Seg display counter mulitply by 4 to take the 4 segments in account
constant maxcount	: integer := (input_clk_freq / refresh_rate) * 16;	

-------------------------------------------------------------------------------
-- 								Signals
-------------------------------------------------------------------------------
-- A 27-bit counter is required to count to 100000000 (100 million/ 100 MHz)
-- we will be counting to 200,000 to achieve a 500Hz refresh rate 
signal counter	: unsigned(26 downto 0) := to_unsigned(0, 27);

-- toggle is used to select which segment is currently being displayed
signal toggle	: std_logic_vector(15 downto 0) := "0000000000000001";
constant in_dp	: std_logic_vector(15 downto 0) := x"FFFF";
signal seg_reg  : std_logic_vector(6 downto 0) := "000" & x"0";

-------------------------------------------------------------------------------
-- 					BASYS (2/3) 7 SEGMENT DISPLAY ARCHITECTURE
-------------------------------------------------------------------------------
begin
	-- Anode segment drivers
	an <= toggle;
	seg <= seg_reg;
	
	---------------------------------------------------------------------------
	-- 							COUNTER PROCESS
	---------------------------------------------------------------------------
	-- Counter to create desired multiplexed rate and shift toggle bits
	counter_proc: process(clk)
	begin
		if(rising_edge(clk)) then
			if(counter = maxcount) then
				counter <= (others => '0');
				toggle(0) <= toggle(15);
				toggle(1) <= toggle(0);
				toggle(2) <= toggle(1);
				toggle(3) <= toggle(2);
				toggle(4) <= toggle(3);
				toggle(5) <= toggle(4);
				toggle(6) <= toggle(5);
				toggle(7) <= toggle(6);
				toggle(8) <= toggle(7);
				toggle(9) <= toggle(8);
				toggle(10) <= toggle(9);
				toggle(11) <= toggle(10);
				toggle(12) <= toggle(11);
				toggle(13) <= toggle(12);
				toggle(14) <= toggle(13);
				toggle(15) <= toggle(14);
			else
				counter <= counter + 1;
			end if;
		end if;
	end process counter_proc;	
	
	---------------------------------------------------------------------------
	-- 							TOGGLE PROCESS
	---------------------------------------------------------------------------
	-- Toggle the seven segment displays by selecting the next segments display
	toggle_proc: process(toggle)
	begin
		-- Digit 1
		if(toggle(0) = '1') then
			seg_reg <= digit_1;
			dp <= in_dp(0);
		-- Digit 2
		elsif(toggle(1) = '1') then
			seg_reg <= digit_2;
			dp <= in_dp(1);
		-- Digit 3
		elsif(toggle(2) = '1') then
			seg_reg <= digit_3;
			dp <= in_dp(2);
		-- Digit 4
		elsif(toggle(3) = '1') then
			seg_reg <= digit_4;
			dp <= in_dp(3);
		-- Digit 5
		elsif(toggle(4) = '1') then
			seg_reg <= digit_5;
			dp <= in_dp(4);
		-- Digit 6
		elsif(toggle(5) = '1') then
			seg_reg <= digit_6;
			dp <= in_dp(5);
		-- Digit 7
		elsif(toggle(6) = '1') then
			seg_reg <= digit_7;
			dp <= in_dp(6);
		-- Digit 8
		elsif(toggle(7) = '1') then
			seg_reg <= digit_8;
			dp <= in_dp(7);
		-- Digit 9
		elsif(toggle(8) = '1') then
			seg_reg <= digit_9;
			dp <= in_dp(8);
		-- Digit 10
		elsif(toggle(9) = '1') then
			seg_reg <= digit_10;
			dp <= in_dp(9);
		-- Digit 11
		elsif(toggle(10) = '1') then
			seg_reg <= digit_11;
			dp <= in_dp(10);
		-- Digit 12
		elsif(toggle(11) = '1') then
			seg_reg <= digit_12;
			dp <= in_dp(11);
		-- Digit 13
		elsif(toggle(12) = '1') then
			seg_reg <= digit_13;
			dp <= in_dp(12);
		-- Digit 14
		elsif(toggle(13) = '1') then
			seg_reg <= digit_14;
			dp <= in_dp(13);
		-- Digit 15
		elsif(toggle(14) = '1') then
			seg_reg <= digit_15;
			dp <= in_dp(14);
		-- Digit 16
		else
			seg_reg <= digit_16;
			dp <= in_dp(15);
		end if;
	end process toggle_proc;
end behavior;