--
-- VHDL Architecture FACT_FAD_lib.mod7.beha
--
-- Created:
--          by - dneise.UNKNOWN (E5B-LABOR6)
--          at - 09:55:28 16.02.2011
--
-- using Mentor Graphics HDL Designer(TM) 2009.2 (Build 10)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
--USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;

ENTITY mod7 IS
	PORT( 
			clk            : IN     std_logic;
			
			number	: in std_logic_vector(31 downto 0);
			start : in std_logic;
	
			remainder : out std_logic_vector(2 downto 0) := (others => '0');
			started : out std_logic := '0';
			valid : out std_logic :='0'
			);
END ENTITY mod7;

--
ARCHITECTURE beha OF mod7 IS
	signal local_number : std_logic_vector (32 downto 0) := (OTHERS => '0'); --33bit number, easy to divide into 3bit-words
	
	type state_type is (
							IDLE_STATE, 
							SUBMOD1_STATE,
							SUM1_STATE,
							SUBMOD2_STATE,
							SUM2_STATE,
							SUBMOD3_STATE,
							SUM3_STATE,
							RESULT_STATE);

	signal state : state_type := IDLE_STATE;
	
	signal sum1  : std_logic_vector (8 downto 0) := (OTHERS => '0'); -- eigentlich reichen 7bit, aber 9 lassen sich leichter teilen
	signal sum2  : std_logic_vector (5 downto 0) := (OTHERS => '0'); -- eigentlich reichen 4 bit, aber 6 lassen sich leichter teilen
	signal sum3  : std_logic_vector (2 downto 0) := (OTHERS => '0'); 
	signal result  : std_logic_vector (2 downto 0) := (OTHERS => '0'); 
	
	type sm1_type is	array (0 to 10) of std_logic_vector (8 downto 0);  -- eigentlich sind es 3 bit werte, aber wenn ich summiere brauche ich die breite (fast)
	type sm2_type is	array (0 to 2) of std_logic_vector (5 downto 0); -- eigentlich sind es 3 bit werte, aber wenn ich summiere brauche ich die breite (fast)
	type sm3_type is	array (0 to 1) of std_logic_vector (2 downto 0);
	
		
	signal submod1 : sm1_type := (others => "000000000");
	signal submod2 : sm2_type := (others => "000000");
	signal submod3 : sm3_type := (others => "000");
	
	
BEGIN
	remainder <= result;
	
	process (clk)
		begin

			
			if rising_edge(clk) then
			
				case state is
					
					when IDLE_STATE =>
						started		<= '0';
						if (start = '1') then 
							started		<= '1';
							valid		<= '0';
							local_number <= '0' & number;
							state <= SUBMOD1_STATE;
						else 
							state <= IDLE_STATE;
						end if;

					when SUBMOD1_STATE =>
						for i in 0 to 10 loop
							if (local_number( 3*i+2 downto 3*i ) = "111" ) then
								submod1(i) <= "000000000";
							else
								submod1(i) <= "000000" & local_number( 3*i+2 downto 3*i );
							end if;
						end loop;
						state <= SUM1_STATE;

					when SUM1_STATE =>
						sum1 <= submod1(0) +
										submod1(1) + 
										submod1(2) + 
										submod1(3) + 
										submod1(4) + 
										submod1(5) + 
										submod1(6) + 
										submod1(7) + 
										submod1(8) + 
										submod1(9) + 
										submod1(10);
						
						state <= SUBMOD2_STATE;
										 
					when SUBMOD2_STATE =>
      					for i in 0 to 2 loop
      						if (sum1( 3*i+2 downto 3*i ) = "111" ) then
      							submod2(i) <= "000000";
      						else
      							submod2(i) <= "000" & sum1( 3*i+2 downto 3*i );
      						end if;
      					end loop;
      					state <= SUM2_STATE;

					when SUM2_STATE =>
						sum2 <= submod2(0) +	submod2(1) +  submod2(2);
						state <= SUBMOD3_STATE;

					when SUBMOD3_STATE =>
						for i in 0 to 1 loop
							if (sum2( 3*i+2 downto 3*i ) = "111" ) then
								submod3(i) <= "000";
							else
								submod3(i) <= sum2( 3*i+2 downto 3*i );
							end if;
						end loop;
						state <= SUM3_STATE;

					when SUM3_STATE =>
						sum3 <= submod3(0) +	submod3(1);
						state <= RESULT_STATE; 

					when RESULT_STATE =>
						started		<= '0';
						valid		<= '1';
						if (sum3( 2 downto 0 ) = "111" ) then
							result <= "000";
						else
							result <= sum3( 2 downto 0 );
						end if;
						state <= IDLE_STATE; 
					
					when others =>
						null;
					end case;
					
			end if;
		end process;
				
END ARCHITECTURE beha;
	
