----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    15:29:59 11/01/2013 
-- Design Name: 
-- Module Name:    command_processor - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
library UNISIM;
use UNISIM.VComponents.all;


entity command_processor is
  port (
		clk									: in  std_logic;
		command_available					: in  std_logic;
		command_contents					: in  std_logic_vector(31 downto 0);
		command_reply_available			: out std_logic;
		command_reply_contents			: out std_logic_vector(31 downto 0);
		firmware_version					: in  std_logic_vector(15 downto 0);
		hdw_cmd_busy						: out std_logic;
		command_busy						: out std_logic;
		GPIO_Switches						: in  std_logic_vector(7 downto 0);
		GPIO_Buttons						: in  std_logic_vector(4 downto 0);
		Disp_seg								: out std_logic_vector(7 downto 0);
		Disp_an								: out std_logic_vector(3 downto 0)
	);
end command_processor;


architecture Behavioral of command_processor is

-- Hardware controller -------------------------------------------------

	component hardware_controller
	port (
--		reset									: in  std_logic;
		clk									: in  std_logic;
		hdw_cmd_available					: in  std_logic;
		fifo_target							: in  std_logic_vector(3 downto 0);
		fifo_cmd								: in  std_logic_vector(7 downto 0);
		fifo_data							: in  std_logic_vector(19 downto 0);
		hdw_cmd_busy						: out std_logic;
		hdw_reply							: out std_logic_vector(31 downto 0);
		firmware_version					: in  std_logic_vector(15 downto 0);
		GPIO_Switches						: in  std_logic_vector(7 downto 0);
		GPIO_Buttons						: in  std_logic_vector(4 downto 0);
		Disp_seg								: out std_logic_vector(7 downto 0);
		Disp_an								: out std_logic_vector(3 downto 0)
	);
	end component;
	

	signal fifo_target							: std_logic_vector(3 downto 0);
	signal fifo_cmd								: std_logic_vector(7 downto 0);
	signal fifo_data								: std_logic_vector(19 downto 0);
	
	signal hdw_cmd_available					: std_logic := '0';
	signal hdw_cmd_busy_i						: std_logic;
	signal hdw_reply								: std_logic_vector(31 downto 0);
	
	
	type   fifo_do_cmd_type is (idle, selTarget, targetErr, hdwCmd, hdwCmd2, hdwCmd3, sendReply);
	signal fifo_do_cmd_state					: fifo_do_cmd_type := idle;
		
	signal command_busy_i						: std_logic := '0';
	signal command_reply_contents_i			: std_logic_vector(31 downto 0) := x"00000000";
	signal command_reply_available_i			: std_logic := '0';
	
begin
	hdw_cmd_busy <= hdw_cmd_busy_i;
	command_busy <= command_busy_i;
	command_reply_contents <= command_reply_contents_i;
	command_reply_available <= command_reply_available_i;

	fifo_target <= command_contents(31 downto 28);
	fifo_cmd <= command_contents(27 downto 20);
	fifo_data <= command_contents(19 downto 0);
	
	

-- hardware processes ------------------------------------------------------


	hardware_controller_0: hardware_controller
	port map (
--		reset									=> reset,
		clk									=> clk,
		hdw_cmd_available					=> hdw_cmd_available,
		fifo_target							=> fifo_target,
		fifo_cmd								=> fifo_cmd,
		fifo_data							=> fifo_data,
		hdw_cmd_busy						=> hdw_cmd_busy_i,
		hdw_reply							=> hdw_reply,
		firmware_version					=> firmware_version,
		GPIO_Switches						=> GPIO_Switches,
		GPIO_Buttons						=> GPIO_Buttons,
		Disp_seg								=> Disp_seg,
		Disp_an								=> Disp_an
	);
	

-------------------------------------------------------------------

	do_cmd_proc: process(clk)
	begin
		if (rising_edge(clk)) then
			hdw_cmd_available <= '0';
			command_reply_available_i <= '0';
			
			case fifo_do_cmd_state is
			
				when idle =>
					if (command_available = '1') then
						fifo_do_cmd_state <= selTarget;
						command_busy_i <= '1';
					else
						fifo_do_cmd_state <= idle;
						command_busy_i <= '0';
					end if;

				when selTarget =>
					case fifo_target is
						when x"1" =>
							fifo_do_cmd_state <= hdwCmd;
							
						when others =>
							fifo_do_cmd_state <= targetErr;
					end case;
				
				
				when targetErr =>
					command_reply_contents_i <= "1" & fifo_target(2 downto 0) & fifo_cmd & fifo_data;
					fifo_do_cmd_state <= sendReply;
				
				
				when hdwCmd =>									-- wait hdw start
					hdw_cmd_available <= '1';
					if (hdw_cmd_busy_i = '0') then
						fifo_do_cmd_state <= hdwCmd;
					else
						fifo_do_cmd_state <= hdwCmd2;
					end if;
				
				when hdwCmd2 =>								-- wait hdw stop
					if (hdw_cmd_busy_i = '1') then
						fifo_do_cmd_state <= hdwCmd2;
					else
						fifo_do_cmd_state <= hdwCmd3;
					end if;
				
				when hdwCmd3 =>								-- send hdw reply
					command_reply_contents_i <= hdw_reply;
					fifo_do_cmd_state <= sendReply;
				
				
				when sendReply =>
					command_reply_available_i <= '1';
					fifo_do_cmd_state <= idle;
				
			end case;
		end if;
	end process do_cmd_proc;

end Behavioral;

