-------------------------------------------------------------------------------
--
-- Text-mode VGA controller for the XESS-300E
--
-- Uses an OPB interface, e.g., for use with the Microblaze soft core
--
-- Stephen A. Edwards
-- sedwards@cs.columbia.edu
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity opb_xsb300e_vga is
  
  generic (
    C_OPB_AWIDTH : integer                   := 32;
    C_OPB_DWIDTH : integer                   := 32;
    C_BASEADDR   : std_logic_vector(31 downto 0) := X"FEFF1000";
    C_HIGHADDR   : std_logic_vector(31 downto 0) := X"FEFF1FFF");

  port (
    -- OPB signals
    OPB_Clk        : in std_logic;
    OPB_Rst        : in std_logic;
    OPB_ABus       : in std_logic_vector (31 downto 0);
    OPB_BE         : in std_logic_vector (3 downto 0);
    OPB_DBus       : in std_logic_vector (31 downto 0);
    OPB_RNW        : in std_logic;
    OPB_select     : in std_logic;
    OPB_seqAddr    : in std_logic;

    VGA_DBus       : out std_logic_vector (31 downto 0);
    VGA_errAck     : out std_logic;
    VGA_retry      : out std_logic;
    VGA_toutSup    : out std_logic;
    VGA_xferAck    : out std_logic;

    Pixel_Clock    : in std_logic;

    -- PAD IO signals
    PB_A : out std_logic_vector(19 downto 0);
    PB_UB_N : out std_logic;
    PB_LB_N : out std_logic;
    PB_WE_N : out std_logic;
    PB_OE_N : out std_logic;
    RAM_CE_N : out std_logic;
    PB_D : inout std_logic_vector(15 downto 0);
 
    -- Video signals
    VIDOUT_CLK     : out std_logic;
    VIDOUT_RED     : out std_logic_vector(9 downto 0);
    VIDOUT_GREEN   : out std_logic_vector(9 downto 0);
    VIDOUT_BLUE    : out std_logic_vector(9 downto 0);
    VIDOUT_BLANK_N : out std_logic;
    VIDOUT_HSYNC_N : out std_logic;
    VIDOUT_VSYNC_N : out std_logic);

end opb_xsb300e_vga;

architecture Behavioral of opb_xsb300e_vga is

  component vga
    port (
      clk : in std_logic;
      pix_clk : in std_logic;
      rst : in std_logic;
      video_data : in std_logic_vector(15 downto 0);
      video_addr : out std_logic_vector(19 downto 0);
      video_req : out std_logic;
      vidout_clk : out std_logic;
      vidout_RCR : out std_logic_vector(9 downto 0);
      vidout_GY : out std_logic_vector(9 downto 0);
      vidout_BCB : out std_logic_vector(9 downto 0);
      vidout_BLANK_N : out std_logic;
      vidout_HSYNC_N : out std_logic;
      vidout_VSYNC_N : out std_logic);
  end component;

  component pad_io
    port (
      clk : in std_logic;
      rst : in std_logic;
      PB_A : out std_logic_vector(19 downto 0);
      PB_UB_N : out std_logic;
      PB_LB_N : out std_logic;
      PB_WE_N : out std_logic;
      PB_OE_N : out std_logic;
      RAM_CE_N : out std_logic;
      PB_D : inout std_logic_vector(15 downto 0);
      pb_addr : in std_logic_vector(19 downto 0);
      pb_ub : in std_logic;
      pb_lb : in std_logic;
      pb_wr : in std_logic;
      pb_rd : in std_logic;
      ram_ce : in std_logic;
      pb_dread : out std_logic_vector(15 downto 0);
      pb_dwrite : in std_logic_vector(15 downto 0));
  end component;

  component line_drawer
  
       port (
    
         X0      : in std_logic_vector (15 downto 0);               
         X1      : in std_logic_vector (15 downto 0);                     
         Y0      : in std_logic_vector (15 downto 0);             
         Y1      : in std_logic_vector (15 downto 0);
         OPB_Clk : in std_logic;
         OPB_Rst : in std_logic;
     
         stall   : in std_logic;
         wr      : out std_logic;
         A       : out std_logic_vector (19 downto 0);
         D       : out std_logic_vector (15 downto 0));
  end component;

  


  -----------------------------------------------------------------------------
  --  
  -- OPB-RAM controller
  --
  -----------------------------------------------------------------------------

 signal Abus, Dbus : std_logic_vector(31 downto 0);
 signal rnw : std_logic;
 
 begin
  
  -- Unused OPB control signals
  VGA_errAck <= '0';
  VGA_retry <= '0';
  VGA_toutSup <= '0';

  -- Latch the relevant OPB signals from the OPB, since they arrive late
  LatchOPB: process (OPB_Clk, OPB_Rst)
  begin
    if OPB_Rst = '1' then
      Abus <= ( others => '0' );
      DBus <= ( others => '0' );
      RNW <= '1';
    elsif OPB_Clk'event and OPB_Clk = '1' then
      ABus <= OPB_ABus;
      DBus <= OPB_DBus;
      RNW <= OPB_RNW;
    end if;
  end process LatchOPB;

  GenDOut: process (OPB_Clk, OPB_Rst)
  begin
    if OPB_Rst = '1' then
      VGA_Dbus <= ( others => '0');
    elsif OPB_Clk'event and OPB_Clk = '1' then
      VGA_Dbus <= X"12345678";
    end if;
  end process GenDOut;

  vga1 : vga
   port map (
      clk => OPB_Clk,
      pix_clk => Pixel_Clock,
      rst => OPB_Rst,
      video_data => X"00FF",
      video_addr => open,
      video_req => open,
      vidout_clk => VIDOUT_Clk,
      vidout_RCR => VIDOUT_RED,
      vidout_GY => VIDOUT_GREEN,
      vidout_BCB => VIDOUT_BLUE,
      vidout_BLANK_N => VIDOUT_BLANK_N,
      vidout_HSYNC_N => VIDOUT_HSYNC_N,
      vidout_VSYNC_N => VIDOUT_VSYNC_N
   ); 

  padio1 : pad_io
    port map (
      clk => OPB_Clk,
      rst => OPB_Rst,
      PB_A => PB_A,
      PB_UB_N => PB_UB_N,
      PB_LB_N => PB_LB_N,
      PB_WE_N => PB_WE_N,
      PB_OE_N => PB_OE_N,
      RAM_CE_N => RAM_CE_N,
      PB_D => PB_D,
      pb_addr => X"00000",
      pb_ub => '0',
      pb_lb => '0',
      pb_wr => '0',
      pb_rd => '0',
      ram_ce => '0',
      pb_dread => open,
      pb_dwrite => X"0000"
  );
  

 line_drawer1: line_drawer
    port map(
      X0 => "1111111111111111",
      X1 => "1111111111111111",        
      Y0 => "1111111111111111",
      Y1 => "1111111111111111",
      OPB_Clk => OPB_Clk,
      OPB_Rst => OPB_Rst,

      stall => '0',
      wr => '1',
      A => "11111111111111111111",
      D => PB_D);
 
 end Behavioral;


--fsm
  
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity line_drawer is
   port (
    -- OPB signals
     X0      : in std_logic_vector (15 downto 0);               
     X1      : in std_logic_vector (15 downto 0);                     
     Y0      : in std_logic_vector (15 downto 0);             
     Y1      : in std_logic_vector (15 downto 0);
     OPB_Clk : in std_logic;
     OPB_Rst : in std_logic;
     
     stall   : in std_logic;
     wr      : out std_logic;
     A       : out std_logic_vector (19 downto 0);
     D       : out std_logic_vector (15 downto 0));

   
end line_drawer;

architecture Behavioral of line_drawer is


   signal address : std_logic_vector(19 downto 0);
   signal data : std_logic_vector(15 downto 0);

begin
   
   draw: process (OPB_Clk,OPB_Rst)

 begin
      
        if OPB_Rst = '1' then
          data <= ( others => '0');
          address <= ( others => '0');

        elsif OPB_Clk'event and OPB_Clk = '1' and stall = '0' then
          data <= data +1;
          address <= address + 2;

          if(address >= X"0004b000") then
            address <= ( others => '0');
          end if;
        
       end if;

          wr <= '1';
          A<=address;
          D<=data;
          
  end process draw;
  
  
end Behavioral;
  
