---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2007
--
-- Filename: FPGAConfig.vhd
-- Language: VHDL '93
-- Project:  NDTS2100 System FPGA
--
-- Design Description:
-- Module to configure a Spartan 3 FPGA
---------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

entity FPGAConfig is
  port (-- Local bus
        nReset      : in  std_ulogic;
        LClk        : in  std_ulogic;
        -- Register interface signals
        ConfigData  : in  std_logic_vector(31 downto 0);
        ConfigWr    : in  std_ulogic;
        ConfigStart : in  std_ulogic;
        ConfigDone  : out std_ulogic;
        ConfigBusy  : out std_ulogic;
        -- FPGA signals
        CClk        : out std_ulogic;
        Done        : in  std_ulogic;
        nProg       : out std_ulogic := '0';
        DIn         : out std_ulogic;
        nInit       : in  std_ulogic);
end entity FPGAConfig;


architecture Rtl of FPGAConfig is

  signal ProgCount  : unsigned(5 downto 0) := (others => '0');
  signal ProgBusy   : std_ulogic := '0';
  signal DataShift  : std_logic_vector(31 downto 0);
  signal ShiftCount : unsigned(6 downto 0) := (others => '0');
  signal DataBusy   : std_ulogic := '0';
begin

  -- Prog Pulse must be 0.3uS - This gives 15ns * 32 = 480ns for a 66MHz clock
  ProgGen: process(LClk)
  begin
    if LClk'event and LClk = '1' then
      if ConfigStart = '1' then
        ProgCount <= ProgCount + 1;
        nProg <= '0';
        ProgBusy <= '1';
      elsif ProgCount /= 0 then
        ProgCount <= ProgCount + 1;
      else
        nProg <= '1';
        ProgBusy <= not nInit; -- Busy until Init goes high
      end if;
    end if;
  end process ProgGen;


  -- Data shift register
  -- CClk must be less than 20MHz - this gives 66MHz / 4 = 16.5MHz
  Shift: process(LClk)
  begin
    if LClk'event and LClk = '1' then
      if ConfigWr = '1' then
        DataShift <= (0 => ConfigData(7), 1 => ConfigData(6), 2 => ConfigData(5), 3 => ConfigData(4),
                      4 => ConfigData(3), 5 => ConfigData(2), 6 => ConfigData(1), 7 => ConfigData(0),

                      8 => ConfigData(15), 9 => ConfigData(14), 10 => ConfigData(13), 11 => ConfigData(12),
                      12 => ConfigData(11), 13 => ConfigData(10), 14 => ConfigData(9), 15 => ConfigData(8),

                      16 => ConfigData(23), 17 => ConfigData(22), 18 => ConfigData(21), 19 => ConfigData(20),
                      20 => ConfigData(19), 21 => ConfigData(18), 22 => ConfigData(17), 23 => ConfigData(16),

                      24 => ConfigData(31), 25 => ConfigData(30), 26 => ConfigData(29), 27 => ConfigData(28),
                      28 => ConfigData(27), 29 => ConfigData(26), 30 => ConfigData(25), 31 => ConfigData(24));

        ShiftCount <= ShiftCount + 1;
        DataBusy <= '1';
      elsif ShiftCount /= 0 then
        ShiftCount <= ShiftCount + 1;
        if ShiftCount(1 downto 0) = 0 then
          DataShift <= '0' & DataShift(31 downto 1);
        end if;
      else
        DataBusy <= '0';
      end if;
    end if;
  end process Shift;

  DIn <= DataShift(0);
  CClk <= ShiftCount(1);

  ConfigBusy <= ProgBusy or DataBusy;

  -- Sample Done signal from FPGA
  DoneFF: process(LClk)
  begin
    if LClk'event and LClk = '1' then
      ConfigDone <= Done;
    end if;
  end process DoneFF;

end Rtl;
