Problem Set 4

-- problemset4_1.vhd

--	Problem 1 (/option)

library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;

entity problem1 is
  port (keypad : in std_logic_vector (9 downto 0); -- the keypad inputs
  	openin : in std_logic;		-- high when the door is open
  	warning : out std_logic;	-- high for 'buzzer'
  	alarm : out std_logic;		-- high when 'alarm'
  	clk : in std_logic);		-- 1 Hz clock
end entity problem1;

architecture fsm of problem1 is
  
  type state is (idle, first, second, third, OK, OKopen, troubleidle, troublefirst,
  	troublesecond, troublethird, alarmidle, alarmfirst, alarmsecond, alarmthird);
  signal n_s, p_s : state;
  signal count : std_logic;
  signal counter : std_logic_vector (4 downto 0);
   --put my signals here;
  
begin  

fsm : process (p_s, keypad, openin, counter)
begin  
  case p_s is
    when idle =>  	-- Waiting for something to happen
      alarm <= '0';
      warning <= '0';
      if keypad = "0010000000"  -- User enters 7
      	then n_s <= first;	
      	     count <= '0';	
      elsif openin = '1'	-- User opened door
        then n_s <= troubleidle;
             count <= '1';
      else n_s <= idle;
             count <= '0';
      end if;
      
    when first =>	-- First number has been entered
      alarm <= '0';
      warning <= '0';
      if openin = '1' 	-- User opened door
      	then n_s <= troublefirst;
      	     count <= '1';
      elsif keypad = "0000000000"	-- no input
        then n_s <= first;
             count <= '0';
      elsif keypad = "0010000000"	-- User enters second 7
        then n_s <= second;
             count <= '0';
      else n_s <= idle;		-- Some other input
	   count <= '0';
      end if;
      
    when second =>	-- Second number has been entered
      alarm <= '0';
      warning <= '0';
      if openin = '1' 	-- User opened door
        then n_s <= troublesecond;
             count <= '1';
      elsif keypad = "0000000000"	-- no input
        then n_s <= second;
             count <= '0';
      elsif keypad = "1000000000"	-- User enters third code number
        then n_s <= third;
             count <= '0';
      elsif keypad <= "0010000000"	-- This is the SECOND 7 in a row
        then n_s <= second;
             count <= '0';
      else n_s <= idle;		-- Some other input
           count <= '0';
      end if;
      
    when third =>	-- Third number has been entered
      alarm <= '0';
      warning <= '0';
      if openin = '1' 	-- User opened door
        then n_s <= troublethird;
             count <= '1';
      elsif keypad = "0000000000"	-- no input
        then n_s <= third;
             count <= '0';
      elsif keypad = "0000000010"	-- User enters third code number
        then n_s <= OK;
             count <= '0';
      else n_s <= idle;		-- Some other input
           count <= '0';
      end if;
    
    when OK =>		-- Code has been input
      alarm <= '0';
      warning <= '0';
      if openin = '1'	-- User opened door
        then n_s <= OKopen;
             count <= '0';
      else n_s <= OK;		-- Wait for user to open door
           count <= '0';
      end if;
      
    when OKopen =>	-- When code entered and then door open
      alarm <= '0';
      warning <= '0';
      if openin = '0'	-- Door closes
        then n_s <= idle;
             count <= '0';
      else n_s <= OKopen;	-- Wait for door to close
           count <= '0';
      end if;
      
    when troubleidle =>			-- No code entered but door was opened                  	          
      alarm <= '0';
      warning <= '1';
      if counter = "11110"
        then n_s <= alarmidle;
             count <= '0';
      elsif keypad = "0010000000"	-- User enters first code number
        then n_s <= troublefirst;
             count <= '1';
      else n_s <= troubleidle;  	-- Any other or no input
           count <= '1';
      end if;
      
    when troublefirst =>	-- First code entered, but door was opened
      alarm <= '0';
      warning <= '1';
      if counter = "11110"	-- If timer up to 30 s set off alarm
        then n_s <= alarmfirst;
             count <= '0';
      elsif keypad = "0000000000"	-- No input
        then n_s <= troublefirst;
             count <= '1';
      elsif keypad = "0010000000"	--  User enters second code number
        then n_s <= troublesecond;
             count <= '1';
      else n_s <= troubleidle;	-- Any other input
           count <= '1';
      end if;
      
    when troublesecond =>	-- Second code entered, but door was opened
      alarm <= '0';
      warning <= '1';
      if counter = "11110"	-- If timer up to 30 s set off alarm
        then n_s <= alarmsecond;
             count <= '0';
      elsif keypad = "0000000000"	-- No input
        then n_s <= troublesecond;
             count <= '1';
      elsif keypad = "0010000000"	--  User enters SECOND 7 in a row
        then n_s <= troublesecond;
             count <= '1';
      elsif keypad = "1000000000" --  User enters third code number
        then n_s <= troublethird;
             count <= '1';
      else n_s <= troubleidle;	--  Any other input
           count <= '1';
      end if;
      
    when troublethird =>	-- Third code entered, but door was opened
      alarm <= '0';
      warning <= '1';
      if counter = "11110"	-- If timer up to 30 s set off alarm
        then n_s <= alarmthird;
             count <= '0';
      elsif keypad = "0000000000"	-- No input
        then n_s <= troublethird;
             count <= '1';
      elsif keypad = "0000000010"	-- User enters final code number
        then if openin = '1'
               then n_s <= OKopen;
                    count <= '0';
               else n_s <= idle;
                    count <= '0';
             end if;
      else n_s <= troubleidle;	-- Any other input
           count <= '1';
      end if;
      
    when alarmidle =>		-- Alarm going off and no code entered
      alarm <= '1';
      warning <= '0';
      if keypad = "0010000000"	-- User inputs first code number
        then n_s <= alarmfirst;
             count <= '0';
      else n_s <= alarmidle;	-- Any other input or no input
           count <= '0';
      end if;
      
    when alarmfirst =>		-- First code entered but alarm going off
      alarm <= '1';
      warning <= '0';
      if keypad = "0010000000"	-- User inputs second code number
        then n_s <= alarmsecond;
             count <= '0';
      elsif keypad = "0000000000" 	-- No input
        then n_s <= alarmfirst;
             count <= '0';
        else n_s <= alarmidle;	-- Any other input
             count <= '0';
      end if;
      
    when alarmsecond =>		-- Second code entered but alarm going off
      alarm <= '1';
      warning <= '0';
      if keypad = "1000000000"  -- User inputs third code number
        then n_s <= alarmthird;
             count <= '0';
      elsif keypad = "0000000000"	-- No input
        then n_s <= alarmsecond;
             count <= '0';
      elsif keypad = "0010000000"	-- User inputs second code number
        then n_s <= alarmsecond;
             count <= '0';
      else n_s <= alarmidle;	-- Any other input
           count <= '0';
      end if;
     
    when alarmthird =>		-- Third code entered but alarm going off
      alarm <= '1';
      warning <= '0';
      if keypad = "0000000010"  -- User inputs final code number
        then if openin = '1'
               then n_s <= OKopen;
               	    count <= '0';
               else n_s <= idle;
                    count <= '0';
             end if;
      elsif keypad = "0000000000"	-- No input
        then n_s <= alarmthird;
             count <= '0';
        else n_s <= alarmidle;	-- Any other input
             count <= '0';
      end if;
  end case;
end process;

clocked : process (clk, count)
begin
  if rising_edge(clk)
    then p_s <= n_s;
         if count = '1'
           then counter <= counter + 1;
           else counter <= "00000";
         end if;
  end if;
end process;
end fsm;

-------------------------------------------------------
-- problemset4_2.vhd


-- Problem Set 4  Problem 2
library ieee;
use ieee.std_logic_1164.all;
use work.std_arith.all;

entity divider is port (a, b: in std_logic_vector(6 downto 0);
			start, clk: in std_logic;
                        q, r : out std_logic_vector (6 downto 0);
                        busy: out std_logic);
end divider;

architecture fsm of divider is
  type states is (idle, calc);
  signal state, n_state : states;
  signal remain, quo, div : std_logic_vector (6 downto 0);
  signal i : std_logic_vector (2 downto 0);
  
begin
  process (clk)
  variable rmndr : std_logic_vector (6 downto 0);
  begin 
    if rising_edge(clk) then
      case state is 
        when idle => 
          i <= "000";
          if start = '1' then
            n_state <= calc;
            busy <= '1';
            div <= a(5 downto 0) & '0';
            remain <= "000000" & a(6);
            quo <= "0000000";
          else
            n_state <= idle;
            busy <= '0';
            r <= remain;
            q <= quo;
          end if;
        when calc =>
          if remain >= b then
            quo <= quo(5 downto 0) & '1';
            rmndr := remain - b;
          else
            quo <= quo(5 downto 0) & '0';
            rmndr := remain;
          end if;
          div <= div(5 downto 0) & '0';
          if i = "110" then
            n_state <= idle;
            remain <= rmndr;
          else
            i <= i + 1;
            remain <= rmndr(5 downto 0) & div(6);
            busy <= '1';
            n_state <= calc;
          end if;
      end case;
    end if;
  end process;
    
  process(clk) 
  begin
    if falling_edge(clk) then
      state <= n_state;
    end if;
  end process;
end fsm;