    yMin : integer;
    yMax : integer
  );
  port (
    x : in integer range xMin to xMax;
    y : in integer range yMin to yMax;
    r : out std_logic_vector( 7 downto 0 );
    g : out std_logic_vector( 7 downto 0 );
    b : out std_logic_vector( 7 downto 0 )
  );
end borderGen;
architecture rtl of borderGen is
begin

  r <= ( others => '0' );
  g <= ( others => '0' );
  b <= ( others => '0' );

end rtl;


-----------------------------------------------------------------------
-- Title: GBA Display Capture
-- Author: zwenergy
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use ieee.math_real.all;

entity captureGBA is
  generic(
    clkPeriodNS : real := 13.0 -- Clock period in ns.
  );
  port(
    clk : in std_logic;
    rst : in std_logic;
    redPxl : in std_logic_vector( 4 downto 0 );
    greenPxl : in std_logic_vector( 4 downto 0 );
    bluePxl : in std_logic_vector( 4 downto 0 );
    vsync : in std_logic;
    dclk : in std_logic;

    colorMode : in std_logic;

    redPxlOut : out std_logic_vector( 7 downto 0 );
    greenPxlOut : out std_logic_vector( 7 downto 0 );
    bluePxlOut : out std_logic_vector( 7 downto 0 );
    validPxlOut : out std_logic;
    pxlCnt : out std_logic_vector( 7 downto 0 );

    validLine : out std_logic;
    newFrame : out std_logic
  );
end captureGBA;

architecture rtl of captureGBA is
signal cntX : integer range -1 to 245;
signal cntY : integer range 0 to 165;
signal prevCntX : integer range -1 to 245;
signal prevCntY : integer range 0 to 165;
signal validLine_int : std_logic;
signal curRedPxl : std_logic_vector( 4 downto 0 );
signal curGreenPxl : std_logic_vector( 4 downto 0 );
signal curBluePxl : std_logic_vector( 4 downto 0 );
signal dclk_int : std_logic;
signal dclk_prev : std_logic;
signal dclkRise : std_logic;
signal newPxl : std_logic;
signal vsyncFall : std_logic;
signal vsyncRise : std_logic;
signal vsync_int : std_logic;
signal vsync_del : std_logic;
signal syncCnt : integer range 0 to integer(ceil(325000.0/clkPeriodNS));
constant minSyncCnt : integer := integer(ceil(136500.0/clkPeriodNS));

-- GBA Color Correction
signal redGBACol, greenGBACol, blueGBACol, redExt, greenExt, blueExt : std_logic_vector( 7 downto 0 );
begin

  -- Thanks to ManCloud for improving my stupid color extension :)

  redExtProc : process( curRedPxl ) is
  variable pxl_tmp, curPxl : unsigned( 7 downto 0 );
  begin
    curPxl := unsigned( curRedPxl ) & "000";
    pxl_tmp := "00000" & unsigned( curRedPxl( 4 downto 2 ) );
    pxl_tmp := pxl_tmp + curPxl;

    redExt <= std_logic_vector( pxl_tmp ) ;

    -- Keep limited range.
--    if ( unsigned( pxl_tmp ) < 16 ) then
--      pxl_tmp := std_logic_vector( to_unsigned( 16, pxl_tmp'length ) );
--    elsif ( unsigned( pxl_tmp ) > 235 ) then
--      pxl_tmp := std_logic_vector( to_unsigned( 235, pxl_tmp'length ) );
--    end if;
  end process;

  blueExtProc : process( curBluePxl ) is
  variable pxl_tmp, curPxl : unsigned( 7 downto 0 );
  begin
    curPxl := unsigned( curBluePxl ) & "000";
    pxl_tmp := "00000" & unsigned( curBluePxl( 4 downto 2 ) );
    pxl_tmp := pxl_tmp + curPxl;

    blueExt <= std_logic_vector( pxl_tmp ) ;
  end process;

  greenExtProc : process( curGreenPxl ) is
  variable pxl_tmp, curPxl : unsigned( 7 downto 0 );
  begin
    curPxl := unsigned( curGreenPxl ) & "000";
    pxl_tmp := "00000" & unsigned( curGreenPxl( 4 downto 2 ) );
    pxl_tmp := pxl_tmp + curPxl;

    greenExt <= std_logic_vector( pxl_tmp ) ;
  end process;

  -- GBA color correction.
  colorCorrection : entity work.gbaColorCorrNew( rtl )
    port map(
      gbaRed => curRedPxl,
      gbaGreen => curGreenPxl,
      gbaBlue => curBluePxl,
      rGBACol => redGBACol,
      gGBACol => greenGBACol,
      bGBACol => blueGBACol
    );

  -- Choose color mode.

        redPxlOut <= redExt;
        greenPxlOut <= greenExt;
        bluePxlOut <= blueExt;

      end if;

      pxlCnt <= std_logic_vector( to_unsigned( prevCntX, pxlCnt'length ) );

      -- Since the very first bit is a start bit, we have to count until 239
      if ( ( newPxl = '1' ) and ( prevCntX = 239 ) ) then
        validLine <= '1';
      else
        validLine <= '0';
      end if;

      if ( prevCntY = 0 ) then
        newFrame <= '1';
      else
        newFrame <= '0';
      end if;

      validPxlOut <= newPxl;

    end if;
  end process;

  dclkRise <= '1' when ( dclk_int = '1' and dclk_prev = '0' ) else '0';

  vsyncRise <= '1' when ( vsync_int = '1' and vsync_del = '0' ) else '0';
  vsyncFall <= '1' when ( vsync_int = '0' and vsync_del = '1' ) else '0';

  process( clk ) is
  begin
    if ( rising_edge( clk ) ) then
      if ( rst = '1' ) then
        syncCnt <= 0;
        vsync_int <= '1';
        vsync_del <= '1';
        cntY <= 0;
        cntX <= -1;
        dclk_prev <= '1';
        curRedPxl <= ( others => '0' );
        curGreenPxl <= ( others => '0' );
        curBluePxl <= ( others => '0' );
        newPxl <= '0';
        prevCntY <= 0;
        prevCntX <= 0;
        dclk_int <= '1';

      else
        -- Shift prev. dclk
        dclk_int <= dclk;
        dclk_prev <= dclk_int;

        vsync_int <= vsync;
        vsync_del <= vsync_int;

        -- Shift newPxl.
        -- The very first pixel seems to be not a valid one (...start bit?)
        if ( cntX = -1 ) then
          newPxl <= '0';
        else
          newPxl <= dclkRise;
        end if;

        prevCntX <= cntX;
        prevCntY <= cntY;

        -- Capture new pxl.
        if ( dclkRise = '1' ) then
          curRedPxl <= redPxl;
          curGreenPxl <= greenPxl;
          curBluePxl <= bluePxl;
        end if;

        if ( vsyncFall = '1' ) then
          syncCnt <= 0;
        elsif ( vsync_int = '0' ) then
          syncCnt <= syncCnt + 1;
        end if;

        if ( vsyncRise = '1' and syncCnt >= minSyncCnt ) then
          cntY <= 0;
          cntX <= -1;
        elsif ( dclkRise = '1' ) then
          if ( cntX = 239 ) then
            cntX <= -1;
            cntY <= cntY + 1;
          else
            cntX <= cntX + 1;
          end if;
        end if;
      end if;
    end if;
  end process;

end rtl;

  process( clk ) is
  begin
    if rising_edge( clk ) then
      if ( colorMode = '1' ) then
        redPxlOut <= redGBACol;


-----------------------------------------------------------------------
-- Title: Controller Transceiver
-- Author: zwenergy
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.math_real.ALL;
use IEEE.std_logic_misc.ALL;

entity commTransceiver is
  generic(
    packetBits : integer := 16;
    clkFreq0 : real; -- kHz
    clkFreq1 : real; -- kHz
    clkFreqMax : real; -- kHz
    usBit : real
  );
  port(
    serDatIn : in std_logic;
    clk : in std_logic;
    rst : in std_logic;

    -- Corresponding to the generics.
    clkFreq : in std_logic;

    --serDatOut : out std_logic;
    --txActive : out std_logic;
    controllerOut : out std_logic_vector( 9 downto 0 );
    controllerOSDActive : out std_logic;

    osdActive : out std_logic;
    osdState : out std_logic_vector( 7 downto 0 );
    osdStateValid : out std_logic;

    -- Settings
    osdSmooth2x : out std_logic;
    osdSmooth4x : out std_logic;
    osdGridActive : out std_logic;
    osdGridBright : out std_logic;
    osdGridMult : out std_logic;
    osdColorCorrection : out std_logic;
    osdRate : out std_logic;
    osdSettingsValid : out std_logic;

    rxValid : out std_logic
    );

end commTransceiver;

architecture rtl of commTransceiver is
  constant cyclesBitMax : integer := integer( ceil( ( usBit / 1000000.0 ) /  ( 1.0 / ( clkFreqMax * 1000.0 ) ) ) );
  constant cyclesTimeout : integer := 2 * cyclesBitMax;

  constant cyclesBit0 : integer := integer( ceil( ( usBit / 1000000.0 ) /  ( 1.0 / ( clkFreq0 * 1000.0 ) ) ) );
  constant cyclesBit1 : integer := integer( ceil( ( usBit / 1000000.0 ) /  ( 1.0 / ( clkFreq1 * 1000.0 ) ) ) );
  constant cyclesHalfBit0 : integer := cyclesBit0 / 2;
  constant cyclesHalfBit1 : integer := cyclesBit1 / 2;

  constant prefixLen : integer := 4;
  constant controllerOSD_prefix : std_logic_vector( prefixLen - 1 downto 0 ) := "1000";
  constant config_prefix : std_logic_vector( prefixLen - 1 downto 0 ) := "0100";
  constant osdState_prefix : std_logic_vector( prefixLen - 1 downto 0 ) := "0010";

  -- Timeout counter.
  signal timeoutCnt : integer range 0 to cyclesTimeout;
  -- Bit counter.
  signal bitCnt : integer range 0 to packetBits;
  -- Packet.
  signal curPacket : std_logic_vector( packetBits - 1 downto 0 );
  -- Flag for a new packet.
  signal newPacket : std_logic;

  signal serDatInPrev, serDatIn_filtered : std_logic;
  signal serDatFilter : std_logic_vector( 7 downto 0 );

  -- A few status bits.
  signal rxPacket : std_logic;

begin

  -- Synch. part.
  process( clk ) is
  begin
    if ( rising_edge( clk ) ) then
      if ( rst = '1' ) then
        timeoutCnt <= 0;
        bitCnt <= 0;
        curPacket <= ( others => '0' );
        newPacket <= '0';
        serDatInPrev <= '0';
        rxPacket <= '0';
        controllerOut <= ( others => '0' );
        rxValid <= '0';
        serDatFilter <= ( others => '1' );

        controllerOut <= ( others => '0' );
        controllerOSDActive <= '0';
        osdActive <= '0';
        osdState <= ( others => '0' );
        osdStateValid <= '0';
        osdSmooth2x <= '0';
        osdSmooth4x <= '0';
        osdGridActive <= '0';
        osdGridBright <= '0';
        osdGridMult <= '0';
        osdColorCorrection <= '0';
        osdRate <= '0';
        osdSettingsValid <= '0';

        serDatIn_filtered <= '1';
        --serDatOut <= '1';
        --txActive <= '0';
      else

        -- Serial Input related stuff.
        serDatFilter( 7 ) <= serDatIn;
        serDatFilter( 6 downto 0 ) <= serDatFilter( 7 downto 1 );

        if ( and_reduce( serDatFilter ) = '1' ) then
          serDatIn_filtered <= '1';
        elsif ( or_reduce( serDatFilter ) = '0' ) then
          serDatIn_filtered <= '0';
        end if;

        serDatInPrev <= serDatIn_filtered;

        -- Per default, there is no new packet.
        newPacket <= '0';

        -- Falling edge, a new bit is arriving.
        if ( serDatInPrev = '1' and serDatIn_filtered = '0' ) then
          -- Reset counter.
          timeoutCnt <= 0;
          rxPacket <= '1';
        elsif ( rxPacket = '1' ) then
          timeoutCnt <= timeoutCnt + 1;

          -- Sample?
          if ( ( clkFreq = '0' and timeoutCnt = cyclesHalfBit0 ) or
               ( clkFreq = '1' and timeoutCnt = cyclesHalfBit1 ) ) then
            curPacket( packetBits - 1 ) <= serDatIn_filtered;
            curPacket( packetBits - 2 downto 0 ) <= curPacket( packetBits - 1 downto 1 );
            bitCnt <= bitCnt + 1;

          -- Timeout?
          elsif ( timeoutCnt = cyclesTimeout ) then
            rxPacket <= '0';
            bitCnt <= 0;
            if ( bitCnt = packetBits ) then
              newPacket <= '1';
            end if;
          end if;
        end if;

        -- Controller output related stuff.
        if ( newPacket = '1' ) then

          -- On screen buttons?
          if ( curPacket( packetBits - 1 downto packetBits - prefixLen ) = controllerOSD_prefix ) then
            controllerOut <= curPacket( 9 downto 0 );

          -- Settings packet?
          elsif ( curPacket( packetBits - 1 downto packetBits - prefixLen ) = config_prefix ) then
            osdSmooth2x <= curPacket( 0 );
            osdSmooth4x <= curPacket( 1 );
            osdGridActive <= curPacket( 2 );
            osdGridBright <= curPacket( 3 );
            osdGridMult <= curPacket( 4 );
            osdColorCorrection <= curPacket( 5 );
            osdRate <= curPacket( 6 );
            controllerOSDActive <= curPacket( 7 );
            osdSettingsValid <= '1';

          -- OSD state?

          end if;

          rxValid <= '1';
        else
          rxValid <= '0';
          osdSettingsValid <= '0';
          osdStateValid <= '0';

        end if;

      end if;
    end if;
  end process;
end rtl;

          elsif ( curPacket( packetBits - 1 downto packetBits - prefixLen ) = osdState_prefix ) then
            osdActive <= curPacket( 0 );
            osdState( 6 downto 0 ) <= curPacket( 7 downto 1 );


-----------------------------------------------------------------------
-- Title: DRP
-- Author: zwenergy
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

entity drp is
  port (
    -- 000: 60 Hz, 720p
    -- 001: 59.x Hz, 720p
    -- 010: 60 Hz, 1080p
    -- 011: 59.x Hz, 1080p
    -- 100: 60 Hz, 480p
    -- 101: 59.x Hz, 480p
    stateSel : in std_logic_vector( 2 downto 0 );
    doSwitch : in std_logic;

    doSig : in std_logic_vector( 15 downto 0 );
    drdy : in std_logic;
    locked : in std_logic;

    clk : in std_logic;
    rst : in std_logic;

    busy : out std_logic;

    dwe : out std_logic;
    den : out std_logic;
    daddr : out std_logic_vector( 6 downto 0 );
    diSig : out std_logic_vector( 15 downto 0 );
    dclk : out std_logic;
    rstMMCM : out std_logic
  );
end drp;

architecture rtl of drp is
type reconfEntry_t is record
  addr : std_logic_vector( 6 downto 0 );
  data : std_logic_vector( 15 downto 0 );
  mask :  std_logic_vector( 15 downto 0 );
end record reconfEntry_t;
type reconfSetting_t is array( 0 to 13 ) of reconfEntry_t;
type reconfROM_t is array( 0 to 5 ) of reconfSetting_t;

-- The actual ROM.
constant reconfROM : reconfROM_t :=
-- 60 Hz, 720p
( 0 =>
  -- General settings
  ( 0 =>
    (
      addr => std_logic_vector( to_unsigned( 16#14#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1491#, 16 ) ),
      mask => "0001000000000000"
    ),

    1 =>
    (
      addr => std_logic_vector( to_unsigned( 16#15#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1800#, 16 ) ),
      mask => "1000000000000000"
    ),
    2 =>
    (
      addr => std_logic_vector( to_unsigned( 16#13#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#2400#, 16 ) ),
      mask => "1100001100000000"
    ),
    3 =>
    (
      addr => std_logic_vector( to_unsigned( 16#16#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0083#, 16 ) ),
      mask => "1100000000000000"
    ),
    4 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4F#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1000#, 16 ) ),
      mask => "0110011001101111"
    ),
    5 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4E#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0900#, 16 ) ),
      mask => "0110011011111111"
    ),
    6 =>
    (
      addr => std_logic_vector( to_unsigned( 16#28#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#FFFF#, 16 ) ),
      mask => "0000000000000000"
    ),
    7 =>
    (
      addr => std_logic_vector( to_unsigned( 16#18#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#00fa#, 16 ) ),
      mask => "1111110000000000"
    ),
    8 =>
    (
      addr => std_logic_vector( to_unsigned( 16#19#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7c01#, 16 ) ),
      mask => "1000000000000000"
    ),
    9 =>
    (
      addr => std_logic_vector( to_unsigned( 16#1A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7de9#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout0
    10 =>
    (
      addr => std_logic_vector( to_unsigned( 16#08#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1041#, 16 ) ),
      mask => "0001000000000000"
    ),
    11 =>
    (
      addr => std_logic_vector( to_unsigned( 16#09#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0000#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout1
    12 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1145#, 16 ) ),
      mask => "1000000000000000"
    ),
    13 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0B#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0000#, 16 ) ),
      mask => "1111110000000000"
    )
  ),

  -- 59.7 Hz, 720 p
  1 =>
  -- General settings
  ( 0 =>
    (
      addr => std_logic_vector( to_unsigned( 16#14#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1410#, 16 ) ),
      mask => "0001000000000000"
    ),

    1 =>
    (
      addr => std_logic_vector( to_unsigned( 16#15#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#2800#, 16 ) ),
      mask => "1000000000000000"
    ),
    2 =>
    (
      addr => std_logic_vector( to_unsigned( 16#13#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#2800#, 16 ) ),
      mask => "1100001100000000"
    ),
    3 =>
    (
      addr => std_logic_vector( to_unsigned( 16#16#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0042#, 16 ) ),
      mask => "1100000000000000"
    ),
    4 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4F#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1000#, 16 ) ),
      mask => "0110011001101111"
    ),
    5 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4E#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0900#, 16 ) ),
      mask => "0110011011111111"
    ),
    6 =>
    (
      addr => std_logic_vector( to_unsigned( 16#28#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#FFFF#, 16 ) ),
      mask => "0000000000000000"
    ),
    7 =>
    (
      addr => std_logic_vector( to_unsigned( 16#18#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#002c#, 16 ) ),
      mask => "1111110000000000"
    ),
    8 =>
    (
      addr => std_logic_vector( to_unsigned( 16#19#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7c01#, 16 ) ),
      mask => "1000000000000000"
    ),
    9 =>
    (
      addr => std_logic_vector( to_unsigned( 16#1A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7de9#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout0
    10 =>
    (
      addr => std_logic_vector( to_unsigned( 16#08#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1042#, 16 ) ),
      mask => "0001000000000000"
    ),
    11 =>
    (
      addr => std_logic_vector( to_unsigned( 16#09#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0080#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout1
    12 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#11c8#, 16 ) ),
      mask => "1000000000000000"
    ),
    13 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0B#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0080#, 16 ) ),
      mask => "1111110000000000"
    )
  ),

  -- 60 Hz, 1080p
  2 =>
  -- General settings
  ( 0 =>
    (
      addr => std_logic_vector( to_unsigned( 16#14#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1491#, 16 ) ),
      mask => "0001000000000000"
    ),

    1 =>
    (
      addr => std_logic_vector( to_unsigned( 16#15#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1800#, 16 ) ),
      mask => "1000000000000000"
    ),
    2 =>
    (
      addr => std_logic_vector( to_unsigned( 16#13#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#2400#, 16 ) ),
      mask => "1100001100000000"
    ),
    3 =>
    (
      addr => std_logic_vector( to_unsigned( 16#16#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0083#, 16 ) ),
      mask => "1100000000000000"
    ),
    4 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4F#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1000#, 16 ) ),
      mask => "0110011001101111"
    ),
    5 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4E#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0900#, 16 ) ),
      mask => "0110011011111111"
    ),
    6 =>
    (
      addr => std_logic_vector( to_unsigned( 16#28#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#FFFF#, 16 ) ),
      mask => "0000000000000000"
    ),
    7 =>
    (
      addr => std_logic_vector( to_unsigned( 16#18#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#00fa#, 16 ) ),
      mask => "1111110000000000"
    ),
    8 =>
    (
      addr => std_logic_vector( to_unsigned( 16#19#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7c01#, 16 ) ),
      mask => "1000000000000000"
    ),
    9 =>
    (
      addr => std_logic_vector( to_unsigned( 16#1A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7de9#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout0
    10 =>
    (
      addr => std_logic_vector( to_unsigned( 16#08#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1041#, 16 ) ),
      mask => "0001000000000000"
    ),
    11 =>
    (
      addr => std_logic_vector( to_unsigned( 16#09#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#00c0#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout1
    12 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1083#, 16 ) ),
      mask => "1000000000000000"
    ),
    13 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0B#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0080#, 16 ) ),
      mask => "1111110000000000"
    )
  ),

  -- 59.x Hz, 1080p
  3 =>
  -- General settings
  ( 0 =>
    (
      addr => std_logic_vector( to_unsigned( 16#14#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#175c#, 16 ) ),
      mask => "0001000000000000"
    ),

    1 =>
    (
      addr => std_logic_vector( to_unsigned( 16#15#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1800#, 16 ) ),
      mask => "1000000000000000"
    ),
    2 =>
    (
      addr => std_logic_vector( to_unsigned( 16#13#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#2400#, 16 ) ),
      mask => "1100001100000000"
    ),
    3 =>
    (
      addr => std_logic_vector( to_unsigned( 16#16#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0104#, 16 ) ),
      mask => "1100000000000000"
    ),
    4 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4F#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1000#, 16 ) ),
      mask => "0110011001101111"
    ),
    5 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4E#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0800#, 16 ) ),
      mask => "0110011011111111"
    ),
    6 =>
    (
      addr => std_logic_vector( to_unsigned( 16#28#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#FFFF#, 16 ) ),
      mask => "0000000000000000"
    ),
    7 =>
    (
      addr => std_logic_vector( to_unsigned( 16#18#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#00fa#, 16 ) ),
      mask => "1111110000000000"
    ),
    8 =>
    (
      addr => std_logic_vector( to_unsigned( 16#19#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7c01#, 16 ) ),
      mask => "1000000000000000"
    ),
    9 =>
    (
      addr => std_logic_vector( to_unsigned( 16#1A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7de9#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout0
    10 =>
    (
      addr => std_logic_vector( to_unsigned( 16#08#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1041#, 16 ) ),
      mask => "0001000000000000"
    ),
    11 =>
    (
      addr => std_logic_vector( to_unsigned( 16#09#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#00c0#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout1
    12 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1083#, 16 ) ),
      mask => "1000000000000000"
    ),
    13 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0B#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0080#, 16 ) ),
      mask => "1111110000000000"
    )
  ),

  -- 60 Hz, 480p
  4 =>
  -- General settings
  ( 0 =>
    (
      addr => std_logic_vector( to_unsigned( 16#14#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#15d7#, 16 ) ),
      mask => "0001000000000000"
    ),

    1 =>
    (
      addr => std_logic_vector( to_unsigned( 16#15#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#2800#, 16 ) ),
      mask => "1000000000000000"
    ),
    2 =>
    (
      addr => std_logic_vector( to_unsigned( 16#13#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#2800#, 16 ) ),
      mask => "1100001100000000"
    ),
    3 =>
    (
      addr => std_logic_vector( to_unsigned( 16#16#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0083#, 16 ) ),
      mask => "1100000000000000"
    ),
    4 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4F#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0100#, 16 ) ),
      mask => "0110011001101111"
    ),
    5 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4E#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1900#, 16 ) ),
      mask => "0110011011111111"
    ),
    6 =>
    (
      addr => std_logic_vector( to_unsigned( 16#28#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#FFFF#, 16 ) ),
      mask => "0000000000000000"
    ),
    7 =>
    (
      addr => std_logic_vector( to_unsigned( 16#18#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#00fa#, 16 ) ),
      mask => "1111110000000000"
    ),
    8 =>
    (
      addr => std_logic_vector( to_unsigned( 16#19#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7c01#, 16 ) ),
      mask => "1000000000000000"
    ),
    9 =>
    (
      addr => std_logic_vector( to_unsigned( 16#1A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7de9#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout0
    10 =>
    (
      addr => std_logic_vector( to_unsigned( 16#08#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#10c4#, 16 ) ),
      mask => "0001000000000000"
    ),
    11 =>
    (
      addr => std_logic_vector( to_unsigned( 16#09#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0080#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout1
    12 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1452#, 16 ) ),
      mask => "1000000000000000"
    ),
    13 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0B#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0080#, 16 ) ),
      mask => "1111110000000000"
    )
  ),

--  -- 59.x Hz, 480p
  5 =>
  -- General settings
  ( 0 =>
    (
      addr => std_logic_vector( to_unsigned( 16#14#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#175d#, 16 ) ),
      mask => "0001000000000000"
    ),

    1 =>
    (
      addr => std_logic_vector( to_unsigned( 16#15#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#4c00#, 16 ) ),
      mask => "1000000000000000"
    ),
    2 =>
    (
      addr => std_logic_vector( to_unsigned( 16#13#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1400#, 16 ) ),
      mask => "1100001100000000"
    ),
    3 =>
    (
      addr => std_logic_vector( to_unsigned( 16#16#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0105#, 16 ) ),
      mask => "1100000000000000"
    ),
    4 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4F#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1000#, 16 ) ),
      mask => "0110011001101111"
    ),
    5 =>
    (
      addr => std_logic_vector( to_unsigned( 16#4E#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0800#, 16 ) ),
      mask => "0110011011111111"
    ),
    6 =>
    (
      addr => std_logic_vector( to_unsigned( 16#28#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#FFFF#, 16 ) ),
      mask => "0000000000000000"
    ),
    7 =>
    (
      addr => std_logic_vector( to_unsigned( 16#18#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#00fa#, 16 ) ),
      mask => "1111110000000000"
    ),
    8 =>
    (
      addr => std_logic_vector( to_unsigned( 16#19#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7c01#, 16 ) ),
      mask => "1000000000000000"
    ),
    9 =>
    (
      addr => std_logic_vector( to_unsigned( 16#1A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#7de9#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout0
    10 =>
    (
      addr => std_logic_vector( to_unsigned( 16#08#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#1083#, 16 ) ),
      mask => "0001000000000000"
    ),
    11 =>
    (
      addr => std_logic_vector( to_unsigned( 16#09#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0080#, 16 ) ),
      mask => "1000000000000000"
    ),
    -- Clkout1
    12 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0A#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#130d#, 16 ) ),
      mask => "1000000000000000"
    ),
    13 =>
    (
      addr => std_logic_vector( to_unsigned( 16#0B#, 7 ) ),
      data => std_logic_vector( to_unsigned( 16#0080#, 16 ) ),
      mask => "1111110000000000"
    )
  )
);

type fsmSingleValStates is ( idle, setDADDR, waitDRDY0,
                             applyMask, doWrite, waitDRDY1 );
type fsmTopStates is ( idle, setVal, waitVal, incInd, waitLock );
signal fsmTopCur, fsmTopNext : fsmTopStates := idle;
signal fsmSingleValCur, fsmSingleValNext : fsmSingleValStates := idle;
signal nextAddr : std_logic_vector( 6 downto 0 );
signal nextVal : std_logic_vector( 15 downto 0 );
signal nextMask : std_logic_vector( 15 downto 0 );
signal setNewVal : std_logic;

signal itemInd : integer range 0 to 13;

signal maskedVal : std_logic_vector( 15 downto 0 );

signal stateSel_int : std_logic_vector( 2 downto 0 );
begin

  dclk <= clk;

  -- Do masking.

  -- Simple seq.
  process( clk ) is
  begin
    if ( rising_edge( clk ) ) then
      if ( fsmTopCur = idle ) then
        stateSel_int <= stateSel;
      end if;
    end if;
  end process;

  -- Do index increasing.
  process( clk ) is
  begin
    if ( rising_edge( clk ) ) then
      if ( rst = '1' ) then
        itemInd <= 0;
      else
        if ( fsmTopCur = idle ) then
          itemInd <= 0;
        elsif ( fsmTopCur = incInd ) then
          itemInd <= itemInd + 1;
        end if;
      end if;
    end if;
  end process;

  -- Top FSM.
  process( clk ) is
  begin
    if ( rising_edge( clk ) ) then
      if ( rst = '1' ) then
        fsmTopCur <= idle;
      else
        fsmTopCur <= fsmTopNext;
      end if;
    end if;
  end process;

  process( fsmTopCur, doSwitch, fsmSingleValCur, locked, itemInd ) is
  begin
    case fsmTopCur is
      when idle =>
        if ( doSwitch = '1' ) then
          fsmTopNext <= setVal;
        else
          fsmTopNext <= idle;
        end if;

      when setVal =>
        fsmTopNext <= waitVal;

      when waitVal =>
        if ( fsmSingleValCur = idle ) then
          if ( itemInd = 13 ) then
            fsmTopNext <= waitLock;
          else
            fsmTopNext <= incInd;
          end if;
        else
          fsmTopNext <= waitVal;
        end if;

      when incInd =>
        fsmTopNext <= setVal;

      when waitLock =>
        if ( locked = '1' ) then
          fsmTopNext <= idle;
        else
          fsmTopNext <= waitLock;
        end if;

    end case;
  end process;

  process( fsmTopCur, stateSel_int, itemInd ) is
  begin
    case fsmTopCur is
      when idle =>
        nextMask <= ( others => '-' );
        nextVal <= ( others => '-' );
        nextAddr <= ( others => '-' );
        setNewVal <= '0';
        rstMMCM <= '0';

      when setVal =>
        nextMask <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).mask;
        nextVal <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).data;
        nextAddr <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).addr;
        rstMMCM <= '1';
        setNewVal <= '1';

      when waitVal =>
        nextMask <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).mask;
        nextVal <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).data;
        nextAddr <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).addr;
        rstMMCM <= '1';
        setNewVal <= '0';

      when incInd =>
        nextMask <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).mask;
        nextVal <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).data;
        nextAddr <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).addr;
        rstMMCM <= '1';
        setNewVal <= '0';

      when waitLock =>
        nextMask <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).mask;
        nextVal <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).data;
        nextAddr <= reconfROM( to_integer( unsigned( stateSel_int ) ) )( itemInd ).addr;
        rstMMCM <= '0';
        setNewVal <= '0';

    end case;
  end process;

  -- FSM for changing a single value.
  process( clk ) is
  begin

    if ( rising_edge( clk ) ) then
      if ( rst = '1' ) then
        fsmSingleValCur <= idle;
      else
        fsmSingleValCur <= fsmSingleValNext;
      end if;
    end if;
  end process;

  process( fsmSingleValCur, setNewVal, drdy ) is
  begin
    case fsmSingleValCur is
      when idle =>
        if ( setNewVal = '1' ) then
          fsmSingleValNext <= setDADDR;
        else
          fsmSingleValNext <= idle;
        end if;

      when setDADDR =>
        fsmSingleValNext <= waitDRDY0;

      when waitDRDY0 =>
        if ( drdy = '1' ) then
          fsmSingleValNext <= applyMask;
        else
          fsmSingleValNext <= waitDRDY0;
        end if;

      when applyMask =>
        fsmSingleValNext <= doWrite;

      when doWrite =>
        fsmSingleValNext <= waitDRDY1;

      when waitDRDY1 =>
        if ( drdy = '1' ) then
          fsmSingleValNext <= idle;
        else
          fsmSingleValNext <= waitDRDY1;
        end if;

      when others =>
        fsmSingleValNext <= idle;
    end case;
  end process;

  process( fsmSingleValCur, nextAddr, maskedVal ) is
  begin
    case fsmSingleValCur is
      when idle =>
        diSig <= ( others => '-' );
        dwe <= '0';
        den <= '0';
        daddr <= ( others => '-' );

      when setDADDR =>
        diSig <= ( others => '-' );
        dwe <= '0';
        den <= '1';
        daddr <= nextAddr;

      when waitDRDY0 =>
        diSig <= ( others => '-' );
        dwe <= '0';
        den <= '0';
        daddr <= nextAddr;

      when applyMask =>
        diSig <= ( others => '-' );
        dwe <= '0';
        den <= '0';
        daddr <= nextAddr;

      when doWrite =>
        diSig <= maskedVal;
        dwe <= '1';
        den <= '1';
        daddr <= nextAddr;

      when waitDRDY1 =>
        diSig <= ( others => '-' );
        dwe <= '0';
        den <= '0';
        daddr <= nextAddr;
    end case;

  end process;

end rtl;

  process( clk ) is
  begin
    if ( rising_edge( clk ) ) then
      if ( fsmSingleValCur = applyMask ) then
        maskedVal <= ( nextMask and doSig ) or ( nextVal and not( nextMask ) ) ;


        ind := offset + x;

        charPxl <= font( char )( ind );
      end if;
    end if;


-----------------------------------------------------------------------
-- Title: Fractional Divier
-- Author: zwenergy
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

entity fracDiv is
  generic (
    mul : integer;
    div : integer;
    maxInt : integer
  );
  port (
    clk : in std_logic;
    rst : in std_logic;
    clkOut : out std_logic
  );
end fracDiv;

architecture rtl of fracDiv is
signal cnt : integer range 0 to maxInt;
begin

  process( clk ) is
  variable tmpCnt : integer range 0 to maxInt;
  begin
    if ( rising_edge( clk ) ) then
      if ( rst = '1' ) then
        cnt <= 0;
      else
        tmpCnt := cnt + mul;
        if ( tmpCnt >= div ) then
          tmpCnt := tmpCnt - div;

  clkOut <= '0' when ( cnt <= div / 2 ) else '1';

end rtl;

        end if;

        cnt <= tmpCnt;
      end if;


-----------------------------------------------------------------------
-- Title: GBA color correction
-- Author: zwenergy
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

entity gbaColorCorr is
  port(
    gbaRed : in std_logic_vector( 4 downto 0 );
    gbaGreen : in std_logic_vector( 4 downto 0 );
    gbaBlue : in std_logic_vector( 4 downto 0 );

    rGBACol : out std_logic_vector( 7 downto 0 );
    gGBACol : out std_logic_vector( 7 downto 0 );
    bGBACol : out std_logic_vector( 7 downto 0 )
  );
end gbaColorCorr;

architecture rtl of gbaColorCorr is
signal baseRed, baseGreen, baseBlue : std_logic_vector( 7 downto 0 );
begin

  process( baseRed, baseGreen, baseBlue, gbaRed, gbaGreen, gbaBlue ) is
  variable tmpRed, tmpGreen, tmpBlue : signed( 9 downto 0 );
  begin
    tmpRed :=  signed( "00" & baseRed ) + signed( "00000000" & gbaRed( 1 downto 0 ) ) + signed( "0000" & gbaGreen( 4 downto 0 ) & '0' ) - signed( "00000" & gbaBlue );
    if ( tmpRed < 0 ) then
      tmpRed := to_signed( 0, tmpRed'length );
    elsif ( tmpRed > 255 ) then
      tmpRed := to_signed( 255, tmpRed'length );
    end if;

    tmpGreen :=  signed( "00" & baseGreen ) + signed( "0000" & gbaRed( 4 downto 0 ) & '0' ) - signed( "00000" & gbaGreen( 4 downto 0 ) ) + signed( "000000" & gbaBlue( 3 downto 0 ) );
    if ( tmpGreen < 0 ) then
      tmpGreen := to_signed( 0, tmpGreen'length );
    elsif ( tmpGreen > 255 ) then
      tmpGreen := to_signed( 255, tmpGreen'length );
    end if;

    tmpBlue :=  signed( "00" & baseBlue ) + signed( "00000000" & gbaRed( 1 downto 0 ) ) + signed( "0000" & gbaGreen( 4 downto 0 ) & '0' ) - signed( "00000" & gbaBlue( 4 downto 0 ) );
    if ( tmpBlue < 0 ) then
      tmpBlue := to_signed( 0, tmpBlue'length );
    elsif ( tmpBlue > 255 ) then
      tmpBlue := to_signed( 255, tmpBlue'length );
    end if;

    rGBACol <= std_logic_vector( tmpRed( 7 downto 0 )  );
    gGBACol <= std_logic_vector( tmpGreen( 7 downto 0 )  );
    bGBACol <= std_logic_vector( tmpBlue( 7 downto 0 )  );
  end process;

process( gbaRed ) is begin


entity gbaColorCorrNew is
  port(
    gbaRed : in std_logic_vector( 4 downto 0 );
    gbaGreen : in std_logic_vector( 4 downto 0 );


-----------------------------------------------------------------------
-- Title: Line buffer
-- Author: zwenergy
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity lineBuffer is
  generic(
    nrStgs : integer range 1 to 20 := 4
  );
  port(
    clkW : in std_logic;
    clkR : in std_logic;
    rst : in std_logic;
    redIn : in std_logic_vector( 7 downto 0 );
    greenIn : in std_logic_vector( 7 downto 0 );
    blueIn :  in std_logic_vector( 7 downto 0 );
    wEn : in std_logic;
    pxlCntWrite : in std_logic_vector( 7 downto 0 );
    pushLine : in std_logic;
    newFrameIn : in std_logic;

    redOutPrev : out std_logic_vector( 7 downto 0 );
    greenOutPrev : out std_logic_vector( 7 downto 0 );
    blueOutPrev :  out std_logic_vector( 7 downto 0 );
    redOutCur : out std_logic_vector( 7 downto 0 );
    greenOutCur : out std_logic_vector( 7 downto 0 );
    blueOutCur :  out std_logic_vector( 7 downto 0 );
    redOutNext : out std_logic_vector( 7 downto 0 );
    greenOutNext : out std_logic_vector( 7 downto 0 );
    blueOutNext :  out std_logic_vector( 7 downto 0 );

    pxlCntRead : in std_logic_vector( 7 downto 0 );
    pullLine : in std_logic;

    sameLine : out std_logic;
    newFrameOut : out std_logic
  );
end lineBuffer;

architecture rtl of lineBuffer is
signal inCnt : integer range 0 to nrStgs-1;
signal outCntCur, outCntPrev, outCntNext : integer range 0 to nrStgs-1;
signal inCntSel, outCntCurSel, outCntPrevSel, outCntNextSel : std_logic;
signal newFrames_sel0, newFrames_sel1 : std_logic_vector( nrStgs - 1 downto 0 );
signal wEnMult : std_logic_vector( nrStgs - 1 downto 0 );

type readDataMult is array (0 to nrStgs - 1) of std_logic_vector( 7 downto 0 );
signal redOut_int : readDataMult;
signal greenOut_int : readDataMult;
signal blueOut_int : readDataMult;

signal readAddr, writeAddr : std_logic_vector( 8 downto 0 );
signal readSel : std_logic_vector( 0 to nrStgs - 1 );

begin

  process( wEn, inCnt ) is
  begin

    for i in 0 to nrStgs - 1 loop
      if ( inCnt = i ) then
        wEnMult( i ) <= wEn;
      else
        wEnMult( i ) <= '0';
      end if;
    end loop;

  end process;

  redOutPrev <= redOut_int( outCntPrev );
  greenOutPrev <= greenOut_int( outCntPrev );
  blueOutPrev <= blueOut_int( outCntPrev );

  redOutCur <= redOut_int( outCntCur );
  greenOutCur <= greenOut_int( outCntCur );
  blueOutCur <= blueOut_int( outCntCur );

  redOutNext <= redOut_int( outCntNext );
  greenOutNext <= greenOut_int( outCntNext );
  blueOutNext <= blueOut_int( outCntNext );

  process( outCntCurSel, outCntPrevSel, outCntNextSel,
           outCntCur, outCntPrev, outCntNext ) is
  begin
    for i in 0 to nrStgs - 1 loop
      if ( ( outCntCur = i and outCntCurSel = '1' ) or
           ( outCntPrev = i and outCntPrevSel = '1' ) or
           ( outCntNext = i and outCntNextSel = '1' ) ) then
        readSel( i ) <= '1';
      else

    if ( rising_edge( clkW ) ) then
      if ( rst = '1' ) then
        inCnt <= 0;
        inCntSel <= '0';
        newFrames_Sel0 <= ( others => '0' );
        newFrames_Sel1 <= ( others => '0' );
      else
        if ( pushLine = '1' ) then
          if ( inCntSel = '1' ) then
            newFrames_Sel1( inCnt ) <= newFrameIn;
          else
            newFrames_Sel0( inCnt ) <= newFrameIn;
          end if;

          if ( inCnt  = nrStgs - 1 ) then
            inCnt <= 0;
            inCntSel <= not inCntSel;
          else
            inCnt <= inCnt + 1;
           end if;
        end if;
      end if;
    end if;
  end process;

  process( clkR ) is
  begin
    if ( rising_edge( clkR ) ) then
      if ( rst = '1' ) then
          outCntPrev <= nrStgs - 1;
          outCntCur <= 0;
          outCntNext <= 1;
          outCntPrevSel <= '1';
          outCntCurSel <= '0';
          outCntNextSel <= '0';
      else
        if ( pullLine = '1' ) then
          if ( outCntCur = nrStgs - 1 ) then
            outCntCur <= 0;
            outCntCurSel <= not outCntCurSel;
          else
            outCntCur <= outCntCur + 1;
          end if;

          if ( outCntPrev = nrStgs - 1 ) then
            outCntPrev <= 0;
            outCntPrevSel <= not outCntPrevSel;
          else
            outCntPrev <= outCntPrev + 1;
          end if;

          if ( outCntNext = nrStgs - 1 ) then
            outCntNext <= 0;
            outCntNextSel <= not outCntNextSel;
          else
            outCntNext <= outCntNext + 1;
          end if;
        end if;
      end if;
    end if;
  end process;

  sameLine <= '1' when ( inCnt = outCntCur and inCntSel = outCntCurSel ) else '0';
  newFrameOut <= newFrames_Sel0( outCntCur ) when outCntCurSel = '0' else newFrames_Sel1( outCntCur );
  writeAddr <= inCntSel & pxlCntWrite;

  -- Instantiate buffers.
  gen_buffers : for i in 0 to nrStgs - 1 generate
    curBuff : entity work.singeLineBuffer( rtl )
      port map(
        clkW => clkW,
        clkR => clkR,
        rst => rst,
        wAddr => writeAddr,
        wEn => wEnMult( i ),
        rAddr( 8 ) => readSel( i ),
        rAddr( 7 downto 0 ) => pxlCntRead,
        redDataIn => redIn,
        greenDataIn => greenIn,
        blueDataIn => blueIn,
        redDataOut => redOut_int( i ),
        greenDataOut => greenOut_int( i ),
        blueDataOut => blueOut_int( i )
      );
  end generate gen_buffers;

end rtl;

        readSel( i ) <= '0';
      end if;
    end loop;
  end process;


    curPxlCnt : in std_logic_vector( 7 downto 0 );
    lineChange : in std_logic;

    curLineCurPxlRedIn : in std_logic_vector( 7 downto 0 );
    curLineCurPxlGreenIn : in std_logic_vector( 7 downto 0 );
    curLineCurPxlBlueIn : in std_logic_vector( 7 downto 0 );

    prevLineCurPxlRedIn : in std_logic_vector( 7 downto 0 );
    prevLineCurPxlGreenIn : in std_logic_vector( 7 downto 0 );
    prevLineCurPxlBlueIn : in std_logic_vector( 7 downto 0 );

    nextLineCurPxlRedIn : in std_logic_vector( 7 downto 0 );
    nextLineCurPxlGreenIn : in std_logic_vector( 7 downto 0 );
    nextLineCurPxlBlueIn : in std_logic_vector( 7 downto 0 );

    prevLinePrevPxlRedOut : out std_logic_vector( 7 downto 0 );
    prevLinePrevPxlGreenOut : out std_logic_vector( 7 downto 0 );
    prevLinePrevPxlBlueOut : out std_logic_vector( 7 downto 0 );

    prevLineCurPxlRedOut : out std_logic_vector( 7 downto 0 );
    prevLineCurPxlGreenOut : out std_logic_vector( 7 downto 0 );
    prevLineCurPxlBlueOut : out std_logic_vector( 7 downto 0 );

    prevLineNextPxlRedOut : out std_logic_vector( 7 downto 0 );
    prevLineNextPxlGreenOut : out std_logic_vector( 7 downto 0 );
    prevLineNextPxlBlueOut : out std_logic_vector( 7 downto 0 );

    curLinePrevPxlRedOut : out std_logic_vector( 7 downto 0 );
    curLinePrevPxlGreenOut : out std_logic_vector( 7 downto 0 );
    curLinePrevPxlBlueOut : out std_logic_vector( 7 downto 0 );

    curLineCurPxlRedOut : out std_logic_vector( 7 downto 0 );
    curLineCurPxlGreenOut : out std_logic_vector( 7 downto 0 );
    curLineCurPxlBlueOut : out std_logic_vector( 7 downto 0 );

    curLineNextPxlRedOut : out std_logic_vector( 7 downto 0 );
    curLineNextPxlGreenOut : out std_logic_vector( 7 downto 0 );
    curLineNextPxlBlueOut : out std_logic_vector( 7 downto 0 );

    nextLinePrevPxlRedOut : out std_logic_vector( 7 downto 0 );
    nextLinePrevPxlGreenOut : out std_logic_vector( 7 downto 0 );
    nextLinePrevPxlBlueOut : out std_logic_vector( 7 downto 0 );

    nextLineCurPxlRedOut : out std_logic_vector( 7 downto 0 );
    nextLineCurPxlGreenOut : out std_logic_vector( 7 downto 0 );
    nextLineCurPxlBlueOut : out std_logic_vector( 7 downto 0 );

    nextLineNextPxlRedOut : out std_logic_vector( 7 downto 0 );
    nextLineNextPxlGreenOut : out std_logic_vector( 7 downto 0 );
    nextLineNextPxlBlueOut : out std_logic_vector( 7 downto 0 );

    pxlCntRead : out std_logic_vector( 7 downto 0 )
  );
end lineCache;

architecture rtl of lineCache is
type pixel is array( 0 to 2 ) of std_logic_vector( 7 downto 0 );
signal curLinePrevPxl, curLineCurPxl, curLineNextPxl,
  prevLinePrevPxl, prevLineCurPxl, prevLineNextPxl,
  nextLinePrevPxl, nextLineCurPxl, nextLineNextPxl : pixel;

signal pxlCntRead_int, pxlCntRead_del, pxlCntRead_del2 : std_logic_vector( 7 downto 0 );
signal incAddr, firstPxlHandled, shiftRegs, lineChange_del : std_logic;
begin

  process( clk ) is
  begin
    if rising_edge( clk ) then
      if ( rst = '1' ) then
        pxlCntRead_del <= ( others => '0' );
        pxlCntRead_del2 <= ( others => '0' );
        firstPxlHandled <= '0';
        lineChange_del <= '0';
      else
        pxlCntRead_del <= pxlCntRead_int;
        pxlCntRead_del2 <= pxlCntRead_del;
        lineChange_del <= lineChange;

        if ( curPxlCnt = "00000000" ) then
          firstPxlHandled <= '1';
        else
          firstPxlHandled <= '0';
        end if;

        if ( lineChange_del = '1' ) then
          firstPxlHandled <= '0';
        end if;

        curLineNextPxl( 0 ) <= curLineCurPxlRedIn;
        curLineNextPxl( 1 ) <= curLineCurPxlGreenIn;
        curLineNextPxl( 2 ) <= curLineCurPxlBlueIn;

        prevLineNextPxl( 0 ) <= prevLineCurPxlRedIn;
        prevLineNextPxl( 1 ) <= prevLineCurPxlGreenIn;
        prevLineNextPxl( 2 ) <= prevLineCurPxlBlueIn;

        nextLineNextPxl( 0 ) <= nextLineCurPxlRedIn;
        nextLineNextPxl( 1 ) <= nextLineCurPxlGreenIn;
        nextLineNextPxl( 2 ) <= nextLineCurPxlBlueIn;

        if ( shiftRegs = '1' ) then
          curLineCurPxl <= curLineNextPxl;
          curLinePrevPxl <= curLineCurPxl;

          prevLineCurPxl <= prevLineNextPxl;
          prevLinePrevPxl <= prevLineCurPxl;

          nextLineCurPxl <= nextLineNextPxl;
          nextLinePrevPxl <= nextLineCurPxl;
        end if;

      end if;
    end if;
  end process;

  incAddr <= '0' when curPxlCnt = "00000000" and firstPxlHandled = '0' else '1';
  pxlCntRead_int <= std_logic_vector( unsigned( curPxlCnt ) + 1 ) when incAddr = '1' else
                    curPxlCnt;

  pxlCntRead <= pxlCntRead_int;

  shiftRegs <= '1' when pxlCntRead_del /= pxlCntRead_del2 else '0';

  prevLinePrevPxlRedOut <= prevLinePrevPxl( 0 );
  prevLinePrevPxlGreenOut <= prevLinePrevPxl( 1 );
  prevLinePrevPxlBlueOut <= prevLinePrevPxl( 2 );

  prevLineCurPxlRedOut <= prevLineCurPxl( 0 );
  prevLineCurPxlGreenOut <= prevLineCurPxl( 1 );
  prevLineCurPxlBlueOut <= prevLineCurPxl( 2 );

  prevLineNextPxlRedOut <= prevLineNextPxl( 0 );
  prevLineNextPxlGreenOut <= prevLineNextPxl( 1 );
  prevLineNextPxlBlueOut <= prevLineNextPxl( 2 );

  curLinePrevPxlRedOut <= curLinePrevPxl( 0 );
  curLinePrevPxlGreenOut <= curLinePrevPxl( 1 );
  curLinePrevPxlBlueOut <= curLinePrevPxl( 2 );

  curLineCurPxlRedOut <= curLineCurPxl( 0 );
  curLineCurPxlGreenOut <= curLineCurPxl( 1 );
  curLineCurPxlBlueOut <= curLineCurPxl( 2 );

  curLineNextPxlRedOut <= curLineNextPxl( 0 );
  curLineNextPxlGreenOut <= curLineNextPxl( 1 );
  curLineNextPxlBlueOut <= curLineNextPxl( 2 );

  nextLinePrevPxlRedOut <= nextLinePrevPxl( 0 );
  nextLinePrevPxlGreenOut <= nextLinePrevPxl( 1 );
  nextLinePrevPxlBlueOut <= nextLinePrevPxl( 2 );

  nextLineCurPxlRedOut <= nextLineCurPxl( 0 );
  nextLineCurPxlGreenOut <= nextLineCurPxl( 1 );
  nextLineCurPxlBlueOut <= nextLineCurPxl( 2 );

  nextLineNextPxlRedOut <= nextLineNextPxl( 0 );
  nextLineNextPxlGreenOut <= nextLineNextPxl( 1 );
  nextLineNextPxlBlueOut <= nextLineNextPxl( 2 );

end rtl;


-----------------------------------------------------------------------
-- Title: OSD
-- Author: zwenergy
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

entity osd is
  generic(
    scale : integer;
    frameWidth : integer;
    frameHeight : integer
  );
  port(
    pxlX : in integer range 0 to 1665;
    pxlY : in integer range -25 to 1000;
    osdEnableIn : in std_logic;
    clk : in std_logic;
    rst : in std_logic;

    osdRed : out std_logic_vector( 7 downto 0 );
    osdGreen : out std_logic_vector( 7 downto 0 );
    osdBlue : out std_logic_vector( 7 downto 0 );

    smooth2xIn : in std_logic;
    smooth4xIn : in std_logic;
    pixelGridIn : in std_logic;
    bgridIn : in std_logic;
    gridMultIn : in std_logic;
    colorModeIn : in std_logic;
    rateIn : in std_logic;
    controllerOSDActive : in std_logic;

    osdEnableOut : out std_logic;
    smooth2xOut : out std_logic;
    smooth4xOut : out std_logic;
    pixelGridOut : out std_logic;
    bgridOut : out std_logic;
    gridMultOut : out std_logic;
    colorModeOut : out std_logic;
    rateOut : out std_logic;

    osdState : in std_logic_vector( 7 downto 0 );

    configValid : in std_logic;
    stateValid : in std_logic;
    rxValid : in std_logic
  );
end entity;

architecture rtl of osd is
-- Assuming the resolution is 1280x720
constant MENU_WIDTHFIELDS : integer := 27;
constant MENU_HEIGHTFIELDS : integer := 12;
constant CHARWIDTH : integer := 5;
constant CHARHEIGHT : integer := 7;
constant CHARSPACE : integer := 1;
constant FIELDHEIGHT : integer := CHARHEIGHT + CHARSPACE;
constant FIELDWIDTH : integer := CHARWIDTH + CHARSPACE;
constant MENUSTARTX : integer := (frameWidth/2) - ( ( ( FIELDWIDTH * MENU_WIDTHFIELDS ) / 2 ) * scale );
constant MENUSTARTY : integer := (frameHeight/2)  - ( ( ( FIELDHEIGHT * MENU_HEIGHTFIELDS ) / 2) * scale );
constant MENUENDX : integer := MENUSTARTX + ( FIELDWIDTH * MENU_WIDTHFIELDS * scale );
constant MENUENDY : integer := MENUSTARTY + ( FIELDHEIGHT * MENU_HEIGHTFIELDS * scale );
constant PXLGRIDFIELDX : integer := 15;
constant PXLGRIDFIELDY : integer := 3;
constant GRIDMULTFIELDX : integer := 15;
constant GRIDMULTFIELDY : integer := PXLGRIDFIELDY + 1;
constant SMOOTHFIELDX : integer := 15;
constant SMOOTHFIELDY : integer := GRIDMULTFIELDY + 1;
constant COLORFIELDX : integer := 15;
constant COLORFIELDY : integer := SMOOTHFIELDY + 1;
constant FRAMEFIELDX : integer := 15;
constant FRAMEFIELDY : integer := COLORFIELDY + 1;
constant PADDISPFIELDX : integer := 15;
constant PADDISPFIELDY : integer := FRAMEFIELDY + 1;

type tLine  is array( 0 to MENU_WIDTHFIELDS - 1 ) of integer range 0 to 43;
type tMenuFrame is array( 0 to MENU_HEIGHTFIELDS - 1 ) of tLine;

attribute ram_style : string;
signal mainMenu : tMenuFrame := (
-- One empty line
( 39, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 40 ),
-- GBAHD v1.4B
( 41, 00, 00, 00, 00, 00, 00, 00, 07, 02, 01, 08, 04, 00, 27, 36, 30, 02, 00, 00, 00, 00, 00, 00, 00, 00, 41 ),
-- One empty line
( 37, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 38 ),
-- PXL GRID
( 41, 00, 16, 24, 12, 00, 07, 18, 09, 04, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 41 ),
-- Method
( 41, 00, 13, 05, 20, 08, 15, 04, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 41 ),
-- Smoothing
( 41, 00, 19, 13, 15, 15, 20, 08, 09, 14, 07, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 41 ),
-- Color
( 41, 00, 03, 15, 12, 15, 18, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 41 ),
-- Framerate
( 41, 00, 06, 18, 01, 13, 05, 18, 01, 20, 05, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 41 ),
-- Pad display
( 41, 00, 16, 01, 04, 00, 04, 09, 19, 16, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 41 ),
-- One empty line
( 41, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 41 ),
-- START: SAVE | B: REVERT
( 41, 00, 19, 20, 01, 18, 20, 42, 00, 19, 01, 22, 05, 00, 41, 00, 02, 42, 00, 01, 02, 15, 18, 20, 00, 00, 41 ),
-- Bottom Line
( 40, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 39 )
);

-- Have to add this attribute to NOT use RAM (since all is used for the line buffer)
attribute ram_style of mainMenu : signal is "registers";

signal fieldYCnt : integer range 0 to MENU_HEIGHTFIELDS - 1;
signal fieldXCnt : integer range 0 to MENU_WIDTHFIELDS - 1;
signal pxlXCnt : integer range 0 to FIELDWIDTH - 1;
signal pxlYCnt : integer range 0 to FIELDHEIGHT - 1;

signal menuArea : std_logic;
signal curSpace : std_logic;
signal nextOSDShow : std_logic;

signal char, char_reg : integer range 0 to 37;
-- Have to add this attribute to NOT use RAM (since all is used for the line buffer)
attribute ram_style of char_reg : signal is "registers";

signal charX : integer range 0 to 4;
signal charY: integer range 0 to 6;
signal charPxl : std_logic;

signal scaleCntX, scaleCntY : integer range 0 to SCALE - 1;

-- 0: Normal, 1: GBA mode
signal colorMode_int : std_logic;

-- 0: 60hz, 1: 59....
signal framerate : std_logic;

signal smooth2x_int, smooth4x_int, pixelGrid_int, bgrid_int, gridMult_int : std_logic;

signal lineSelected : integer range 0 to MENU_HEIGHTFIELDS - 1;
signal lineActive, osdEnable_int : std_logic;

begin

  smooth2xOut <= smooth2x_int;
  smooth4xOut <= smooth4x_int;
  pixelGridOut <= pixelGrid_int;
  bgridOut <= bgrid_int;
  gridMultOut <= gridMult_int;
  colorModeOut <= colorMode_int;
  rateOut <= framerate;

  -- Update menu.
  process( smooth2x_int, smooth4x_int, pixelGrid_int, bgrid_int, gridMult_int, colorMode_int, framerate, controllerOSDActive ) is
  begin
    if ( smooth2x_int = '1' ) then
      -- 2X
      mainMenu( SMOOTHFIELDY )( SMOOTHFIELDX ) <= 28;
      mainMenu( SMOOTHFIELDY )( SMOOTHFIELDX + 1 ) <= 24;
      mainMenu( SMOOTHFIELDY )( SMOOTHFIELDX + 2 ) <= 0;
    elsif ( smooth4x_int = '1' ) then
      -- 4X
      mainMenu( SMOOTHFIELDY )( SMOOTHFIELDX ) <= 30;
      mainMenu( SMOOTHFIELDY )( SMOOTHFIELDX + 1 ) <= 24;
      mainMenu( SMOOTHFIELDY )( SMOOTHFIELDX + 2 ) <= 0;
    else
      -- OFF
      mainMenu( SMOOTHFIELDY )( SMOOTHFIELDX ) <= 15;
      mainMenu( SMOOTHFIELDY )( SMOOTHFIELDX + 1 ) <= 6;

        mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 3 ) <= 7;
        mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 4 ) <= 8;
        mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 5 ) <= 20;
      else
        -- Dark
        mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX ) <= 4;
        mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 1 ) <= 1;
        mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 2 ) <= 18;
        mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 3 ) <= 11;
        mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 4 ) <= 0;
        mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 5 ) <= 0;

      end if;
    else
      -- OFF
      mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX ) <= 15;
      mainMenu( PXLGRIDFIELDY )( SMOOTHFIELDX + 1 ) <= 6;
      mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 2 ) <= 6;
      mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 3 ) <= 0;
      mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 4 ) <= 0;
      mainMenu( PXLGRIDFIELDY )( PXLGRIDFIELDX + 5 ) <= 0;
    end if;

    if ( gridMult_int = '1' ) then
      -- MULT
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX ) <= 13;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 1 ) <= 21;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 2 ) <= 12;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 3 ) <= 20;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 4 ) <= 0;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 5 ) <= 0;
    else
      -- ADD
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX ) <= 1;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 1 ) <= 4;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 2 ) <= 4;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 3 ) <= 0;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 4 ) <= 0;
      mainMenu( GRIDMULTFIELDY )( GRIDMULTFIELDX + 5 ) <= 0;
    end if;

    if ( colorMode_int = '0' ) then
      -- Normal
      mainMenu( COLORFIELDY )( COLORFIELDX ) <= 14;
      mainMenu( COLORFIELDY )( COLORFIELDX + 1 ) <= 15;
      mainMenu( COLORFIELDY )( COLORFIELDX + 2 ) <= 18;
      mainMenu( COLORFIELDY )( COLORFIELDX + 3 ) <= 13;
      mainMenu( COLORFIELDY )( COLORFIELDX + 4 ) <= 1;
      mainMenu( COLORFIELDY )( COLORFIELDX + 5 ) <= 12;
    else
    --GBA
      mainMenu( COLORFIELDY )( COLORFIELDX ) <= 7;
      mainMenu( COLORFIELDY )( COLORFIELDX + 1 ) <= 2;
      mainMenu( COLORFIELDY )( COLORFIELDX + 2 ) <= 1;
      mainMenu( COLORFIELDY )( COLORFIELDX + 3 ) <= 0;
      mainMenu( COLORFIELDY )( COLORFIELDX + 4 ) <= 0;
      mainMenu( COLORFIELDY )( COLORFIELDX + 5 ) <= 0;
    end if;

    --60hz
    if ( framerate = '0' ) then
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX ) <= 32;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 1 ) <= 15;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 2 ) <= 8;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 3 ) <= 26;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 4 ) <= 0;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 5 ) <= 0;
    else
      --59.7Hz
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX ) <= 31;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 1 ) <= 35;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 2 ) <= 36;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 3 ) <= 33;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 4 ) <= 8;
      mainMenu( FRAMEFIELDY )( FRAMEFIELDX + 5 ) <= 26;
    end if;

    -- Input display
    if ( controllerOSDActive = '0' ) then
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX ) <= 15;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 1 ) <= 6;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 2 ) <= 6;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 3 ) <= 0;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 4 ) <= 0;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 5 ) <= 0;
    else
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX ) <= 15;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 1 ) <= 14;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 2 ) <= 0;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 3 ) <= 0;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 4 ) <= 0;
      mainMenu( PADDISPFIELDY )( PADDISPFIELDX + 5 ) <= 0;
    end if;
  end process;

  menuArea <= '1' when ( pxlX >= MENUSTARTX and pxlX < MENUENDX and
                         pxlY >= MENUSTARTY and pxlY < MENUENDY ) else '0';

  lineActive <= '1' when ( lineSelected = fieldYCnt ) else '0';

  curSpace <= '1' when ( pxlXCnt = FIELDWIDTH - 1 or pxlYCnt = FIELDHEIGHT - 1 ) else '0';

  char <= mainMenu( fieldYCnt )( fieldXCnt ) when ( curSpace = '0' ) else 0;
  charX <= pxlXCnt when ( menuArea = '1' and curSpace = '0' ) else 0;
  charY <= pxlYCnt when ( menuArea = '1' and curSpace = '0' ) else 0;

  font_inst : entity work.font5x7( rtl )
  port map(
    char => char,
    x => charX,
    y => charY,
    clk => clk,
    rst => rst,
    charPxl => charPxl
  );

  process( clk ) is
  begin
    if ( rising_edge( clk ) ) then
      if ( rst = '1' ) then
        osdEnable_int <= '0';
        fieldYCnt <= 0;
        fieldXCnt <= 0;
        pxlYCnt <= 0;
        pxlXCnt <= 0;
        nextOSDShow <= '0';
        scaleCntX <= 0;
        scaleCntY <= 0;

        smooth2x_int <= '0';
        smooth4x_int <= '0';
        pixelGrid_int <= '0';
        gridMult_int <= '0';
        bgrid_int <= '0';
        colorMode_int <= '0';
        framerate <= '0';
        lineSelected <= 3;

        char_reg <= 0;

      else

        nextOSDShow <= menuArea and osdEnable_int;
        char_reg <= char;

        if ( rxValid = '1' ) then
          if ( stateValid = '1' ) then
            osdEnable_int <= osdEnableIn;
            lineSelected <= to_integer( unsigned( osdState ) );

          elsif ( configValid = '1' ) then
            smooth2x_int <= smooth2xIn;
            smooth4x_int <= smooth4xIn;
            pixelGrid_int <= pixelGridIn;
            bgrid_int <= bgridIn;
            gridMult_int <= gridMultIn;
            colorMode_int <= colorModeIn;
            framerate <= rateIn;

          end if;

        end if;

        -- Zero everything.
        if ( pxlX = 0 and pxlY = 0 ) then
          fieldYCnt <= 0;
          fieldXCnt <= 0;
          pxlYCnt <= 0;
          pxlXCnt <= 0;
          scaleCntX <= 0;
          scaleCntY <= 0;
        end if;

        if ( osdEnable_int = '1' and menuArea = '1' ) then
          -- Increase counters.
          if ( scaleCntX = SCALE - 1 ) then
            scaleCntX <= 0;
          else
            scaleCntX <= scaleCntX + 1;
          end if;

          if ( scaleCntX = SCALE - 1 ) then
            -- Reached end of a field (X)
            if ( pxlXCnt = FIELDWIDTH - 1 ) then
              pxlXCnt <= 0;

              -- Reached end of the menu (X)
              if ( fieldXCnt = MENU_WIDTHFIELDS - 1 ) then
                fieldXCnt <= 0;

                if ( scaleCntY = SCALE - 1 ) then
                  scaleCntY <= 0;
                else
                  scaleCntY <= scaleCntY + 1;
                end if;

                if ( scaleCntY = SCALE - 1 ) then
                  -- Reached end of a field (Y)
                  if ( pxlYCnt = FIELDHEIGHT - 1 ) then
                    pxlYCnt <= 0;
                    if ( fieldYCnt = MENU_HEIGHTFIELDS - 1 ) then
                      fieldYCnt <= 0;
                    else
                      fieldYCnt <= fieldYCnt + 1;
                    end if;
                  else
                    pxlYCnt <= pxlYCnt + 1;
                  end if;
                end if;

              else
                fieldXCnt <= fieldXCnt + 1;
              end if;
            else

              pxlXCnt <= pxlXCnt + 1;
            end if;
          end if;
        end if;

        -- Pipeline outgoing signals.
        osdEnableOut <= nextOSDShow;

        if ( lineActive = '1' ) then
          osdRed <= ( others => ( not charPxl ) );
          osdGreen <= ( others => ( not charPxl ) );
          osdBlue <= ( others => ( not charPxl ) );
        else
          osdRed <= ( others => ( charPxl ) );
          osdGreen <= ( others => ( charPxl ) );
          osdBlue <= ( others => ( charPxl ) );
        end if;

      end if;
    end if;
  end process;

end rtl;

      mainMenu( SMOOTHFIELDY )( SMOOTHFIELDX + 2 ) <= 6;
    end if;

    if ( pixelGrid_int = '1' ) then
      if ( bgrid_int = '1' ) then


  process( clk ) is
  begin
    if rising_edge( clk ) then
        if ( rst = '1' ) then
          pxlXCnt <= 0;
          pxlYCnt <= 0;
          pxlXCnt_sub <= 0;
          pxlYCnt_sub <= 0;
          scaleCntX <= 0;
          scaleCntY <= 0;

          butUp <= '0';
          butDown <= '0';
          butLeft <= '0';
          butRight <= '0';
          butA <= '0';
          butB <= '0';
          butL <= '0';
          butR <= '0';
          butStart <= '0';
          butSelect <= '0';

          overlayInact <= '0';
          overlayAct <= '0';

        else
          -- Zero everything.
          if ( pxlX = 0  ) then
            pxlXCnt <= 0;
            scaleCntX <= 0;

            if ( pxlY = 0 ) then
                scaleCntY <= 0;
                pxlYCnt <= 0;
            end if;
          end if;

          if ( scaleCntX = scale - 1 ) then
            scaleCntX <= 0;
            pxlXCnt <= pxlXCnt + 1;
          else
            scaleCntX <= scaleCntX + 1;
          end if;

          if ( pxlX = frameWidth -1 ) then
            scaleCntX <= 0;
            pxlXCnt <= 0;

            if ( scaleCntY = scale - 1 ) then
              scaleCntY <= 0;
              pxlYCnt <= pxlYCnt + 1;
            else
              scaleCntY <= scaleCntY + 1;
            end if;
          end if;

          butUp <= buttons( 0 );
          butDown <= buttons( 1 );
          butLeft <= buttons( 2 );
          butRight <= buttons( 3 );
          butA <= buttons( 4 );
          butB <= buttons( 5 );
          butL <= buttons( 6 );
          butR <= buttons( 7 );
          butStart <= buttons( 8 );
          butSelect <= buttons( 9 );

          -- Shift pxlCnt
          pxlXCnt_sub <= pxlXCnt - posX;
          pxlYCnt_sub <= pxlYCnt - posY;
          --pxlXCnt_sub <= pxlX;
          --pxlYCnt_sub <= pxlY;

          -- Output logic.
          if ( pxlXCnt_sub >= 0 and pxlXCnt_sub <= 21 and
               pxlYCnt_sub >= 0 and pxlYCnt_sub <= 11 ) then
            -- Overlay window.
            case overlayROM( pxlYCnt_sub )( pxlXCnt_sub ) is
              when 00 =>
                overlayInact <= '1';
                overlayAct <= butUp;

              when 01 =>
                overlayInact <= '1';
                overlayAct <= butDown;

              when 02 =>
                overlayInact <= '1';
                overlayAct <= butLeft;

              when 03 =>
                overlayInact <= '1';
                overlayAct <= butRight;

              when 04 =>
                overlayInact <= '1';
                overlayAct <= butA;

              when 05 =>
                overlayInact <= '1';
                overlayAct <= butB;

              when 06=>
                overlayInact <= '1';
                overlayAct <= butL;

              when 07 =>
                overlayInact <= '1';
                overlayAct <= butR;

              when 08 =>
                overlayInact <= '1';
                overlayAct <= butStart;

              when 09 =>
                overlayInact <= '1';
                overlayAct <= butSelect;

              when others =>
                overlayInact <= '0';
                overlayAct <= '0';
            end case;

          else
            overlayInact <= '0';
            overlayAct <= '0';
          end if;

        end if;

    end if;
  end process;

end behaviour;

signal butUp, butDown, butLeft, butRight, butA, butB, butL, butR,
  butStart, butSelect : std_logic;


-----------------------------------------------------------------------
-- Title: Single Line buffer
-- Author: zwenergy
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
library UNIMACRO;
use unimacro.Vcomponents.all;

entity singeLineBuffer is
  port(
    clkW : in std_logic;
    clkR : in std_logic;
    rst : in std_logic;
    wAddr : in std_logic_vector( 8 downto 0 );
    wEn : in std_logic;
    rAddr : in std_logic_vector( 8 downto 0 );

  );
end singeLineBuffer;

architecture rtl of singeLineBuffer is
signal readData : std_logic_vector( 31 downto 0 );
signal wea_int : std_logic_vector( 3 downto 0 );
signal addra_int : std_logic_vector( 8 downto 0 );
signal dina_int : std_logic_vector( 31 downto 0 );
signal addrb_int : std_logic_vector( 8 downto 0 );

begin

  wea_int <= ( others => wEn );
  addra_int <=  wAddr;
  dina_int <= "00000000" & redDataIn & greenDataIn & blueDataIn;
  addrb_int <= rAddr;

  bram_inst : BRAM_SDP_MACRO
    generic map(
      BRAM_SIZE => "18Kb",
      DEVICE => "7SERIES",
      WRITE_WIDTH => 32,
      READ_WIDTH => 32,
      DO_REG => 0,
      INIT_FILE => "NONE",
      SIM_COLLISION_CHECK => "WARNING_ONLY",
      SRVAL => X"000000000000000000",
      WRITE_MODE => "WRITE_FIRST"
     )
     port map(
      DO => readData,
      DI => dina_int,
      RDADDR => addrb_int,
      RDCLK => clkR,
      RDEN => '1',
      REGCE => '1',
      RST => rst,
      WE => wea_int,
      WRADDR => addra_int,
      WRCLK => clkW,
      WREN => wEn
     );

    redDataOut <= readData( 23 downto 16 );
    greenDataOut <= readData( 15 downto 8 );
    blueDataOut <= readData( 7 downto 0 );

end rtl;

    redDataIn : in std_logic_vector( 7 downto 0 );
    blueDataIn : in std_logic_vector( 7 downto 0 );
    greenDataIn : in std_logic_vector( 7 downto 0 );


-----------------------------------------------------------------------
-- Title: 4x Smoother
-- Author: zwenergy
-----------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity smooth4x is
  generic(
    colorDepth : integer := 8
  );
  port (
    -- Source pixels
   rTL : in std_logic_vector( colorDepth - 1 downto 0 );
   gTL : in std_logic_vector( colorDepth - 1 downto 0 );
   bTL : in std_logic_vector( colorDepth - 1 downto 0 );
   rTM : in std_logic_vector( colorDepth - 1 downto 0 );
   gTM : in std_logic_vector( colorDepth - 1 downto 0 );
   bTM : in std_logic_vector( colorDepth - 1 downto 0 );
   rTR : in std_logic_vector( colorDepth - 1 downto 0 );
   gTR : in std_logic_vector( colorDepth - 1 downto 0 );
   bTR : in std_logic_vector( colorDepth - 1 downto 0 );

   rCL : in std_logic_vector( colorDepth - 1 downto 0 );
   gCL : in std_logic_vector( colorDepth - 1 downto 0 );
   bCL : in std_logic_vector( colorDepth - 1 downto 0 );
   rCM : in std_logic_vector( colorDepth - 1 downto 0 );
   gCM : in std_logic_vector( colorDepth - 1 downto 0 );
   bCM : in std_logic_vector( colorDepth - 1 downto 0 );
   rCR : in std_logic_vector( colorDepth - 1 downto 0 );
   gCR : in std_logic_vector( colorDepth - 1 downto 0 );
   bCR : in std_logic_vector( colorDepth - 1 downto 0 );

   rBL : in std_logic_vector( colorDepth - 1 downto 0 );
   gBL : in std_logic_vector( colorDepth - 1 downto 0 );
   bBL : in std_logic_vector( colorDepth - 1 downto 0 );
   rBM : in std_logic_vector( colorDepth - 1 downto 0 );
   gBM : in std_logic_vector( colorDepth - 1 downto 0 );
   bBM : in std_logic_vector( colorDepth - 1 downto 0 );
   rBR : in std_logic_vector( colorDepth - 1 downto 0 );
   gBR : in std_logic_vector( colorDepth - 1 downto 0 );
   bBR : in std_logic_vector( colorDepth - 1 downto 0 );

   xSel : in std_logic_vector( 1 downto 0 );
   ySel : in std_logic_vector( 1 downto 0 );

   do4x : in std_logic;

   -- Out pixel
   rOut : out std_logic_vector( colorDepth - 1 downto 0 );
   gOut : out std_logic_vector( colorDepth - 1 downto 0 );
   bOut : out std_logic_vector( colorDepth - 1 downto 0 )
  );
end smooth4x;

architecture rtl of smooth4x is
type pixel is array( 0 to 2 ) of std_logic_vector( colorDepth - 1 downto 0 );
type pixel4 is array( 0 to 3 ) of pixel;
type pixel16 is array( 0 to 3 ) of pixel4;

function smooth2x(
  signal pxTM: in pixel;
  signal pxCL: in pixel;
  signal pxCM: in pixel;
  signal pxCR: in pixel;
  signal pxBM: in pixel ) return pixel4 is
    variable sm : pixel4;
    variable tmpTL, tmpTR, tmpBL, tmpBR : pixel;
begin
  if ( pxTM /= pxBM and pxCL /= pxCR ) then
      if ( pxCL = pxTM ) then
        tmpTL := pxCL;
      else
        tmpTL := pxCM;
      end if;

      if ( pxTM = pxCR ) then
        tmpTR := pxCR;
      else
        tmpTR := pxCM;
      end if;

      if ( pxCL = pxBM ) then
        tmpBL := pxCL;
      else
        tmpBL := pxCM;
      end if;

      if ( pxBM = pxCR ) then
        tmpBR := pxCR;
      else
        tmpBR := pxCM;
      end if;

    else
      tmpTL := pxCM;
      tmpTR := pxCM;
      tmpBL := pxCM;
      tmpBR := pxCM;
    end if;

    sm( 0 ) := tmpTL;
    sm( 1 ) := tmpTR;
    sm( 2 ) := tmpBL;
    sm( 3 ) := tmpBR;

    return sm;
end smooth2x;

function smooth2xMod(
  signal pxTM: in pixel;
  signal pxCL: in pixel;
  signal pxCM: in pixel;
  signal pxCR: in pixel;
  signal pxBM: in pixel;
  signal ignoreTopBottom: in std_logic;
  signal ignoreLeftRight: in std_logic ) return pixel4 is
    variable sm : pixel4;
    variable tmpTL, tmpTR, tmpBL, tmpBR : pixel;
begin
  if ( ( ignoreTopBottom = '1' and pxCL /= pxCR ) or
       ( ignoreLeftRight = '1' and pxTM /= pxBM ) or
       ( pxTM /= pxBM and pxCL /= pxCR and
         ignoreTopBottom = '0' and ignoreLeftRight = '0' ) ) then
      if ( pxCL = pxTM ) then
        tmpTL := pxCL;
      else
        tmpTL := pxCM;
      end if;

      if ( pxTM = pxCR ) then
        tmpTR := pxCR;
      else
        tmpTR := pxCM;
      end if;

      if ( pxCL = pxBM ) then
        tmpBL := pxCL;
      else
        tmpBL := pxCM;
      end if;

      if ( pxBM = pxCR ) then
        tmpBR := pxCR;
      else
        tmpBR := pxCM;
      end if;

    else
      tmpTL := pxCM;
      tmpTR := pxCM;
      tmpBL := pxCM;
      tmpBR := pxCM;
    end if;

    sm( 0 ) := tmpTL;
    sm( 1 ) := tmpTR;
    sm( 2 ) := tmpBL;
    sm( 3 ) := tmpBR;

    return sm;
end smooth2xMod;

signal pxTL, pxTM, pxTR, pxCL, pxCM, pxCR, pxBL, pxBM, pxBR : pixel;
signal smoothOut : pixel16;
signal tm2x, cl2x, cm2x, cr2x, bm2x : pixel4;
signal ignoreSig : std_logic := '1';
signal notIgnoreSig : std_logic := '0';
begin

  pxTL( 0 ) <= rTL;
  pxTL( 1 ) <= gTL;
  pxTL( 2 ) <= bTL;

  pxTM( 0 ) <= rTM;
  pxTM( 1 ) <= gTM;
  pxTM( 2 ) <= bTM;

  pxTR( 0 ) <= rTR;
  pxTR( 1 ) <= gTR;
  pxTR( 2 ) <= bTR;

  pxCL( 0 ) <= rCL;
  pxCL( 1 ) <= gCL;
  pxCL( 2 ) <= bCL;

  pxCM( 0 ) <= rCM;
  pxCM( 1 ) <= gCM;
  pxCM( 2 ) <= bCM;

  pxCR( 0 ) <= rCR;
  pxCR( 1 ) <= gCR;
  pxCR( 2 ) <= bCR;

  pxBL( 0 ) <= rBL;
  pxBL( 1 ) <= gBL;
  pxBL( 2 ) <= bBL;

  pxBM( 0 ) <= rBM;
  pxBM( 1 ) <= gBM;
  pxBM( 2 ) <= bBM;

  pxBR( 0 ) <= rBR;
  pxBR( 1 ) <= gBR;
  pxBR( 2 ) <= bBR;

  process( pxTL, pxTM, pxTR, pxCL, pxCM, pxCR, pxBL, pxBM, pxBR, ignoreSig, notIgnoreSig ) is
  begin

    -- Smooth 2x
    tm2x <= smooth2xMod( pxCM, pxTL, pxTM, pxTR, pxCM, ignoreSig, notIgnoreSig );
    cl2x <= smooth2xMod( pxTL, pxCM, pxCL, pxCM, pxBL, notIgnoreSig, ignoreSig );
    cm2x <= smooth2x( pxTM, pxCL, pxCM, pxCR, pxBM );
    cr2x <= smooth2xMod( pxTR, pxCM, pxCR, pxCM, pxBR, notIgnoreSig, ignoreSig );
    bm2x <= smooth2xMod( pxCM, pxBL, pxBM, pxBR, pxCM, ignoreSig, notIgnoreSig );
  end process;

  process( tm2x, cl2x, cm2x, cr2x, bm2x ) is
  begin
    -- And 4x.
    smoothOut( 0 ) <= smooth2x( tm2x( 2 ), cl2x( 1 ), cm2x( 0 ),
      cm2x( 1 ), cm2x( 2 ) );

    smoothOut( 1 ) <= smooth2x( tm2x( 3 ), cm2x( 0 ), cm2x( 1 ), cr2x( 0 ),
      cm2x( 3 ) );

    smoothOut( 2 ) <= smooth2x( cm2x( 0 ), cl2x( 3 ), cm2x( 2 ),
      cm2x( 3 ), bm2x( 0 ) );

    smoothOut( 3 ) <= smooth2x( cm2x( 1 ), cm2x( 2 ), cm2x( 3 ),
      cr2x( 2 ), bm2x( 1 ) );
  end process;

  -- Output.
  process( tm2x, cl2x, cm2x, cr2x, bm2x, xSel, ySel, smoothOut, do4x ) is
  begin
    if ( do4x = '0' ) then
      case xSel is
        when "00"|"01" =>
          case ySel is
            when "00"|"01" =>
              rOut <= cm2x( 0 )( 0 );
              gOut <= cm2x( 0 )( 1 );
              bOut <= cm2x( 0 )( 2 );
            when "10"|"11" =>
              rOut <= cm2x( 2 )( 0 );
              gOut <= cm2x( 2 )( 1 );
              bOut <= cm2x( 2 )( 2 );
            when others =>
              rOut <= cm2x( 0 )( 0 );
              gOut <= cm2x( 0 )( 1 );
              bOut <= cm2x( 0 )( 2 );
            end case;

        when "10"|"11" =>
          case ySel is
            when "00"|"01" =>
              rOut <= cm2x( 1 )( 0 );
              gOut <= cm2x( 1 )( 1 );
              bOut <= cm2x( 1 )( 2 );
            when "10"|"11" =>
              rOut <= cm2x( 3 )( 0 );
              gOut <= cm2x( 3 )( 1 );
              bOut <= cm2x( 3 )( 2 );
            when others =>
              rOut <= cm2x( 0 )( 0 );
              gOut <= cm2x( 0 )( 1 );
              bOut <= cm2x( 0 )( 2 );
            end case;

        when others =>
          rOut <= cm2x( 0 )( 0 );
          gOut <= cm2x( 0 )( 1 );
          bOut <= cm2x( 0 )( 2 );
    end case;

  else
    case xSel is
      when "00" =>
        case ySel is
          when "00" =>
            rOut <= smoothOut( 0 )( 0 )( 0 );
            gOut <= smoothOut( 0 )( 0 )( 1 );
            bOut <= smoothOut( 0 )( 0 )( 2 );

          when "01" =>
            rOut <= smoothOut( 0 )( 2 )( 0 );
            gOut <= smoothOut( 0 )( 2 )( 1 );
            bOut <= smoothOut( 0 )( 2 )( 2 );

          when "10" =>
            rOut <= smoothOut( 2 )( 0 )( 0 );
            gOut <= smoothOut( 2 )( 0 )( 1 );
            bOut <= smoothOut( 2 )( 0 )( 2 );

          when "11" =>
            rOut <= smoothOut( 2 )( 2 )( 0 );
            gOut <= smoothOut( 2 )( 2 )( 1 );
            bOut <= smoothOut( 2 )( 2 )( 2 );

          when others =>
            rOut <= smoothOut( 0 )( 0 )( 0 );
            gOut <= smoothOut( 0 )( 0 )( 0 );
            bOut <= smoothOut( 0 )( 0 )( 0 );
        end case;

      when "01" =>
        case ySel is
          when "00" =>
            rOut <= smoothOut( 0 )( 1 )( 0 );
            gOut <= smoothOut( 0 )( 1 )( 1 );
            bOut <= smoothOut( 0 )( 1 )( 2 );

          when "01" =>

          when "10" =>
            rOut <= smoothOut( 2 )( 1 )( 0 );
            gOut <= smoothOut( 2 )( 1 )( 1 );
            bOut <= smoothOut( 2 )( 1 )( 2 );

          when "11" =>
            rOut <= smoothOut( 2 )( 3 )( 0 );
            gOut <= smoothOut( 2 )( 3 )( 1 );
            bOut <= smoothOut( 2 )( 3 )( 2 );

          when others =>
            rOut <= smoothOut( 0 )( 0 )( 0 );
            gOut <= smoothOut( 0 )( 0 )( 0 );
            bOut <= smoothOut( 0 )( 0 )( 0 );
        end case;

      when "10" =>
        case ySel is
          when "00" =>
            rOut <= smoothOut( 1 )( 0 )( 0 );
            gOut <= smoothOut( 1 )( 0 )( 1 );
            bOut <= smoothOut( 1 )( 0 )( 2 );

          when "01" =>
            rOut <= smoothOut( 1 )( 2 )( 0 );
            gOut <= smoothOut( 1 )( 2 )( 1 );
            bOut <= smoothOut( 1 )( 2 )( 2 );

          when "10" =>
            rOut <= smoothOut( 3 )( 0 )( 0 );
            gOut <= smoothOut( 3 )( 0 )( 1 );
            bOut <= smoothOut( 3 )( 0 )( 2 );

          when "11" =>
            rOut <= smoothOut( 3 )( 2 )( 0 );
            gOut <= smoothOut( 3 )( 2 )( 1 );
            bOut <= smoothOut( 3 )( 2 )( 2 );

          when others =>
            rOut <= smoothOut( 0 )( 0 )( 0 );
            gOut <= smoothOut( 0 )( 0 )( 0 );
            bOut <= smoothOut( 0 )( 0 )( 0 );
        end case;

      when "11" =>
        case ySel is
          when "00" =>
            rOut <= smoothOut( 1 )( 1 )( 0 );
            gOut <= smoothOut( 1 )( 1 )( 1 );
            bOut <= smoothOut( 1 )( 1 )( 2 );

          when "01" =>
            rOut <= smoothOut( 1 )( 3 )( 0 );
            gOut <= smoothOut( 1 )( 3 )( 1 );
            bOut <= smoothOut( 1 )( 3 )( 2 );

          when "10" =>
            rOut <= smoothOut( 3 )( 1 )( 0 );
            gOut <= smoothOut( 3 )( 1 )( 1 );
            bOut <= smoothOut( 3 )( 1 )( 2 );

          when "11" =>
            rOut <= smoothOut( 3 )( 3 )( 0 );
            gOut <= smoothOut( 3 )( 3 )( 1 );
            bOut <= smoothOut( 3 )( 3 )( 2 );

          when others =>
            rOut <= smoothOut( 0 )( 0 )( 0 );
            gOut <= smoothOut( 0 )( 0 )( 0 );
            bOut <= smoothOut( 0 )( 0 )( 0 );
        end case;

      when others =>
        rOut <= smoothOut( 0 )( 0 )( 0 );
        gOut <= smoothOut( 0 )( 0 )( 0 );
        bOut <= smoothOut( 0 )( 0 )( 0 );
      end case;
    end if;
  end process;

end rtl;

            rOut <= smoothOut( 0 )( 3 )( 0 );
            gOut <= smoothOut( 0 )( 3 )( 1 );


--------------------------------------------------------------------------------
--         .XXXXXXXXXXXXXXXX.  .XXXXXXXXXXXXXXXX.  .XX.                       --
--         XXXXXXXXXXXXXXXXX'  XXXXXXXXXXXXXXXXXX  XXXX                       --
--         XXXX                XXXX          XXXX  XXXX                       --
--         XXXXXXXXXXXXXXXXX.  XXXXXXXXXXXXXXXXXX  XXXX                       --
--         'XXXXXXXXXXXXXXXXX  XXXXXXXXXXXXXXXXX'  XXXX                       --
--                       XXXX  XXXX                XXXX                       --
--         .XXXXXXXXXXXXXXXXX  XXXX                XXXXXXXXXXXXXXXXX.         --
--         'XXXXXXXXXXXXXXXX'  'XX'                'XXXXXXXXXXXXXXXX'         --
--------------------------------------------------------------------------------
--             Copyright 2023 Vittorio Pascucci (SideProjectsLab)             --
--                                                                            --
-- Licensed under the GNU General Public License, Version 3 (the "License");  --
-- you may not use this file except in compliance with the License.           --
-- You may obtain a copy of the License at                                    --
--                                                                            --
--     https://www.gnu.org/licenses/gpl-3.0.en.html#license-text              --
--                                                                            --
-- Unless required by applicable law or agreed to in writing, software        --
-- distributed under the License is distributed on an "AS IS" BASIS,          --
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   --
-- See the License for the specific language governing permissions and        --
-- limitations under the License.                                             --
--------------------------------------------------------------------------------

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

library work;
use     work.qol_pkg.all;
use     work.vic_pkg.all;

entity bad_line_detect is
port
(
	clk    : in  std_wire;
	rst    : in  std_wire;

	reg    : in  t_regs;
	aec    : in  std_wire;
	strb   : in  t_strb;
	cycl   : in  t_ppos;
	ypos   : in  t_ppos;
	bdln   : out std_wire;
	ccax   : out std_wire
);
end entity;

architecture rtl of bad_line_detect is

	signal rst_1r  : std_wire := '1';
	signal den     : std_wire;
	signal enable  : std_wire;
	signal yscroll : unsigned(2 downto 0);

begin

	yscroll <= unsigned(reg(17)(2 downto 0));
	den     <= reg(17)(4);

			v_enable := enable;

			if strb = 1 then
				if ((den = '1') and (ypos = 48)) then
					v_enable := '1';
				end if;

				if ypos >= 48 and ypos <= 247 then
					if (v_enable = '1') and (yscroll = ypos(2 downto 0)) then
						bdln <= '1';
					else
						bdln <= '0';
					end if;
				else
					bdln     <= '0';
					v_enable := '0';
				end if;
			end if;

			if (strb = 9) then
				if (cycl = c_cycl_ref - 1) then
					ccax <= '0';
				else
					ccax <= '0';
					if (ypos >= 48) and (ypos <= 247) and
					   (cycl >= c_cycl_ref) and (cycl < c_cycl_ref + 40)
					then
						ccax <= not aec;
					end if;
				end if;
			end if;

			enable <= v_enable;

			rst_1r <= rst;
			if rst_1r then
				bdln   <= '0';
				ccax   <= '0';
				enable <= '0';
			end if;

		end if;
	end process;

end architecture;

	p_detect : process(clk) is
		variable v_enable : std_wire;


--------------------------------------------------------------------------------
--         .XXXXXXXXXXXXXXXX.  .XXXXXXXXXXXXXXXX.  .XX.                       --
--         XXXXXXXXXXXXXXXXX'  XXXXXXXXXXXXXXXXXX  XXXX                       --
--         XXXX                XXXX          XXXX  XXXX                       --
--         XXXXXXXXXXXXXXXXX.  XXXXXXXXXXXXXXXXXX  XXXX                       --
--         'XXXXXXXXXXXXXXXXX  XXXXXXXXXXXXXXXXX'  XXXX                       --
--                       XXXX  XXXX                XXXX                       --
--         .XXXXXXXXXXXXXXXXX  XXXX                XXXXXXXXXXXXXXXXX.         --
--         'XXXXXXXXXXXXXXXX'  'XX'                'XXXXXXXXXXXXXXXX'         --
--------------------------------------------------------------------------------
--             Copyright 2023 Vittorio Pascucci (SideProjectsLab)             --
--                                                                            --
-- Licensed under the GNU General Public License, Version 3 (the "License");  --
-- you may not use this file except in compliance with the License.           --
-- You may obtain a copy of the License at                                    --
--                                                                            --
--     https://www.gnu.org/licenses/gpl-3.0.en.html#license-text              --
--                                                                            --
-- Unless required by applicable law or agreed to in writing, software        --
-- distributed under the License is distributed on an "AS IS" BASIS,          --
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   --
-- See the License for the specific language governing permissions and        --
-- limitations under the License.                                             --
--------------------------------------------------------------------------------

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

library work;
use     work.qol_pkg.all;
use     work.vic_pkg.all;

entity border is
port
(
	clk    : in  std_wire;
	rst    : in  std_wire;

	strb   : in  t_strb;
	specs  : in  t_vic_specs;
	cycl   : in  t_ppos;
	xpos   : in  t_ppos;

	enable : in  std_word(1 downto 0);

	mark_bord : out std_wire;
	mark_colr : out t_colr
);
end entity;

architecture rtl of border is

	signal rst_1r   : std_wire := '1';

	signal ff_main  : std_wire;
	signal ff_vert  : std_wire;

	signal edge_ll  : t_ppos;
	signal edge_rr  : t_ppos;
	signal edge_hi  : t_ppos;
	signal edge_lo  : t_ppos;

	signal reg_rsel : std_wire;
	signal reg_csel : std_wire;

	signal reg_rsel_1r : std_wire;
	signal reg_csel_1r : std_wire;

	alias  reg_ec   : std_word is reg(32)(3 downto 0);
	alias  reg_den  : std_wire is reg(17)(4);

begin

	----------------------------------------------------------------------------
	--                             DIAGNOSTICS                                --
	----------------------------------------------------------------------------

	process(all) is
	begin
		reg_rsel <= reg(17)(3);
		reg_csel <= reg(22)(3);

		if enable = "01" then
			-- force wide border
			reg_rsel <= '1';
			reg_csel <= '1';
		elsif enable = "10" then
			-- force narrow border
			reg_rsel <= '0';
			reg_csel <= '0';
		end if;
	end process;

	----------------------------------------------------------------------------

	edge_ll <= specs.xfvc + 7 when (reg_csel = '0') else specs.xfvc;
	edge_rr <= specs.xlvc - 8 when (reg_csel = '0') else specs.xlvc + 1;
	edge_hi <= specs.yfvc + 4 when (reg_rsel = '0') else specs.yfvc;
	edge_lo <= specs.ylvc - 3 when (reg_rsel = '0') else specs.ylvc + 1;

	P_border : process(clk) is
		variable v_ff_main : std_wire;
		variable v_ff_vert : std_wire;
	begin
		if rising_edge(clk) then

			v_ff_main := ff_main;
			v_ff_vert := ff_vert;

			if strb(0) = '1' then

				-- vertical ff control
				if (ypos = edge_lo) then
					v_ff_vert := '1';
				end if;

				if (xpos = edge_ll) then
					o_vbrd <= v_ff_vert;
				end if;

				if (ypos = edge_hi) and (reg_den = '1') then
					v_ff_vert := '0';
					o_vbrd    <= v_ff_vert;
				end if;

				-- main ff control
				if (xpos = edge_rr) then
					v_ff_main := '1';
				end if;
				if (xpos = edge_ll) and (v_ff_vert = '0') then
					v_ff_main := '0';
				end if;

				-- this is copied from kawarii
				if (cycl = 0)then
					o_vbrd <= v_ff_vert;
				end if;

				o_bord <= v_ff_main;
				o_colr <= t_colr(reg_ec);

				ff_vert <= v_ff_vert;
				ff_main <= v_ff_main;

				----------------------------------------------------------------
				--                       DIAGNOSTICS                          --
				----------------------------------------------------------------

				-- turning off border
				if enable = "00" then
					o_bord <= '0';
				end if;

				-- marking csel and rsel changes (opening border)
				reg_csel_1r <= reg_csel;
				reg_rsel_1r <= reg_rsel;

				mark_bord <= '0';
				if reg_csel_1r /= reg_csel then
					mark_bord <= '1';
					mark_colr <= x"d"; -- LIGHT GREEN
				end if;

				if reg_rsel_1r /= reg_rsel then
					mark_bord <= '1';
					mark_colr <= x"4"; -- PURPLE
				end if;

				----------------------------------------------------------------

			end if;

			rst_1r <= rst;
			if rst_1r then
				ff_main <= '0';
				ff_vert <= '0';
			end if;

		end if;
	end process;

end architecture;

	ypos   : in  t_ppos;
	reg    : in  t_regs;

	o_vbrd : out std_wire;


--------------------------------------------------------------------------------
--         .XXXXXXXXXXXXXXXX.  .XXXXXXXXXXXXXXXX.  .XX.                       --
--         XXXXXXXXXXXXXXXXX'  XXXXXXXXXXXXXXXXXX  XXXX                       --
--         XXXX                XXXX          XXXX  XXXX                       --
--         XXXXXXXXXXXXXXXXX.  XXXXXXXXXXXXXXXXXX  XXXX                       --
--         'XXXXXXXXXXXXXXXXX  XXXXXXXXXXXXXXXXX'  XXXX                       --
--                       XXXX  XXXX                XXXX                       --
--         .XXXXXXXXXXXXXXXXX  XXXX                XXXXXXXXXXXXXXXXX.         --
--         'XXXXXXXXXXXXXXXX'  'XX'                'XXXXXXXXXXXXXXXX'         --
--------------------------------------------------------------------------------
--             Copyright 2023 Vittorio Pascucci (SideProjectsLab)             --
--                                                                            --
-- Licensed under the GNU General Public License, Version 3 (the "License");  --
-- you may not use this file except in compliance with the License.           --
-- You may obtain a copy of the License at                                    --
--                                                                            --
--     https://www.gnu.org/licenses/gpl-3.0.en.html#license-text              --
--                                                                            --
-- Unless required by applicable law or agreed to in writing, software        --
-- distributed under the License is distributed on an "AS IS" BASIS,          --
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   --
-- See the License for the specific language governing permissions and        --
-- limitations under the License.                                             --
--------------------------------------------------------------------------------

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

library work;
use     work.qol_pkg.all;
use     work.gp3r_pkg.all;
use     work.vic_pkg.all;

entity bus_latch is
generic
(
	g_enable : boolean := True
);
port

	i_a      : in  t_addr;
	i_rw     : in  std_wire;
	i_cs     : in  std_wire;
	i_aec    : in  std_wire;

	o_ph0    : out std_wire;
	o_db     : out std_word(11 downto 0);
	o_a      : out t_addr;
	o_rw     : out std_wire;
	o_cs     : out std_wire;
	o_aec    : out std_wire
);
end entity;

architecture rtl of bus_latch is

	signal vector_in  : std_word(21 downto 0);
	signal vector_out : std_word(21 downto 0);

begin

	process(all) is
	begin
		vector_in <= i_ph0 & i_db & std_word(i_a) & i_rw & i_cs & i_aec;
		o_ph0     <= vector_out(21);
		o_db      <= vector_out(20 downto 9);
		o_a       <= unsigned(vector_out(8 downto 3));
		o_rw      <= vector_out(2);
		o_cs      <= vector_out(1);
		o_aec     <= vector_out(0);
	end process;

	i_multi_flop : entity work.multi_flop
	generic map
	(
		g_num_stages => switch(g_enable, 2, 0),
		g_input_reg  => false
	)
	port map
	(
		i_clk  => clk,
		i_rst  => rst,
		i_data => vector_in,

		o_clk  => clk,
		o_rst  => rst,
		o_data => vector_out
	);

end architecture;

(
	clk      : in  std_wire; -- must be twice the video clock (16 times ph0)
	rst      : in  std_wire;


--------------------------------------------------------------------------------
--         .XXXXXXXXXXXXXXXX.  .XXXXXXXXXXXXXXXX.  .XX.                       --
--         XXXXXXXXXXXXXXXXX'  XXXXXXXXXXXXXXXXXX  XXXX                       --
--         XXXX                XXXX          XXXX  XXXX                       --
--         XXXXXXXXXXXXXXXXX.  XXXXXXXXXXXXXXXXXX  XXXX                       --
--         'XXXXXXXXXXXXXXXXX  XXXXXXXXXXXXXXXXX'  XXXX                       --
--                       XXXX  XXXX                XXXX                       --
--         .XXXXXXXXXXXXXXXXX  XXXX                XXXXXXXXXXXXXXXXX.         --
--         'XXXXXXXXXXXXXXXX'  'XX'                'XXXXXXXXXXXXXXXX'         --
--------------------------------------------------------------------------------
--             Copyright 2023 Vittorio Pascucci (SideProjectsLab)             --
--                                                                            --
-- Licensed under the GNU General Public License, Version 3 (the "License");  --
-- you may not use this file except in compliance with the License.           --
-- You may obtain a copy of the License at                                    --
--                                                                            --
--     https://www.gnu.org/licenses/gpl-3.0.en.html#license-text              --
--                                                                            --
-- Unless required by applicable law or agreed to in writing, software        --
-- distributed under the License is distributed on an "AS IS" BASIS,          --
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   --
-- See the License for the specific language governing permissions and        --
-- limitations under the License.                                             --
--------------------------------------------------------------------------------

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

library work;
use     work.qol_pkg.all;
use     work.gp3r_pkg.all;
use     work.vic_pkg.all;

entity bus_logger is
generic
(
	g_enable : boolean
);
port
(
	clk      : in  std_wire; -- must be twice the video clock (16 times ph0)
	rst      : in  std_wire;

	-- gp3r master
	req      : in  t_gp3r_req;
	rsp      : out t_gp3r_rsp;

	xpos     : in  t_ppos;
	ypos     : in  t_ppos;

	-- VIC signals
	strb     : in  t_strb;
	ph0      : in  std_wire;
	db       : in  std_word(11 downto 0);
	a        : in  t_addr;
	rw       : in  std_wire;
	cs       : in  std_wire;
	aec      : in  std_wire
);
end entity;

architecture rtl of bus_logger is

	constant c_bit_width   : positive := 32;
	constant c_fifo_depth  : positive := 2048;

	signal   rst_1r        : std_wire := '1';

	signal   req_fifo      : req'subtype;
	signal   rsp_fifo      : rsp'subtype;

	signal   count         : natural range 0 to c_fifo_depth;
	signal   dumping       : std_wire;
	signal   pixl_num      : unsigned(bits_for_value(c_fifo_depth) - 1 downto 0);
	signal   line_num      : unsigned(31 downto 0);
	signal   line_num_push : std_wire;

	signal   data_out      : std_word(c_bit_width - 1 downto 0);
	signal   read_out      : std_wire;
	signal   push_out      : std_wire;

begin

	r_enable : if g_enable generate
		i_memmap : entity work.memmap_bus_logger
		generic map
		(
			g_decouple => true
		)
		port map
		(
			clk           => clk,
			rst           => rst,
			req           => req,
			rsp           => rsp,
			line_num      => line_num,
			pixl_num      => lresize(pixl_num, 32),
			line_num_push => line_num_push,
			req_line_read => req_fifo,
			rsp_line_read => rsp_fifo
		);

		p_input : process(clk) is
		begin
			if rising_edge(clk) then

				push_in <= '0';

				if ((ypos = line_num) and (xpos = 0) and (count = 0)) or
				   ((dumping = '1') and (xpos = count)              )
				then
					dumping <= '1';
					push_in <= '1';
					data_in <= "000000"       &
					           std_word(strb) & -- 25 downto 22
					           ph0            & -- 21
					           db             & -- 20 downto 9
					           std_word(a)    & -- 8 downto 3
					           rw             & -- 2
					           cs             & -- 1
					           aec;             -- 0

					if strb(0) = '1' then
						count <= count + 1;
					end if;
				end if;

				if line_num_push then
					count   <= 0;
					dumping <= '0';
				end if;

				rst_1r <= rst;
				if rst_1r then
					count   <= c_fifo_depth;
					dumping <= '0';
					push_in <= '0';
				end if;

			end if;
		end process;

		i_fifo : entity work.fifo
		generic map
		(
			g_depth => c_fifo_depth,
			g_width => c_bit_width
		)
		port map
		(
			i_clk   => clk,
			i_rst   => rst,
			i_push  => push_in,
			i_read  => open,
			i_data  => data_in,

			o_clk   => clk,
			o_rst   => rst,
			o_flush => '0',
			o_push  => push_out,
			o_read  => read_out,
			o_data  => data_out,
			o_nfull => pixl_num
		);

		i_stream_to_gp3r : entity work.gp3r_istream
		port map
		(
			clk    => clk,
			rst    => rst,
			req    => req_fifo,
			rsp    => rsp_fifo,
			data   => data_out,
			read   => read_out,
			push   => push_out
		);

	else generate

		i_nack : entity work.gp3r_dummy
		generic map
		(
			g_nack  => c_gp3r_nack_addr
		)
		port map
		(
			clk    => clk,
			rst    => rst,
			req    => req,
			rsp    => rsp
		);

	end generate;

end architecture;

	signal   data_in       : std_word(c_bit_width - 1 downto 0);
	signal   push_in       : std_wire;