--
-- VHDL Architecture FACT_FAD_lib.controlRAM_manager.beha
--
-- Created:
--          by - Benjamin Krumm.UNKNOWN (EEPC8)
--          at - 14:35:46 14.04.2010
--
-- using Mentor Graphics HDL Designer(TM) 2009.1 (Build 12)
--
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
LIBRARY FACT_FAD_LIB;
USE FACT_FAD_LIB.fad_definitions.ALL;

ENTITY control_manager IS
   GENERIC( 
      NO_OF_ROI  : integer := 36;
      NO_OF_DAC  : integer := 8;
      ADDR_WIDTH : integer := 8
   );
   PORT( 
      clk               : IN     std_logic;
      ram_data_out      : IN     std_logic_vector (15 DOWNTO 0);
      config_ready, config_started : OUT    std_logic := '0';
      config_start      : IN     std_logic;
      config_data       : INOUT  std_logic_vector (15 DOWNTO 0) := (others => 'Z');
      config_addr       : IN     std_logic_vector (ADDR_WIDTH - 1 DOWNTO 0);
      config_wr_en      : IN     std_logic;
      config_rd_en      : IN     std_logic;
      config_data_valid : OUT    std_logic := '0';
      config_busy       : OUT    std_logic := '0';
      ram_addr          : OUT    std_logic_vector (ADDR_WIDTH - 1 DOWNTO 0);
      ram_data_in       : OUT    std_logic_vector (15 DOWNTO 0);
      ram_write_en      : OUT    std_logic_vector (0 DOWNTO 0);
      dac_array         : OUT    dac_array_type;
      roi_array         : OUT    roi_array_type;
      drs_address       : OUT    std_logic_vector (3 DOWNTO 0);
      drs_address_mode  : OUT    std_logic
   );

-- Declarations

END control_manager ;

ARCHITECTURE beha OF control_manager IS
  
  type TYPE_CTRL_STATE is (CTRL_INIT, CTRL_IDLE, CTRL_WAIT_IDLE, CTRL_WRITE,
                           CTRL_LOAD_ADDR, CTRL_LOAD_WAIT, CTRL_LOAD_DATA, 
                           CTRL_READ_ADDR, CTRL_READ_WAIT, CTRL_READ_DATA);
  
  signal ctrl_state : TYPE_CTRL_STATE := CTRL_INIT;
  signal addr_cntr : integer range 0 to 2**ADDR_WIDTH - 1 := 0;
  signal int_dac_array : dac_array_type := DEFAULT_DAC;
  signal int_roi_array : roi_array_type := DEFAULT_ROI;
  signal int_drs_address: std_logic_vector (3 DOWNTO 0) := DEFAULT_DRSADDR;
  signal int_drs_address_mode: std_logic := DEFAULT_DRSADDR_MODE;

BEGIN
  
  control_fsm_proc: process (clk)
  begin
    
    if rising_edge(clk) then

      config_busy <= '1';     -- is always busy except in idle mode
      
      case ctrl_state is
        
        when CTRL_INIT =>
          -- WRITES DEFAULT VALUES IN config ram
          addr_cntr <= addr_cntr + 1;
          ram_addr <= conv_std_logic_vector(addr_cntr, ADDR_WIDTH);
          config_data_valid <= '0';
          config_ready <= '0';
          ctrl_state <= CTRL_INIT;
          ram_write_en <= "1";
          if (addr_cntr < NO_OF_ROI) then
            ram_data_in <= conv_std_logic_vector(int_roi_array(addr_cntr ), 16);
          elsif (addr_cntr < NO_OF_ROI + NO_OF_DAC) then
            ram_data_in <= conv_std_logic_vector(int_dac_array(addr_cntr - NO_OF_ROI), 16);
          elsif (addr_cntr < NO_OF_ROI + NO_OF_DAC + 1) then
            ram_data_in <=  "0000" & "0000" 
                            & "000" & conv_std_logic_vector(int_drs_address_mode, 1)
                            & int_drs_address;
          else
            ram_write_en <= "0"; 
            ctrl_state <= CTRL_IDLE;
          end if;
      
        when CTRL_IDLE =>
          -- 
          addr_cntr <= 0;
          ram_write_en <= "0";
          config_busy <= '0';
          if (config_start = '1') then
            config_started <= '1';
            config_ready <= '0';
            config_data_valid <= '0';
            ctrl_state <= CTRL_LOAD_ADDR;
          end if;
          if (config_wr_en = '1') then
            config_busy <= '1';
            config_data <= (others => 'Z');
            ctrl_state <= CTRL_WRITE;
          end if;
          if (config_rd_en = '1') then
            ram_addr <= config_addr;
            config_data_valid <= '0';
--            ctrl_state <= CTRL_READ_ADDR;
            ctrl_state <= CTRL_READ_WAIT;
          end if; 

        when CTRL_WAIT_IDLE =>
          ctrl_state <= CTRL_IDLE; 
          
        when CTRL_LOAD_ADDR =>
          ram_addr <= conv_std_logic_vector(addr_cntr, ADDR_WIDTH);
          ctrl_state <= CTRL_LOAD_WAIT;
        when CTRL_LOAD_WAIT =>
          ctrl_state <= CTRL_LOAD_DATA;
        when CTRL_LOAD_DATA =>
          addr_cntr <= addr_cntr + 1;
          if (addr_cntr < NO_OF_ROI) then
            roi_array(addr_cntr) <= conv_integer(ram_data_out);
            ctrl_state <= CTRL_LOAD_ADDR;
          elsif (addr_cntr < NO_OF_ROI + NO_OF_DAC) then
            dac_array(addr_cntr - NO_OF_ROI) <= conv_integer(ram_data_out);
            ctrl_state <= CTRL_LOAD_ADDR;
          elsif (addr_cntr < NO_OF_ROI + NO_OF_DAC + 1) then
             drs_address <= ram_data_out(3 downto 0);
             drs_address_mode <= ram_data_out(4);
             ctrl_state <= CTRL_LOAD_ADDR;
          else 
            addr_cntr <= 0;
            config_started <= '0';
            config_ready <= '1';
            ctrl_state <= CTRL_WAIT_IDLE;
          end if;
        
        when CTRL_WRITE =>
          ram_data_in <= config_data;
          ram_addr <= config_addr;
          ram_write_en <= "1";
          ctrl_state <= CTRL_IDLE;
        
        -- *** IMPORTANT ***
        -- read address must remain two clock cycles
        when CTRL_READ_ADDR =>
          ctrl_state <= CTRL_READ_WAIT;
        when CTRL_READ_WAIT =>
          ctrl_state <= CTRL_READ_DATA;
        when CTRL_READ_DATA =>
          config_data <= ram_data_out;
          config_data_valid <= '1';
          ctrl_state <= CTRL_IDLE;
        
        end case;
        
    end if;
    
  end process control_fsm_proc;

END ARCHITECTURE beha;

