--==============================================================================
--
-- AHB general purpose input/outputs
--
-- Provides "ioNb" input/output signals .
--
--------------------------------------------------------------------------------
--
-- Write registers
--
-- 00, data register receives the values to drive the output lines.
-- 01, output enable register defines the signal direction:
--     when '1', the direction is "out".
--
--------------------------------------------------------------------------------
--
-- Read registers
-- 00, data register provides the values detected on the lines.
--
ARCHITECTURE studentVersion OF ahbGpio IS

signal addresses: unsigned(hAddr'range);
signal bRead: std_ulogic;
signal bWrite: std_ulogic;
signal bDone: std_ulogic;


BEGIN

  process(hReset_n, hClk) begin
    if hReset_n = '0' then
      -- AHB-Lite
      --hRData  <=  (OTHERS => 'Z');
      hRData  <=  (OTHERS => '0');
      hReady  <=  '1';  
      hResp   <=  '0';  

      -- Out
      ioOut <= (OTHERS => '0');
      ioEn  <= (OTHERS => '0');

      addresses  <=  (OTHERS => '0');
      bRead <= '0';
      bWrite <= '0';
      bDone <= '0';
    elsif rising_edge(hClk) then
      if hSel = '1' then
        bWrite <= hWrite;
        bRead <= not hWrite;
        addresses <= hAddr;
        hReady <= '0';
        bDone <= '0';
      else
        bWrite <= '0';
        bRead <= '0';
      end if;

      if bRead = '1' and bWrite = '0' then
        -------------------------------------------------------------------------
        -- READ
        -------------------------------------------------------------------------
        
        if addresses = "00" then
          -- ##### Read data register #####
          --hRData <= unsigned(resize(ioIn, ioNb));
          for i in 0 to ioNb-1 loop
            hRData(i) <= ioIn(i);
          end loop;
          bDone <= '1';

        elsif addresses = "01" then
          report "@@@@@@@@@@ Not possible to change output in READ mode @@@@@@@@@@" severity error;

        end if;

      elsif bRead = '0' and bWrite = '1' then
        -------------------------------------------------------------------------
        -- WRITE
        -------------------------------------------------------------------------
        
        if addresses = "00" then
          -- ##### Write data register #####
          --ioOut <= resize(std_ulogic_vector(hWData), ioNb);
          for i in 0 to ioNb-1 loop
            ioOut(i) <= hWData(i);
          end loop;
          bDone <= '1';

        elsif addresses = "01" then
          -- ##### Write direction register #####
          --ioEn <= hWData;
          for i in 0 to ioNb-1 loop
            ioEn(i) <= hWData(i);
          end loop;
          bDone <= '1';
          
        end if;

      elsif bRead = '1' and bWrite = '1' then
        -------------------------------------------------------------------------
        -- SHOULD NEVER HAPPEN
        -------------------------------------------------------------------------
        report "@@@@@@@@@@ READ and WRITE can't happened in same time @@@@@@@@@@" severity error;

      end if;

      if (ioIn and ioEn) = (ioEn and ioOut) then
        hResp <= '0';
      else
        hResp <= '1';
      end if;

      if bDone = '1' then
        --hRData  <=  (OTHERS => 'Z');
        bDone <= '0';
        hReady <= '1';
      end if;

    end if;

    for i in (ioNb-1) downto 0 loop
      if (ioEn(i) and ioIn(i)) /= (ioEn(i) and ioOut(i)) then
        --ioEn(i) <= '0';
        report "an output was in conflict" severity note;
      end if;
    end loop;

  end process;

  -- AHB-Lite
--  hRData  <=	(OTHERS => '0');
--  hReady  <=	'0';	
--  hResp	  <=	'0';	

  -- Out
--  ioOut <= (OTHERS => '0');
--  ioEn  <= (OTHERS => '0');

END ARCHITECTURE studentVersion;

