--------------------------------------------------------------------------------
-- TEM : Cyclone V
-- Interface PVC -> ASML PARALLEL : EPCQ FLASH
--------------------------------------------------------------------------------
-- DO 4/2015
--------------------------------------------------------------------------------

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

LIBRARY work;
USE work.base_pack.ALL;
USE work.plomb_pack.ALL;
USE work.ts_pack.ALL;

ENTITY pvc_asmi IS
  GENERIC (
    AMASK : uv32 := x"00000000");
  PORT (
    -- PLOMB
    w : IN  type_pvc_w;
    r : OUT type_pvc_r;
    
    -- ASMI_PARALLEL
    clkin      : OUT std_logic;
    read       : OUT std_logic;
    rden       : OUT std_logic;
    addr       : OUT std_logic_vector(31 DOWNTO 0);
    reset      : OUT std_logic;              
    dataout    : IN  std_logic_vector(7 DOWNTO 0);
    busy       : IN  std_logic;
    data_valid : IN  std_logic;
    wren       : OUT std_logic;
    en4b_addr  : OUT std_logic;
    
    -- Global
    clk      : IN std_logic;
    reset_na : IN std_logic
    );
END ENTITY pvc_asmi;

--##############################################################################

ARCHITECTURE rtl OF pvc_asmi IS

  SIGNAL cpt,cpt_pre : natural RANGE 0 TO 3;
  SIGNAL ack : std_logic;
  SIGNAL dbuf : uv32;
  CONSTANT DIVISION : natural := 3;
  
  SIGNAL div : natural RANGE 0 TO DIVISION-1;
  TYPE enum_state IS (sINIT,sIDLE,sTRANS);
  SIGNAL state,state_pre : enum_state;
  SIGNAL clki,pulse_f,pulse_r : std_logic;
  SIGNAL icpt : natural RANGE 0 TO 3;
BEGIN

  en4b_addr<='1';
  wren<='0';
  
  Memop: PROCESS  (clk, reset_na)
  BEGIN
    IF reset_na='0' THEN
      rden<='0';
      read<='0';
      div<=0;
      state<=sINIT;
      clki<='0';
    ELSIF rising_edge(clk) THEN
      ----------------------------------
      IF div=DIVISION-1 THEN
        div<=0;
        pulse_f<=clki;
        pulse_r<=NOT clki;
        clki<=NOT clki;
      ELSE
        div<=div+1;
        pulse_f<='0';
        pulse_r<='0';
      END IF;
      clkin<=clki;
      
      addr<=std_logic_vector(w.a OR AMASK);
      ----------------------------------
      ack<='0';
      CASE state IS
        WHEN sINIT =>
          reset<='1';
          IF pulse_f='1' THEN
            icpt<=icpt+1;
            IF icpt=2 THEN
              state<=sIDLE;
              reset<='0';
            END IF;
          END IF;
          
        WHEN sIDLE =>
          IF w.req='1' AND pulse_f='1' AND state_pre=sIDLE THEN
            state<=sTRANS;
            cpt<=0;
            read<='1';
            rden<='1';
          END IF;
          
        WHEN sTRANS =>
          IF pulse_f='1' THEN
            read<='0';
            IF cpt=3 AND cpt_pre=3 THEN
              rden<='0';
            END IF;
          END IF;
          IF pulse_r='1' THEN
            IF data_valid='1' THEN
              cpt<=(cpt+1) MOD 4;
              dbuf<=dbuf(23 DOWNTO 0) & unsigned(dataout);
            END IF;
            IF busy='0' AND state_pre=sTRANS THEN
              state<=sIDLE;
              ack<='1';
            END IF;
          END IF;
          
      END CASE;
      IF pulse_r='1' THEN
        state_pre<=state;
        cpt_pre<=cpt;
      END IF;
    END IF;
  END PROCESS Memop;
  
  r.ack<=ack;
  r.dr<=dbuf;

END ARCHITECTURE rtl;
