--------------------------------------------------------------------------------
-- VECTREX
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- DO 8/2017
--------------------------------------------------------------------------------

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

USE std.textio.ALL;

LIBRARY work;
USE work.base_pack.ALL;
USE work.mc6809_pack.ALL;
USE work.plomb_pack.ALL;
USE work.vid_pack.ALL;

ENTITY vec_core IS
  PORT (
    --------------------------
    sound   : OUT unsigned(15 DOWNTO 0);
    
    --------------------------
    left_udlr  : IN uv4; -- Up/Down/Left/Right
    left_x     : IN uv8;
    left_y     : IN uv8;
    right_udlr : IN uv4; -- Up/Down/Left/Right
    right_x    : IN uv8;
    right_y    : IN uv8;
    pause      : IN std_logic;
    
    --------------------------
    -- Video
    vga_r    : OUT uv8;
    vga_g    : OUT uv8;
    vga_b    : OUT uv8;
    vga_de   : OUT std_logic;
    vga_hsyn : OUT std_logic;
    vga_vsyn : OUT std_logic;
    vga_hpos : OUT uint12;
    vga_vpos : OUT uint12;
    vga_clk  : IN  std_logic;
    vga_en   : IN  std_logic;           -- Clock enable
    
    --------------------------
    -- Vector
    spot_x     : OUT uv16;
    spot_y     : OUT uv16;
    spot_z     : OUT uv8;
    spot_en    : OUT std_logic;
    spot_clk   : OUT std_logic;
    
    --------------------------
    status     : IN  uv32;
    testleds   : OUT uv4;
    
    --------------------------
    -- Draw Interface
    avl_clk           : OUT std_logic;
    avl_waitrequest   : IN  std_logic;
    avl_readdata      : IN  std_logic_vector(31 DOWNTO 0);
    avl_readdatavalid : IN  std_logic;
    avl_burstcount    : OUT std_logic_vector(7 DOWNTO 0);
    avl_writedata     : OUT std_logic_vector(31 DOWNTO 0);
    avl_address       : OUT std_logic_vector(29 DOWNTO 0);
    avl_write         : OUT std_logic;
    avl_read          : OUT std_logic;
    avl_byteenable    : OUT std_logic_vector(3 DOWNTO 0);
    
    -- Framebuffer interface (read only)
    vid_clk           : OUT std_logic;
    vid_waitrequest   : IN  std_logic;
    vid_readdata      : IN  std_logic_vector(31 DOWNTO 0);
    vid_readdatavalid : IN  std_logic;
    vid_burstcount    : OUT std_logic_vector(7 DOWNTO 0);
    vid_writedata     : OUT std_logic_vector(31 DOWNTO 0);
    vid_address       : OUT std_logic_vector(29 DOWNTO 0);
    vid_write         : OUT std_logic;
    vid_read          : OUT std_logic;
    vid_byteenable    : OUT std_logic_vector(3 DOWNTO 0);
    
    -- ROM (game cardridge)
    rom_clk           : OUT std_logic;
    rom_waitrequest   : IN  std_logic;
    rom_readdata      : IN  std_logic_vector(31 DOWNTO 0);
    rom_readdatavalid : IN  std_logic;
    rom_burstcount    : OUT std_logic_vector(7 DOWNTO 0);
    rom_writedata     : OUT std_logic_vector(31 DOWNTO 0);
    rom_address       : OUT std_logic_vector(29 DOWNTO 0);
    rom_write         : OUT std_logic;
    rom_read          : OUT std_logic;
    rom_byteenable    : OUT std_logic_vector(3 DOWNTO 0);
    
    --------------------------
    host_download : IN  std_logic;
    host_wr       : IN  std_logic;
    host_addr     : IN  std_logic_vector(24 DOWNTO 0);
    host_data     : IN  std_logic_vector(15 DOWNTO 0);
    host_wait     : OUT std_logic;
    
    --------------------------
    clksys     : IN std_logic;
    reset_na   : IN std_logic
    );
END ENTITY vec_core;


ARCHITECTURE rtl OF vec_core IS

  SIGNAL ram : arr_uv8(0 TO 1023) :=(OTHERS =>x"00");

  ------------------------------------------------
  SIGNAL ad   : uv16;
  SIGNAL dw   : uv8;
  SIGNAL dr   : uv8;
  SIGNAL req  : std_logic;
  SIGNAL ack  : std_logic;
  SIGNAL wr   : std_logic;
  SIGNAL ph   : uv3;
  
  SIGNAL dr_io,dr_rom,dr_ram,dr_cart : uv8;
  SIGNAL req_io ,req_ram ,req_rom ,req_cart  : std_logic;
  SIGNAL req_io2,req_ram2,req_rom2,req_cart2 : std_logic;
  SIGNAL ack_io : std_logic;

  SIGNAL irq,firq,reset : std_logic :='0';
  CONSTANT nmi,wake : std_logic :='0';
  CONSTANT fast : std_logic :='0';

  SIGNAL stop : std_logic;

  SIGNAL ireset_cpt : natural RANGE 0 TO 100000 :=0;
  SIGNAL ipso_reset_na : std_logic :='0';
  SIGNAL ireset_na : std_logic :='0';
  
  ------------------------------------------------
  SIGNAL fresh_a   : unsigned(20 DOWNTO 5);
  SIGNAL fresh_req : std_logic;

  SIGNAL svga_vsyn,svga_vsyn2,vpulse : std_logic;
  SIGNAL date : uv8;
  SIGNAL vtot,vcpt  : natural RANGE 0 TO 2**24-1;
  SIGNAL vcpp,vtotp : natural RANGE 0 TO 2**18-1;
  
  SIGNAL vinc : std_logic;

  SIGNAL vga_vpos_i : uint12;
  SIGNAL vpos : uv12;
  SIGNAL vcomp : uv8;
  
  --------------------------
  SIGNAL spot_x_i  : uv16;
  SIGNAL spot_y_i  : uv16;
  SIGNAL spot_z_i  : uv8;
  SIGNAL spot_en_i : std_logic;

  SIGNAL dac_x,dac_y : uv24;
  
  CONSTANT VID_A  : uv32 :=x"0000_0000";
  CONSTANT VID_AH : uv4 :=x"0";

  SIGNAL vid_pw,cart_pw : type_plomb_w;
  SIGNAL vid_pr,cart_pr : type_plomb_r;

  SIGNAL run : std_logic;
  SIGNAL drun_cpt : natural RANGE 0 TO 2*65536-1;
  
  CONSTANT MODELINE_1024_720_60Hz_74MHz : type_modeline := (--74.25,
    1024,1392,1448,1650,720,722,728,750,'0','0');
  
  CONSTANT mode : type_modeline :=
    MODELINE_1024_768_60Hz_65MHz;
    --MODELINE_1024_720_60Hz_74MHz;
  
  SIGNAL phos : uv3;
  SIGNAL lumi : uv3;
  SIGNAL shape : uv2;
  SIGNAL rotate : std_logic;
  SIGNAL thermo,over : std_logic;

  SIGNAL tick_cpu,tick_vec : std_logic;
  SIGNAL tick_cpu_cpt : natural RANGE 0 TO 127;
  SIGNAL tick_vec_cpt : natural RANGE 0 TO 31;
  SIGNAL reset_cpt : natural RANGE 0 TO 7;

  SIGNAL efifo_lev,efifofresh_lev,efifoclr_lev : uv16;

  SIGNAL reset_download_na : std_logic;
  
  ------------------------------------------------
                  
  COMPONENT mc6809 IS
    PORT (
      ad       : OUT uv16;
      dw       : OUT uv8;
      dr       : IN  uv8;
      req      : OUT std_logic;
      ack      : IN  std_logic;
      wr       : OUT std_logic;
      ph       : OUT uv3;
      irq      : IN  std_logic;
      firq     : IN  std_logic;
      nmi      : IN  std_logic;
      reset    : IN  std_logic;
      wake     : IN  std_logic;
      fast     : IN  std_logic;
      xpc      : OUT uv16;
      clk      : IN  std_logic;
      reset_na : IN  std_logic);
  END COMPONENT mc6809;
  
  COMPONENT vecio IS
    PORT (
      ad         : IN  uv16;
      dw         : IN  uv8;
      dr         : OUT uv8;
      req        : IN  std_logic;
      ack        : OUT std_logic;
      wr         : IN  std_logic;
      irq        : OUT std_logic;
      firq       : OUT std_logic;
      spot_x     : OUT uv16;
      spot_y     : OUT uv16;
      spot_z     : OUT uv8;
      spot_en    : OUT std_logic;
      dac_x      : OUT uv24;
      dac_y      : OUT uv24;
      rotate     : IN  std_logic;
      sound      : OUT signed(15 DOWNTO 0);
      left_udlr  : IN  uv4;
      left_x     : IN  uv8;
      left_y     : IN  uv8;
      right_udlr : IN  uv4;
      right_x    : IN  uv8;
      right_y    : IN  uv8;
      tick_cpu   : IN  std_logic;
      tick_vec   : IN  std_logic;
      clk        : IN  std_logic;
      reset_na   : IN  std_logic);
  END COMPONENT vecio;
  
  COMPONENT exerom IS
    PORT (
      ad  : IN  uv16;
      dr  : OUT uv8;
      clk : IN  std_logic);
  END COMPONENT exerom;
  
  COMPONENT vecgraph IS
    PORT (
      spot_x            : IN  uv16;
      spot_y            : IN  uv16;
      spot_z            : IN  uv8;
      spot_en           : IN  std_logic;
      fresh_a           : IN  unsigned(20 DOWNTO 5);
      fresh_req         : IN  std_logic;
      date              : IN  uv8;
      vpos              : IN  uv12;
      vcomp             : IN  uv8;
      over              : IN  std_logic;
      lumi              : IN  uv3;
      shape             : IN  uv2;
      efifofresh_lev    : OUT uv16;
      efifo_lev         : OUT uv16;
      efifoclr_lev      : OUT uv16;
      avl_waitrequest   : IN  std_logic;
      avl_readdata      : IN  std_logic_vector(31 DOWNTO 0);
      avl_readdatavalid : IN  std_logic;
      avl_burstcount    : OUT std_logic_vector(7 DOWNTO 0);
      avl_writedata     : OUT std_logic_vector(31 DOWNTO 0);
      avl_address       : OUT std_logic_vector(18 DOWNTO 0);
      avl_write         : OUT std_logic;
      avl_read          : OUT std_logic;
      avl_byteenable    : OUT std_logic_vector(3 DOWNTO 0);
      clk               : IN  std_logic;
      reset_na          : IN  std_logic);
  END COMPONENT vecgraph;

  COMPONENT vidvec IS
    GENERIC (
      BURSTLEN    : natural;
      FIFO_SIZE   : natural;
      FIFO_LEVMAX : natural;
      FIFO_AEC    : natural);
    PORT (
      pw        : OUT type_plomb_w;
      pr        : IN  type_plomb_r;
      adr       : IN  uv32;
      adr_h     : IN  uv4;
      run       : IN  std_logic;
      mode      : IN  type_modeline;
      phos      : IN  uv3;
      fresh_a   : OUT unsigned(20 DOWNTO 5);
      fresh_req : OUT std_logic;
      date      : IN  uv8;
      vga_r     : OUT uv8;
      vga_g     : OUT uv8;
      vga_b     : OUT uv8;
      vga_de    : OUT std_logic;
      vga_hsyn  : OUT std_logic;
      vga_vsyn  : OUT std_logic;
      vga_hpos  : OUT uint12;
      vga_vpos  : OUT uint12;
      vga_clk   : IN  std_logic;
      vga_en    : IN  std_logic;
      clk       : IN  std_logic;
      reset_na  : IN  std_logic);
  END COMPONENT vidvec;

  COMPONENT plomb_avalon IS
    GENERIC (
      N : natural);
    PORT (
      pw                : IN  type_plomb_w;
      pr                : OUT type_plomb_r;
      avl_waitrequest   : IN  std_logic;
      avl_readdata      : IN  std_logic_vector(31 DOWNTO 0);
      avl_readdatavalid : IN  std_logic;
      avl_burstcount    : OUT std_logic_vector(7 DOWNTO 0);
      avl_writedata     : OUT std_logic_vector(31 DOWNTO 0);
      avl_address       : OUT std_logic_vector(N-3 DOWNTO 0);
      avl_write         : OUT std_logic;
      avl_read          : OUT std_logic;
      avl_byteenable    : OUT std_logic_vector(3 DOWNTO 0);
      clk               : IN  std_logic;
      reset_na          : IN  std_logic);
  END COMPONENT plomb_avalon;

  SIGNAL avl_address_i : std_logic_vector(18 DOWNTO 0);
  SIGNAL vid_address_i : std_logic_vector(18 DOWNTO 0);
  SIGNAL rom_address_i : std_logic_vector(18 DOWNTO 0);
  SIGNAL avl_write_i,avl_read_i : std_logic;
  SIGNAL ctrans : std_logic;

  SIGNAL left_udlr_inv,right_udlr_inv : uv4;
  SIGNAL cleft_x,cleft_y,cright_x,cright_y : uv8;
  
  SIGNAL vga_r_i    : uv8;
  SIGNAL vga_g_i    : uv8;
  SIGNAL vga_b_i    : uv8;
  SIGNAL vga_de_i   : std_logic;
  SIGNAL vga_hsyn_i : std_logic;
  SIGNAL vga_vsyn_i : std_logic;

  SIGNAL ovo_ena  : std_logic;
  SIGNAL ovo_in0  : unsigned(0 TO 32*5-1) :=(OTHERS =>'0');
  SIGNAL ovo_in1  : unsigned(0 TO 32*5-1) :=(OTHERS =>'0');
  
  SIGNAL xpc : uv16;
  SIGNAL wpend : std_logic;

  SIGNAL sound_i : signed(15 DOWNTO 0);
  
  SIGNAL cart0 : arr_uv8(0 TO 2**13-1);
  SIGNAL cart1 : arr_uv8(0 TO 2**13-1);
  SIGNAL cart2 : arr_uv8(0 TO 2**13-1);
  SIGNAL cart3 : arr_uv8(0 TO 2**13-1);
  
  ATTRIBUTE ramstyle : string;
  ATTRIBUTE ramstyle OF cart0 : SIGNAL IS "no_rw_check";
  ATTRIBUTE ramstyle OF cart1 : SIGNAL IS "no_rw_check";
  ATTRIBUTE ramstyle OF cart2 : SIGNAL IS "no_rw_check";
  ATTRIBUTE ramstyle OF cart3 : SIGNAL IS "no_rw_check";

  SIGNAL dreq : std_logic;
  SIGNAL cart_a : natural RANGE 0 TO 2**13-1;
  SIGNAL w0,w1,w2,w3 : std_logic;

  SIGNAL cdr0,cdr1,cdr2,cdr3 : uv8;
  SIGNAL cdw0,cdw1,cdw2,cdw3 : uv8;

  -- OVO -----------------------------------------
  FUNCTION CC(i : character) RETURN unsigned IS
  BEGIN
    CASE i IS
      WHEN '0' => RETURN "00000";
      WHEN '1' => RETURN "00001";
      WHEN '2' => RETURN "00010";
      WHEN '3' => RETURN "00011";
      WHEN '4' => RETURN "00100";
      WHEN '5' => RETURN "00101";
      WHEN '6' => RETURN "00110";
      WHEN '7' => RETURN "00111";
      WHEN '8' => RETURN "01000";
      WHEN '9' => RETURN "01001";
      WHEN 'A' => RETURN "01010";
      WHEN 'B' => RETURN "01011";
      WHEN 'C' => RETURN "01100";
      WHEN 'D' => RETURN "01101";
      WHEN 'E' => RETURN "01110";
      WHEN 'F' => RETURN "01111";
      WHEN ' ' => RETURN "10000";
      WHEN '=' => RETURN "10001";
      WHEN '+' => RETURN "10010";
      WHEN '-' => RETURN "10011";
      WHEN '<' => RETURN "10100";
      WHEN '>' => RETURN "10101";
      WHEN '^' => RETURN "10110";
      WHEN 'v' => RETURN "10111";
      WHEN '(' => RETURN "11000";
      WHEN ')' => RETURN "11001";
      WHEN ':' => RETURN "11010";
      WHEN '.' => RETURN "11011";
      WHEN ',' => RETURN "11100";
      WHEN '?' => RETURN "11101";
      WHEN '|' => RETURN "11110";
      WHEN '#' => RETURN "11111";
      WHEN OTHERS => RETURN "10000";
    END CASE;
  END FUNCTION CC;
  FUNCTION CS(s : string) RETURN unsigned IS
    VARIABLE r : unsigned(0 TO s'length*5-1);
    VARIABLE j : natural :=0;
  BEGIN
    FOR i IN s'RANGE LOOP
      r(j TO j+4) :=CC(s(i));
      j:=j+5;
    END LOOP;
    RETURN r;
  END FUNCTION CS;
  -- OVO -----------------------------------------
                  
BEGIN
  
  ireset:PROCESS (clksys) IS
  BEGIN
    IF rising_edge(clksys) THEN
      IF ireset_cpt<65536 THEN
        ireset_cpt<=ireset_cpt+1;
        ipso_reset_na<='0';
      ELSE
        ipso_reset_na<='1';
      END IF;
    END IF;
  END PROCESS ireset;

  ireset_na<=reset_na AND ipso_reset_na;

  drun:PROCESS(clksys,ireset_na) IS
  BEGIN
    IF ireset_na='0' THEN
      drun_cpt<=0;
      run<='0';
    ELSIF rising_edge(clksys) THEN
      IF drun_cpt<1024 THEN
        drun_cpt<=drun_cpt+1;
        run<='0';
      ELSE
        run<='1';
      END IF;
    END IF;
  END PROCESS drun;
  
  --------------------------------------
  i_mc6809: mc6809
    PORT MAP (
      ad       => ad,
      dw       => dw,
      dr       => dr,
      req      => req,
      ack      => ack,
      wr       => wr,
      ph       => ph,
      irq      => irq,
      firq     => firq,
      nmi      => nmi,
      reset    => reset,
      wake     => wake,
      fast     => fast,
      xpc      => xpc,
      clk      => clksys,
      reset_na => ireset_na);
  
  i_vecio: vecio
    PORT MAP (
      ad         => ad,
      dw         => dw,
      dr         => dr_io,
      req        => req_io,
      ack        => ack_io,
      wr         => wr,
      irq        => irq,
      firq       => firq,
      spot_x     => spot_x_i,
      spot_y     => spot_y_i,
      spot_z     => spot_z_i,
      spot_en    => spot_en_i,
      dac_x      => dac_x,
      dac_y      => dac_y,
      rotate     => rotate,
      sound      => sound_i,
      left_udlr  => left_udlr_inv,
      left_x     => cleft_x,
      left_y     => cleft_y,
      right_udlr => right_udlr_inv,
      right_x    => cright_x,
      right_y    => cright_y,
      tick_cpu   => tick_cpu,
      tick_vec   => tick_vec,
      clk        => clksys,
      reset_na   => ireset_na);

  sound<=unsigned(sound_i);
  
  cleft_x<=left_x;
  cleft_y<=NOT left_y;
  cright_x<=right_x;
  cright_y<=NOT right_y;
  
  left_udlr_inv <=NOT left_udlr;
  right_udlr_inv<=NOT right_udlr;

  i_vecgraph: vecgraph
    PORT MAP (
      spot_x            => spot_x_i,
      spot_y            => spot_y_i,
      spot_z            => spot_z_i,
      spot_en           => spot_en_i,
      fresh_a           => fresh_a,
      fresh_req         => fresh_req,
      date              => date,
      vpos              => vpos,
      vcomp             => vcomp,
      over              => over,
      lumi              => lumi,
      shape             => shape,
      efifo_lev         => efifo_lev,
      efifofresh_lev    => efifofresh_lev,
      efifoclr_lev      => efifoclr_lev,
      avl_waitrequest   => avl_waitrequest,
      avl_readdata      => avl_readdata,
      avl_readdatavalid => avl_readdatavalid,
      avl_burstcount    => avl_burstcount,
      avl_writedata     => avl_writedata,
      avl_address       => avl_address_i,
      avl_write         => avl_write_i,
      avl_read          => avl_read_i,
      avl_byteenable    => avl_byteenable,
      clk               => clksys,
      reset_na          => ireset_na);

  avl_clk<=clksys;

  avl_write<=avl_write_i;
  avl_read<=avl_read_i;
  
  spot_x  <=spot_x_i;
  spot_y  <=spot_y_i;
  spot_z  <=spot_z_i;
  spot_en <=spot_en_i;
  spot_clk<=clksys;

  vga_vpos<=vga_vpos_i;
  vpos<=to_unsigned(vga_vpos_i,12) WHEN rising_edge(clksys); -- <ASYNC>
  
  i_vidvec: vidvec
    GENERIC MAP (
      BURSTLEN    => 8,
      FIFO_SIZE   => 64,
      FIFO_LEVMAX => 31,
      FIFO_AEC    => 15
--pragma synthesis_off
      *0
--pragma synthesis_on
      )
    PORT MAP (
      pw        => vid_pw,
      pr        => vid_pr,
      adr       => VID_A,
      adr_h     => VID_AH,
      run       => run,
      mode      => mode,
      phos      => phos,
      fresh_a   => fresh_a,
      fresh_req => fresh_req,
      date      => date,
      vga_r     => vga_r_i,
      vga_g     => vga_g_i,
      vga_b     => vga_b_i,
      vga_de    => vga_de_i,
      vga_hsyn  => vga_hsyn_i,
      vga_vsyn  => vga_vsyn_i,
      vga_hpos  => vga_hpos,
      vga_vpos  => vga_vpos_i,
      vga_clk   => vga_clk,
      vga_en    => vga_en,
      clk       => clksys,
      reset_na  => ireset_na);
  
  i_ovo: ENTITY work.ovo
    PORT MAP (
      i_r     => vga_r_i,
      i_g     => vga_g_i,
      i_b     => vga_b_i,
      i_hs    => vga_hsyn_i,
      i_vs    => vga_vsyn_i,
      i_de    => vga_de_i,
      i_en    => vga_en,
      i_clk   => vga_clk,
      o_r     => vga_r,
      o_g     => vga_g,
      o_b     => vga_b,
      o_hs    => vga_hsyn,
      o_vs    => vga_vsyn,
      o_de    => vga_de,
      ena     => ovo_ena,
      in0     => ovo_in0,
      in1     => ovo_in1);

  ovo_in0<=
    '0' & xpc(15 DOWNTO 12) &
    '0' & xpc(11 DOWNTO 8) &
    '0' & xpc( 7 DOWNTO  4) &
    '0' & xpc( 3 DOWNTO 0) &
    CC(' ') &
    CC('(') &
    CS("        (") &
    '0' & efifo_lev(15 DOWNTO 12) &
    '0' & efifo_lev(11 DOWNTO  8) &
    '0' & efifo_lev( 7 DOWNTO  4) &
    '0' & efifo_lev( 3 DOWNTO  0) &
    CC(',') &
    '0' & efifoclr_lev(15 DOWNTO 12) &
    '0' & efifoclr_lev(11 DOWNTO  8) &
    '0' & efifoclr_lev( 7 DOWNTO  4) &
    '0' & efifoclr_lev( 3 DOWNTO  0) &
    CC(',') &
    '0' & efifofresh_lev(15 DOWNTO 12) &
    '0' & efifofresh_lev(11 DOWNTO  8) &
    '0' & efifofresh_lev( 7 DOWNTO  4) &
    '0' & efifofresh_lev( 3 DOWNTO  0) &
    CC(')') &
    CC('#') & "0000" & host_download;

  ovo_in1<=
    '0' & spot_x_i(15 DOWNTO 12) & '0' & spot_x_i(11 DOWNTO 8) &
    '0' & spot_x_i( 7 DOWNTO  4) & '0' & spot_x_i( 3 DOWNTO 0) &
    '0' & spot_y_i(15 DOWNTO 12) & '0' & spot_y_i(11 DOWNTO 8) &
    '0' & spot_y_i( 7 DOWNTO  4) & '0' & spot_y_i( 3 DOWNTO 0) &
    '1' & spot_en_i & spot_en_i & spot_en_i & spot_en_i &
--        CC(' ') &
    '0' & unsigned(sound_i(15 DOWNTO 12)) &
    '0' & unsigned(sound_i(11 DOWNTO 8)) & 
    '0' & unsigned(sound_i(7 DOWNTO 4)) &
    '0' & unsigned(sound_i(3 DOWNTO 0)) &
    CC('^') &
    '0' & efifo_lev(15 DOWNTO 12) &'0' & efifo_lev(11 DOWNTO 8) & 
    '0' & efifo_lev(7 DOWNTO 4) & '0' & efifo_lev(3 DOWNTO 0) &
    CC(' ') & -- 19 chars
    CC(' ') &
    CS("  ,  ") &
    "0000" & run &
    CS(", ") &
    CS("    ");
  
  ovo_ena<='0'; -- Overlay
  
  testleds<=(ireset_na & NOT ireset_na & clksys & host_download);
  
  i_pa_vid: plomb_avalon
    GENERIC MAP (N => 21)
    PORT MAP (
      pw                => vid_pw,
      pr                => vid_pr,
      avl_waitrequest   => vid_waitrequest,
      avl_readdata      => vid_readdata,
      avl_readdatavalid => vid_readdatavalid,
      avl_burstcount    => vid_burstcount,
      avl_writedata     => vid_writedata,
      avl_address       => vid_address_i,
      avl_write         => vid_write,
      avl_read          => vid_read,
      avl_byteenable    => vid_byteenable,
      clk               => clksys,
      reset_na          => ireset_na);
  
  vid_clk<=clksys;

  --------------------------------------------------
  Cartouche:PROCESS(clksys) IS
  BEGIN
    
    IF rising_edge(clksys) THEN
      dreq<='0';
      
      IF cart_pw.req='1' THEN
        IF cart_pw.mode=PB_MODE_RD THEN
          dreq<='1';
        END IF;
      END IF;
      
    END IF;
  END PROCESS Cartouche;

  w0<=cart_pw.req AND to_std_logic(cart_pw.mode=PB_MODE_WR) AND cart_pw.be(0);
  w1<=cart_pw.req AND to_std_logic(cart_pw.mode=PB_MODE_WR) AND cart_pw.be(1);
  w2<=cart_pw.req AND to_std_logic(cart_pw.mode=PB_MODE_WR) AND cart_pw.be(2);
  w3<=cart_pw.req AND to_std_logic(cart_pw.mode=PB_MODE_WR) AND cart_pw.be(3);

  cart_a<=to_integer(cart_pw.a(14 DOWNTO 2));
  
  Icart0:PROCESS(clksys) IS
  BEGIN
    IF rising_edge(clksys) THEN
      cdr0<=cart0(cart_a);
      IF w0='1' THEN cart0(cart_a)<=cdw0; END IF;
    END IF;
  END PROCESS Icart0;
  
  Icart1:PROCESS(clksys) IS
  BEGIN
    IF rising_edge(clksys) THEN
      cdr1<=cart1(cart_a);
      IF w1='1' THEN cart1(cart_a)<=cdw1; END IF;
    END IF;
  END PROCESS Icart1;
  
  Icart2:PROCESS(clksys) IS
  BEGIN
    IF rising_edge(clksys) THEN
      cdr2<=cart2(cart_a);
      IF w2='1' THEN cart2(cart_a)<=cdw2; END IF;
    END IF;
  END PROCESS Icart2;
  
  Icart3:PROCESS(clksys) IS
  BEGIN
    IF rising_edge(clksys) THEN
      cdr3<=cart3(cart_a);
      IF w3='1' THEN cart3(cart_a)<=cdw3; END IF;
    END IF;
  END PROCESS Icart3;

  cart_pr.d<=cdr0 & cdr1 & cdr2 & cdr3;
  cart_pr.dreq<=dreq;
  cart_pr.ack<='1';

  cdw0<=cart_pw.d(31 DOWNTO 24);
  cdw1<=cart_pw.d(23 DOWNTO 16);
  cdw2<=cart_pw.d(15 DOWNTO  8);
  cdw3<=cart_pw.d( 7 DOWNTO  0);
  
    
  --i_pa_cart: plomb_avalon
  --  GENERIC MAP (N => 21)
  --  PORT MAP (
  --    pw                => cart_pw,
  --    pr                => cart_pr,
  --    avl_waitrequest   => rom_waitrequest,
  --    avl_readdata      => rom_readdata,
  --    avl_readdatavalid => rom_readdatavalid,
  --    avl_burstcount    => rom_burstcount,
  --    avl_writedata     => rom_writedata,
  --    avl_address       => rom_address_i,
  --    avl_write         => rom_write,
  --    avl_read          => rom_read,
  --    avl_byteenable    => rom_byteenable,
  --    clk               => clksys,
  --    reset_na          => reset_download_na);

  rom_clk<=clksys;
  rom_burstcount<=x"00";
  rom_writedata<=x"0000_0000";
  --rom_address<=(OTHERS =>'0');
  rom_write<='0';
  rom_read<='0';
  rom_byteenable<="0000";
  rom_address_i<=(OTHERS =>'0');
  rom_address<=x"3" & "0000000" & rom_address_i;
  
  
  reset_download_na<=ireset_na OR host_download;
  

  -- 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13
  --  0  0  1  0                      [ ---------------
  
  avl_address<=x"2" & "0000000" & avl_address_i;
  vid_address<=x"2" & "0000000" & vid_address_i;
  
  --------------------------------------
  
  PROCESS (clksys,reset_download_na) IS
  BEGIN
    IF reset_download_na='0' THEN
      cart_pw.req<='0';
      cart_pw.dack<='1';
      ctrans<='0';
      wpend<='0';
    ELSIF rising_edge(clksys) THEN
      cart_pw.burst<=PB_SINGLE;
      cart_pw.cont <='0';
      cart_pw.dack <='1';
      cart_pw.be<="0000";
      
      IF cart_pr.dreq='1' THEN
        IF cart_pw.a(1 DOWNTO 0)="00" THEN
          dr_cart<=cart_pr.d(7 DOWNTO 0);
        ELSIF cart_pw.a(1 DOWNTO 0)="01" THEN
          dr_cart<=cart_pr.d(15 DOWNTO 8);
        ELSIF cart_pw.a(1 DOWNTO 0)="10" THEN
          dr_cart<=cart_pr.d(23 DOWNTO 16);
        ELSE
          dr_cart<=cart_pr.d(31 DOWNTO 24);
        END IF;
      END IF;

      IF host_download='0' THEN
        IF req_cart='1' AND (ctrans='0' OR ack='1')THEN
          cart_pw.req<='1';
          cart_pw.a  <=x"0000" & ad;
          ctrans<='1';
        ELSIF cart_pr.ack='1' AND cart_pw.req='1' THEN
          cart_pw.req<='0';
        END IF;
        IF ack='1' THEN
          ctrans<='0';
        END IF;
        
        cart_pw.mode<=PB_MODE_RD;
        cart_pw.be<="1111";
        
      ELSE
        cart_pw.mode<=PB_MODE_WR;
        IF host_wr='1' AND wpend='0' THEN
          cart_pw.a(19 DOWNTO 0)<=unsigned(host_addr(19 DOWNTO 0));
          cart_pw.d<=unsigned(host_data & host_data);  
          IF host_addr(1)='0' THEN
            cart_pw.be<="0011";
          ELSE
            cart_pw.be<="1100";
          END IF;
          cart_pw.req<='1';
          wpend<='1';
        END IF;
        
        IF cart_pr.ack='1' AND cart_pw.req='1' THEN
          wpend<='0';
        END IF;
        
      END IF;
    END IF;
  END PROCESS;
  
  host_wait<=cart_pw.req AND NOT cart_pr.ack;
  
  --------------------------------------
  i_exerom: exerom
    PORT MAP (
      ad => ad,
      dr => dr_rom,
      clk => clksys);
    
  --------------------------------------
  req_io  <=req WHEN ad>=x"D000" AND ad<=x"DFFF" ELSE '0';
  req_rom <=req WHEN ad>=x"E000" ELSE '0';
  req_ram <=req WHEN ad>=x"C800" AND ad<=x"CFFF" ELSE '0';
  req_cart<=req WHEN ad<x"8000" ELSE '0';
  
  ack<=tick_cpu;
  dr<=dr_rom  WHEN req_rom2='1' ELSE
      dr_ram  WHEN req_ram2='1' ELSE
      dr_io   WHEN req_io2='1'  ELSE
      dr_cart;
  
  PROCESS(clksys) IS
  BEGIN
    IF rising_edge(clksys) THEN
      dr_ram<=ram(to_integer(ad AND x"03FF"));
      IF wr='1' AND req_ram='1' THEN
        ram(to_integer(ad AND x"03FF"))<=dw;
      END IF;
      
      req_io2<=req_io;
      req_rom2<=req_rom;
      req_ram2<=req_ram;
      req_cart2<=req_cart;
    END IF;
  END PROCESS;
  
  Dator:PROCESS (clksys,ireset_na) IS
    VARIABLE inc : uint8;
    VARIABLE scal : std_logic;
  BEGIN
    IF ireset_na='0' THEN
      date<=x"00";
    ELSIF rising_edge(clksys) THEN
      svga_vsyn<=vga_vsyn_i; -- <ASYNC>
      svga_vsyn2<=svga_vsyn;
      vpulse<=svga_vsyn AND NOT svga_vsyn2;

      vinc<='0';
      IF vpulse='1' THEN
        vcpt<=0;
        vtot<=vcpt;
        vcpp<=0;
        vinc<='1';
      ELSE
        vcpt<=vcpt+1;
      END IF;
      
      vtotp<=vtot/16+2;
      
      IF vcpp=vtotp THEN
        vcpp<=0;
        vinc<='1';
      ELSE
        vcpp<=vcpp+1;
      END IF;
      
      CASE status(6 DOWNTO 4) IS
        WHEN "000"  => inc:=1; scal:='0'; vcomp<=x"10"; -- 3
        WHEN "001"  => inc:=8; scal:='1'; vcomp<=x"08"; -- 4
        WHEN "010"  => inc:=4; scal:='1'; vcomp<=x"04"; -- 5 
        WHEN "011"  => inc:=2; scal:='1'; vcomp<=x"02"; -- 6
        WHEN "100"  => inc:=1; scal:='1'; vcomp<=x"01"; -- 7
                       
        WHEN "101"  => inc:=8; scal:='0'; vcomp<=x"80"; -- 0
        WHEN "110"  => inc:=4; scal:='0'; vcomp<=x"40"; -- 1
        WHEN OTHERS => inc:=2; scal:='0'; vcomp<=x"20"; -- 2
      END CASE;
      
      IF mux(scal,vpulse,vinc)='1' AND stop='0' THEN
        date<=date+inc;
      END IF;
      
    END IF;
  END PROCESS Dator;
  
  --------------------------------------
  phos<=status(9 DOWNTO 7);
  lumi<=status(12 DOWNTO 10);
  shape<=status(3 DOWNTO 2);
  over<=NOT status(13);
  rotate<=status(14);
  thermo<=status(15);
  
  --------------------------------------
  Pendule:PROCESS(clksys,ireset_na) IS
  BEGIN
    IF ireset_na='0' THEN
      reset_cpt<=0;
      stop<='0';
    ELSIF rising_edge(clksys) THEN

      IF pause='1' THEN
        stop<=NOT stop;
      END IF;
      
      IF tick_vec_cpt=4 THEN --5 THEN
        tick_vec_cpt<=0;
        tick_vec<='1';
      ELSE
        tick_vec_cpt<=tick_vec_cpt+1;
        tick_vec<='0';
      END IF;
      
      IF tick_cpu_cpt=65 THEN -- 99MHz / 66 = 1.5MHz
        tick_cpu_cpt<=0;
        tick_cpu<='1';
      ELSIF stop='0' THEN
        tick_cpu_cpt<=tick_cpu_cpt+1;
        tick_cpu<='0';
      END IF;

      IF tick_cpu='1' THEN
        IF reset_cpt<5 THEN
          reset_cpt<=reset_cpt+1;
          reset<='1';
        ELSE
          reset<='0';
        END IF;
      END IF;
       
    END IF;
  END PROCESS Pendule;
  
END ARCHITECTURE rtl;

