library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity User_Interface_v1_0 is
	generic (
		-- Users to add parameters here

		-- User parameters ends
		-- Do not modify the parameters beyond this line


		-- Parameters of Axi Slave Bus Interface S00_AXI
		C_S00_AXI_DATA_WIDTH	: integer	:= 32;
		C_S00_AXI_ADDR_WIDTH	: integer	:= 4
	);
	port (
		-- Users to add ports here
        clk : in std_logic;
        btnl : in std_logic;
        btnr : in std_logic;
        btnu : in std_logic;
        btnd : in std_logic;
        btnc : in std_logic;
        run : out std_logic;
        requested_speed : out std_logic_vector (15 downto 0);
        leds : out std_logic_vector (7 downto 0);
		-- User ports ends
		-- Do not modify the ports beyond this line


		-- Ports of Axi Slave Bus Interface S00_AXI
		s00_axi_aclk	: in std_logic;
		s00_axi_aresetn	: in std_logic;
		s00_axi_awaddr	: in std_logic_vector(C_S00_AXI_ADDR_WIDTH-1 downto 0);
		s00_axi_awprot	: in std_logic_vector(2 downto 0);
		s00_axi_awvalid	: in std_logic;
		s00_axi_awready	: out std_logic;
		s00_axi_wdata	: in std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0);
		s00_axi_wstrb	: in std_logic_vector((C_S00_AXI_DATA_WIDTH/8)-1 downto 0);
		s00_axi_wvalid	: in std_logic;
		s00_axi_wready	: out std_logic;
		s00_axi_bresp	: out std_logic_vector(1 downto 0);
		s00_axi_bvalid	: out std_logic;
		s00_axi_bready	: in std_logic;
		s00_axi_araddr	: in std_logic_vector(C_S00_AXI_ADDR_WIDTH-1 downto 0);
		s00_axi_arprot	: in std_logic_vector(2 downto 0);
		s00_axi_arvalid	: in std_logic;
		s00_axi_arready	: out std_logic;
		s00_axi_rdata	: out std_logic_vector(C_S00_AXI_DATA_WIDTH-1 downto 0);
		s00_axi_rresp	: out std_logic_vector(1 downto 0);
		s00_axi_rvalid	: out std_logic;
		s00_axi_rready	: in std_logic
	);
end User_Interface_v1_0;

architecture arch_imp of User_Interface_v1_0 is
    
    signal run_temp : std_logic := '0';
    
	-- component declaration
	component User_Interface_v1_0_S00_AXI is
		generic (
		C_S_AXI_DATA_WIDTH	: integer	:= 32;
		C_S_AXI_ADDR_WIDTH	: integer	:= 4
		);
		port (
		S_AXI_ACLK	: in std_logic;
		S_AXI_ARESETN	: in std_logic;
		S_AXI_AWADDR	: in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
		S_AXI_AWPROT	: in std_logic_vector(2 downto 0);
		S_AXI_AWVALID	: in std_logic;
		S_AXI_AWREADY	: out std_logic;
		S_AXI_WDATA	: in std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
		S_AXI_WSTRB	: in std_logic_vector((C_S_AXI_DATA_WIDTH/8)-1 downto 0);
		S_AXI_WVALID	: in std_logic;
		S_AXI_WREADY	: out std_logic;
		S_AXI_BRESP	: out std_logic_vector(1 downto 0);
		S_AXI_BVALID	: out std_logic;
		S_AXI_BREADY	: in std_logic;
		S_AXI_ARADDR	: in std_logic_vector(C_S_AXI_ADDR_WIDTH-1 downto 0);
		S_AXI_ARPROT	: in std_logic_vector(2 downto 0);
		S_AXI_ARVALID	: in std_logic;
		S_AXI_ARREADY	: out std_logic;
		S_AXI_RDATA	: out std_logic_vector(C_S_AXI_DATA_WIDTH-1 downto 0);
		S_AXI_RRESP	: out std_logic_vector(1 downto 0);
		S_AXI_RVALID	: out std_logic;
		S_AXI_RREADY	: in std_logic
		);
	end component User_Interface_v1_0_S00_AXI;

begin

-- Instantiation of Axi Bus Interface S00_AXI
User_Interface_v1_0_S00_AXI_inst : User_Interface_v1_0_S00_AXI
	generic map (
		C_S_AXI_DATA_WIDTH	=> C_S00_AXI_DATA_WIDTH,
		C_S_AXI_ADDR_WIDTH	=> C_S00_AXI_ADDR_WIDTH
	)
	port map (
		S_AXI_ACLK	=> s00_axi_aclk,
		S_AXI_ARESETN	=> s00_axi_aresetn,
		S_AXI_AWADDR	=> s00_axi_awaddr,
		S_AXI_AWPROT	=> s00_axi_awprot,
		S_AXI_AWVALID	=> s00_axi_awvalid,
		S_AXI_AWREADY	=> s00_axi_awready,
		S_AXI_WDATA	=> s00_axi_wdata,
		S_AXI_WSTRB	=> s00_axi_wstrb,
		S_AXI_WVALID	=> s00_axi_wvalid,
		S_AXI_WREADY	=> s00_axi_wready,
		S_AXI_BRESP	=> s00_axi_bresp,
		S_AXI_BVALID	=> s00_axi_bvalid,
		S_AXI_BREADY	=> s00_axi_bready,
		S_AXI_ARADDR	=> s00_axi_araddr,
		S_AXI_ARPROT	=> s00_axi_arprot,
		S_AXI_ARVALID	=> s00_axi_arvalid,
		S_AXI_ARREADY	=> s00_axi_arready,
		S_AXI_RDATA	=> s00_axi_rdata,
		S_AXI_RRESP	=> s00_axi_rresp,
		S_AXI_RVALID	=> s00_axi_rvalid,
		S_AXI_RREADY	=> s00_axi_rready
	);

	-- Add user logic here
    process (clk)        
        variable cnt : integer := 0;
        variable speed_temp : signed (12 downto 0) := (others => '0');
        variable sign : signed (1 downto 0);         
    begin
        if (clk'event and clk='1') then
            if (cnt = 0) then
                if (btnu='1' and speed_temp<to_signed(3500,13)) then
                   speed_temp := speed_temp + to_signed(100,13);
                   cnt := 10000000; 
                elsif (btnd='1' and speed_temp>to_signed(0,13)) then
                   speed_temp := speed_temp - to_signed(100,13);
                   cnt := 10000000;  
                end if;        
                if (btnc='1') then
                   run_temp <= not run_temp;
                   cnt := 20000000;  
                end if;
                
            elsif (cnt > 0) then
                cnt := cnt - 1;                         
            end if;
            
            if (btnl='1') then
                sign := to_signed(1,2);
            elsif (btnr='1') then
                sign := to_signed(-1,2);
            end if;  
            
            if (speed_temp >= to_signed(3500,13)) then
                leds(7 downto 1) <= "1111111";
            elsif (speed_temp >= to_signed(3000,13)) then
                leds(7 downto 1) <= "0111111";
            elsif (speed_temp >= to_signed(2500,13)) then
                leds(7 downto 1) <= "0011111";   
            elsif (speed_temp >= to_signed(2000,13)) then
                leds(7 downto 1) <= "0001111";
            elsif (speed_temp >= to_signed(1500,13)) then
                leds(7 downto 1) <= "0000111";
            elsif (speed_temp >= to_signed(1000,13)) then
                leds(7 downto 1) <= "0000011"; 
            elsif (speed_temp >= to_signed(500,13)) then
                leds(7 downto 1) <= "0000001";
            else
                leds(7 downto 1) <= "0000000";
            end if;
            leds(0) <= run_temp;
            run <= run_temp;                            
            requested_speed <= std_logic_vector(resize(speed_temp*sign,16));             
        end if;
    end process;
	-- User logic ends

end arch_imp;
