-- Kyle McGhee
-- kmcghee@purdue.edu
-- lcd_controller.vhd

-- This module sends a signal out to an LCD driver.
-- After one screen-cycle, it is impossible to become out of sync.
-- Asynchronous and essentially separate with rest of design.
-- LCD_CLK should be much slower than CLK, and slow enough for the SRAM.

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity LCD_CONTROLLER is
  port (
    LCD_CLK: in STD_LOGIC;
    nRST: in STD_LOGIC;

    LAddress: out std_logic_vector(15 downto 0);
    LData : in std_logic_vector(15 downto 0);

    BUSY: out STD_LOGIC;
    --Also "SCREEN" system output

    PIXEL: out STD_LOGIC_VECTOR(7 downto 0);
    ROW: out STD_LOGIC);
end LCD_CONTROLLER;

architecture LCD_CONTROLLER_ARCH of LCD_CONTROLLER is
  signal ADDRESS: UNSIGNED(15 downto 0);
  signal NEXT_ADDRESS : UNSIGNED(15 downto 0);
begin
  -- Operate on LCD_CLK instead of CLK.
  -- Increment and output the next pixel
  process (LCD_CLK, nRST)
  begin
    if (nRST = '0') then
      PIXEL <= x"00";
      ADDRESS <= x"0000";
    elsif (LCD_CLK'event and LCD_CLK = '1') then
      PIXEL <= LData(15 downto 8);
      ADDRESS <= NEXT_ADDRESS;
    end if;
  end process;
  NEXT_ADDRESS <= ADDRESS + 1;

-- Set busy low on first pixel of each screen.  This is the inverse of the "SCREEN" system output.
  BUSY <= '1' when (ADDRESS = x"0000") else '0';
-- Set row high on the first pixel of each row.
  ROW <= '1' when (ADDRESS(7 downto 0) = x"00") else '0';

  LAddress <= STD_LOGIC_VECTOR(ADDRESS);
end LCD_CONTROLLER_ARCH;
