---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2004
--
-- Filename: LbusCont.vhd
-- Language: VHDL '93
-- Project:  Digitiser Card System FPGA
--
-- Design Description:
-- Local Bus Control for Digitiser Card System FPGA
--
-- SRAM controller for the PLX IC local bus - provides a prototype
-- for all other local bus peripherals.
--
---------------------------------------------------------------------------


library IEEE;
use IEEE.Std_Logic_1164.all;
use IEEE.Std_Logic_Arith.all;


entity LbusCont is
  port(pnReset     : in  std_ulogic;
       pLCLKA      : in  std_ulogic;                 -- local bus clock
       pLAin       : in  std_logic_vector(31 downto 2);
       pLDin       : in  std_logic_vector(31 downto 0);    -- local data bus input
       pLDout      : out std_logic_vector(31 downto 0);  -- local data bus output
       pLDoutEn    : out std_ulogic;            -- output buffer enable
       pLW_R       : in  std_ulogic;                  -- write NOT read
       pnADS       : in  std_ulogic;                  -- ads#
       pnBLAST     : in  std_ulogic;                -- blast#
       pnREADY     : out std_ulogic;               -- ready#
       pnBTERM     : out std_ulogic;               -- bterm#
       pLHOLDA     : out std_ulogic;               -- lholda#
       pLHOLD      : in  std_ulogic;               -- lhold#
       pBREQi      : out std_ulogic;
       pnSysRamWE  : out std_ulogic;
       pnSysRamCS  : out std_ulogic;
       pnSysRamOE  : out std_ulogic;
       -- Generic IO signals
       pSysIo0In   : in  std_logic_vector(31 downto 0);
       pSysIo0Out  : out std_logic_vector(31 downto 0);
       pSysIo0Dir  : out std_logic_vector(31 downto 0);
       pSysIo1In   : in  std_logic_vector(20 downto 0);
       pSysIo1Out  : out std_logic_vector(20 downto 0);
       pSysIo1Dir  : out std_logic_vector(20 downto 0);
       -- Block RAM Signals
       pBlkRamWriteEn : out std_ulogic;
       pBlkRamAddr    : out std_logic_vector(5 downto 0);
       pBlkRamDataIn  : out std_logic_vector(31 downto 0);
       pBlkRamDataOut : in  std_logic_vector(31 downto 0);
       -- Control signals for EEPROM access block
       pWriteEeprom   : out std_ulogic;
       pReadEeprom    : out std_ulogic;
       -- Signals for status reg
       pEepromBusy    : in  std_ulogic;
       --
       pnDspFpgaProg  : in  std_logic_vector(3 downto 0);   -- DSP FPGA / sample system chip selects
       pnPerFpgaProg  : in  std_logic_vector(3 downto 0);   -- Peripheral chip selects
       --
       pCCS           : out std_ulogic;      -- PCI 9056 configuration chip select
       pWhatFpga      : out std_logic_vector(3 downto 0);
       pnDspFpgaCs    : out std_logic_vector(3 downto 0);   -- DSP FPGA / sample system chip selects
       pnPerFpgaCs    : out std_logic_vector(3 downto 0);   -- Peripheral chip selects
       pFpgaLoad      : out std_ulogic;      -- flag start of fpga program sequence
       pFpgaProged    : in  std_ulogic;     -- The FPGAs have been programmed
       pFpgaDone      : in  std_logic;    -- feedback strobe from fpga load module
       pTest          : out std_ulogic);
end LbusCont;

architecture Behavioral of LbusCont is

  constant cSysFpgaVer: std_logic_vector(15 downto 0) := X"0104";

  type tCtrlState is (sIdle, sDelay1, sSampleDelay1, sSampleDelay2, sDelay2, sDoAccess);
  signal CtrlState:  tCtrlState;
  signal IncAddress: std_ulogic;
  signal nSysRamCS:   std_ulogic;
  signal nSysRamOE:   std_ulogic;
  signal nSysRamWE:   std_ulogic;

  signal nReady:      std_ulogic;
  signal nExtndReady: std_ulogic;
  signal nDspFpgaCs:  std_ulogic;
  signal nPerFpgaCs:  std_ulogic;

  signal check_register:   std_logic_vector(31 downto 0);
  signal sys_io_bank0:     std_logic_vector(31 downto 0);
  signal sys_io_bank0_ddr: std_logic_vector(31 downto 0);
  signal sys_io_bank1:     std_logic_vector(20 downto 0);
  signal sys_io_bank1_ddr: std_logic_vector(20 downto 0);
  signal sys_command_reg:  std_logic_vector(31 downto 0);
  signal sys_status_reg:   std_logic_vector(31 downto 0);
  signal sys_debug_reg:    std_logic_vector(0 downto 0);
  signal sys_test_reg:     std_logic_vector(31 downto 0);
  signal sys_oor_count:    unsigned(31 downto 0);

  -- Debug signals
  constant cBurstCountMax: integer := 65535;
  signal BurstInc:    std_ulogic;
  signal BurstCount:  integer range 0 to cBurstCountMax;
  signal BurstZero:   std_ulogic;
  signal BurstAddr:   std_logic_vector(5 downto 0);
  signal BurstWrite:  std_ulogic;
  signal BurstReset:  std_ulogic;
  signal OorReset:    std_ulogic;

  signal sys_enable_any : std_ulogic;
  signal sys_enable     : std_logic_vector(8 downto 0); -- collection of enable flags organised thus...
                                    --  Bit   Function
                                    --   0     Check register enable
                                    --   1     System IO bank 0 enable
                                    --   2     System IO bank 0 DDR enable
                                    --   3     System IO bank 1 enable
                                    --   4     System IO bank 1 DDR enable
                                    --   5     System command reg / status reg enable
                                    --   6     not used
                                    --   7     test register
                                    --   8     out of range access count
  signal sys_reg_enable:    std_ulogic;
  signal local_bus_control: std_ulogic;   -- 0 = PCI has bus control, 1 = local bus control
  signal SysRamAccess:      std_ulogic;
  signal BlockRamAccess:    std_ulogic;
  signal BlockRamAccessQ:   std_ulogic;
  signal SampleRamAccess:   std_ulogic;

  signal IntAddr:           std_logic_vector(31 downto 0);
  signal IntLW_R:           std_ulogic;
  signal Intlholda:         std_ulogic;

  signal next_ram_nWR:      std_ulogic;
  signal next_ram_nCS:      std_ulogic;
  signal nADS_delayed:      std_ulogic;
  signal SysRamWr_a:        std_ulogic;
  signal SysRamWr_b:        std_ulogic;
  signal fpga_load_int:     std_ulogic;
  signal BREQi:             std_ulogic;

  signal WriteEeprom:       std_ulogic;
  signal ReadEeprom:        std_ulogic;

  signal BlkRamData:        std_logic_vector(31 downto 0);
  signal RegReadData:       std_logic_vector(31 downto 0);

  signal FirstAccess:       std_ulogic;

begin

  pnREADY <= nReady;

  --
  -- Load local address into counter when ADS# is asserted
  --
  GenIntAddr: process(pnReset, pLCLKA)
  begin
    if pnReset = '0' then
      IntAddr(31 downto 2) <= (others => '0');
    elsif rising_edge(pLCLKA) then
      if pnADS = '0' then
        IntAddr(31 downto 2) <= pLAin(31 downto 2);
      elsif IncAddress = '1' then
        IntAddr(31 downto 2) <= unsigned(IntAddr(31 downto 2)) + 1;
      end if;
    end if;
  end process GenIntAddr;

  IntAddr(1 downto 0) <= "00";


  GenSysRamAccess: process(pnReset, pLCLKA)
    variable vLast_nADS: std_ulogic;
  begin
    if pnReset = '0' then
      SysRamAccess    <= '0';
      SampleRamAccess <= '0';
      vLast_nADS      := '1';
    elsif rising_edge(pLCLKA) then
      if vLast_nADS = '0' then
        if IntAddr(31 downto 20) = X"004" then
          SysRamAccess <= '1';
        else
          SysRamAccess <= '0';
        end if;

        if IntAddr(31 downto 20) = X"000" or
           IntAddr(31 downto 20) = X"001" or
           IntAddr(31 downto 20) = X"002" or
           IntAddr(31 downto 20) = X"003" then
          SampleRamAccess <= '1';
        else
          SampleRamAccess <= '0';
        end if;
      end if;

      vLast_nADS := pnADS;
    end if;
  end process GenSysRamAccess;


  GenIntLW_R: process(pLCLKA)
  begin
    if rising_edge(pLCLKA) then
      IntLW_R <= pLW_R;
    end if;
  end process GenIntLW_R;


  -- Generate delayed version of pnADS input
  process(pLCLKA)
  begin
    if rising_edge(pLCLKA) then
      nADS_delayed <= pnADS;
    end if;
  end process;


  pBlkRamWriteEn <= (IntLW_R and BlockRamAccess) when sys_debug_reg(0) = '0' else BurstWrite;
  pBlkRamAddr    <= IntAddr(7 downto 2) when sys_debug_reg(0) = '0' else BurstAddr;
  pBlkRamDataIn  <= pLDin when sys_debug_reg(0) = '0' else X"0000" & conv_std_logic_vector(BurstCount, 16);


  -- Check for accesses to System RAM
  GenSysRamSignals: process(sys_command_reg, IntAddr, IntLW_R, next_ram_nCS, Intlholda)
  begin
    if sys_command_reg(0) = '1' and Intlholda = '0' then
      -- Set the System SRAM to read mode for FPGA loading
--      SysRamCsnActive <= '0';
--      SysRamOenActive <= '0';

    elsif next_ram_nCS = '0' then
      if IntAddr(31 downto 20) = X"004" then
--        SysRamCsnActive <= '0';
        if IntLW_R = '1' then
          -- SRAM Write
--          SysRamOenActive <= '1';
          -- Toggle nWR when active
        else
          -- SRAM Read
--          SysRamOenActive <= '0';
        end if;
      else
        -- Not SRAM access
--        SysRamCsnActive <= '1';
--        SysRamOenActive <= '1';
      end if;
    else
      -- No access
--      SysRamCsnActive <= '1';
--      SysRamOenActive <= '1';
    end if;
  end process GenSysRamSignals;


  GenSysRamAccess2: process(sys_command_reg, IntAddr, IntLW_R, nReady, next_ram_nWR)
  begin
    if sys_command_reg(0) = '1' then
      -- Set the System SRAM to read mode for FPGA loading
--      SysRamWrnActive <= '1';

    else
      if IntAddr(31 downto 20) = X"004" then
        if IntLW_R = '1' then
          -- SRAM Write
          -- Toggle nWR when active
          if next_ram_nWR = '0' then
--            SysRamWrnActive <= '0';
          else
--            SysRamWrnActive <= '1';
          end if;
        else
          -- SRAM Read
--          SysRamWrnActive <= '1';
        end if;
      else
        -- Not SRAM access
--        SysRamWrnActive <= '1';
      end if;
--    else
--      -- No access
--      SysRamWrnActive <= '1';
    end if;
  end process GenSysRamAccess2;




  --
  --  manage writes from local bus
  --
  process(pnReset, pLCLKA)
  begin
    if pnReset = '0' then
      sys_command_reg  <= (others => '0');
      check_register   <= (others => '0');
      sys_io_bank0     <= (others => '0');
      sys_io_bank0_ddr <= (others => '0');
      sys_io_bank1     <= (others => '0');
      sys_io_bank1_ddr <= (others => '0');
      sys_debug_reg    <= (others => '0');
      sys_test_reg     <= (others => '0');
      WriteEeprom      <= '0';
      ReadEeprom       <= '0';
      BurstReset       <= '0';
      OorReset         <= '0';

    elsif rising_edge(pLCLKA) then
      WriteEeprom      <= '0';
      ReadEeprom       <= '0';
      BurstReset       <= '0';
      OorReset         <= '0';

      if pFpgaDone = '1' then
        sys_command_reg(0) <= '0';

      elsif(IntLW_R = '1')then
        if(sys_enable(0) = '1') then   -- 0x00500000 check register
          check_register <= pLDin;
        end if;

        if(sys_enable(1) = '1') then   -- 0x00500004 system IO bank 0
          sys_io_bank0 <= pLDin;
        end if;

        if(sys_enable(2) = '1') then   -- 0x00500008 system IO bank 0 data direction register
          sys_io_bank0_ddr <= pLDin;
        end if;

        if(sys_enable(3) = '1')then    -- 0x0050000C system IO bank 1
          sys_io_bank1 <= pLDin(20 downto 0);
        end if;

        if(sys_enable(4) = '1') then   -- 0x00500010 system IO bank 1 data direction register
          sys_io_bank1_ddr <= pLDin(20 downto 0);
        end if;

        if(sys_enable(5) = '1') then   -- 0x00500014 system command register
          sys_command_reg <= pLDin and X"000001F9";
          WriteEeprom      <= pLDin(1);
          ReadEeprom       <= pLDin(2);
          OorReset         <= pLDin(9);
        end if;

        if(sys_enable(6) = '1') then   -- 0x00500018 System burst debug mode
          sys_debug_reg(0) <= pLDin(0);
          BurstReset <= '1';
        end if;

        if(sys_enable(7) = '1') then   -- 0x0050001C testy thingy
          sys_test_reg <= pLDin;
        end if;
      end if;
    end if;

  end process;

  -- Drive outputs with internal signals
  pWriteEeprom <= WriteEeprom;
  pReadEeprom  <= ReadEeprom;
  pSysIo0Out   <= sys_io_bank0;
  pSysIo0Dir   <= sys_io_bank0_ddr;
  pSysIo1Out   <= sys_io_bank1;
  pSysIo1Dir   <= sys_io_bank1_ddr;


  process(pnReset, pLCLKA)
  begin
    if pnReset = '0' then
      sys_status_reg(0) <= '0';
    elsif rising_edge(pLCLKA) then
      sys_status_reg(0) <= pFpgaProged;
    end if;
  end process;

  sys_status_reg(1) <= pEepromBusy;
  sys_status_reg(2) <= Intlholda;
  sys_status_reg(3) <= '0';  --BREQi;
  sys_status_reg(31 downto 4) <= (others => '0');

  --
  --  setup the start coditions for fpga programming and eeprom functions
  --
  process(sys_command_reg, local_bus_control)
  begin
    fpga_load_int <= '0';             -- default
    BREQi     <= '0';               -- default - lets PCI have the local bus

    if(sys_command_reg(0) = '1') then     -- detect command to program fpga
      BREQi <= '1';             -- request local bus control

      if(local_bus_control = '1') then  -- got local bus control
        fpga_load_int <= '1';         -- flag command to program fpga
      end if;
    end if;
  end process;

  pBREQi <= BREQi;


  -- Delay pFpgaLoad by 1 clock cycle
  process(pLCLKA)
  begin
    if rising_edge(pLCLKA) then
      pFpgaLoad <= fpga_load_int;
    end if;
  end process;

  --
  -- Generate register reads
  --
  process(pnReset, pLCLKA)
    variable vLAin7_2: std_logic_vector(5 downto 0);
  begin
    if pnReset = '0' then
      BlkRamData  <= X"00000000";
      RegReadData <= X"00000000";
    elsif rising_edge(pLCLKA) then
      BlkRamData <= pBlkRamDataOut;

      vLAin7_2 := IntAddr(7 downto 2);
      case vLAin7_2 is
        when "000000" =>
          RegReadData <= not check_register;
        when "000001" =>
          RegReadData <= pSysIo0In;
        when "000010" =>
          RegReadData <= sys_io_bank0_ddr;
        when "000011" =>
          RegReadData <= "00000000000" & pSysIo1In;
        when "000100" =>
          RegReadData <= "00000000000" & sys_io_bank1_ddr;
        when "000101" =>
          RegReadData <= sys_status_reg;
        when "000110" =>
          RegReadData <= (0 => sys_debug_reg(0), others => '0');
        when "000111" =>
          RegReadData <= sys_test_reg;
        when "001000" =>
          RegReadData <= std_logic_vector(sys_oor_count);
        when "111111" =>
          RegReadData <= X"0000" & cSysFpgaVer;
        when others =>
          RegReadData <= X"00000000";
      end case;
    end if;
  end process;


  --
  --  manage reads to local bus
  --
  process(pnReset, pLCLKA)
    variable vLAin7_2: std_logic_vector(5 downto 0);
  begin
    if pnReset = '0' then
--      pLDoutEn <= '0';
      BlockRamAccessQ <= '0';
    elsif rising_edge(pLCLKA) then
--      if pnBLAST = '0' and nReady = '0' then
--        -- Deassert data output enable at the end of a cycle
--        pLDoutEn <= '0';
--      elsif IntLW_R = '0' and (sys_reg_enable = '1' or BlockRamAccess = '1') then
--        -- Read access, assert data output enable
--        pLDoutEn <= '1';
--      end if;

      BlockRamAccessQ <= BlockRamAccess;
    end if;
  end process;

  process(BlockRamAccessQ, BlkRamData, RegReadData)
  begin
    pLDout <= (others => '0');

    if BlockRamAccessQ = '1' then
      pLDout <= BlkRamData;
    else
      pLDout <= RegReadData;
    end if;
  end process;


  -- ****************************************************************
  -- address decodes...
  -- ****************************************************************
--  process(IntAddr, IntAddrValid, sys_command_reg)
--  begin
      -- defaults
--      sys_reg_enable <= '0';  -- disable system register access
--      BlockRamAccess <= '0';
--      nDspFpgaCs <= '1';
--      nPerFpgaCs <= '1';

--      if IntAddrValid = '1' then
--        case IntAddr(31 downto 20) is
--          when X"000" | X"001" | X"002" | X"003" =>   -- Sample  enable
--            nDspFpgaCs <= '0';
--          when X"004" =>            -- System RAM enable
--          when X"005" =>            -- registers
--            case IntAddr(19 downto 8) is
--              when X"000" =>
--                sys_reg_enable <= '1';            -- Enable system register access
--              when X"001" =>
--                sys_reg_enable <= '1';            -- Enable system register access
--              when X"002" =>
--                nDspFpgaCs <= '0';  -- DSP FPGA registers
--              when X"003" =>
--                nDspFpgaCs <= '0';  -- DSP FPGA registers
--              when X"004" =>
--                nPerFpgaCs <= '0';  -- Peripheral FPGA registers
--              when others =>
--                null;
--            end case;
--          when X"006" =>  -- EEPROM Block RAM
--            if IntAddr(19 downto 8) = "000000000000" then
----              BlockRamAccess <= '1';
--            end if;
--
--          when others =>
--            null;
--      end case;
--    end if;
--  end process;

---  nDspFpgaCs <= '1';  -- Temp
--  nPerFpgaCs <= '1';  -- Temp
  pnDspFpgaCs <= "111" & nDspFpgaCs;  --(not sys_command_reg(7 downto 4)) when (nDspFpgaCs = '0' and not(pnBLAST = '0' and nReady = '0')) else (others => '1');
  pnPerFpgaCs <= "111" & nPerFpgaCs;  --(not sys_command_reg(7 downto 4)) when (nPerFpgaCs = '0' and not(pnBLAST = '0' and nReady = '0')) else (others => '1');
  pWhatFpga <= not sys_command_reg(7 downto 4);


  -- system register address decodes
  process(IntAddr, sys_reg_enable)
  begin
    sys_enable <= (others => '0');
    sys_enable_any <= '0';

    if (sys_reg_enable = '1') then
      case IntAddr(7 downto 2) is
        when "000000" =>           -- 0x00500000 check register
          sys_enable(0)  <= '1';
          sys_enable_any <= '1';
        when "000001" =>           -- 0x00500004 system IO bank 0
          sys_enable(1) <= '1';
          sys_enable_any <= '1';
        when "000010" =>           -- 0x00500008 system IO bank 0 DDR
          sys_enable(2) <= '1';
          sys_enable_any <= '1';
        when "000011" =>           -- 0x0050000C system IO bank 1
          sys_enable(3) <= '1';
          sys_enable_any <= '1';
        when "000100" =>           -- 0x00500010 system IO bank 1 DDR
          sys_enable(4) <= '1';
          sys_enable_any <= '1';
        when "000101" =>           -- 0x00500014 system command / status register
          sys_enable(5) <= '1';
          sys_enable_any <= '1';
        when "000110" =>           -- 0x00500018 spare
          sys_enable(6) <= '1';
          sys_enable_any <= '1';
        when "000111" =>
          sys_enable(7) <= '1';   -- 0x0050001C test jobbie
          sys_enable_any <= '1';
        when "001000" =>
          sys_enable(8) <= '1';   -- 0x00500020 out of range access count
          sys_enable_any <= '1';
        when others =>
          null;
      end case;
    end if;
  end process;


  --******************************************************************
  -- local bus state machine
  -- handles handshaking required by PLX chip for assorted PCI modes
  --******************************************************************
  pnBTERM  <= '1';  -- We never terminate bursts - maybe we should in some circumstances...
  pCCS     <= '1';  -- basically enables local bus - actually disables local bus PLX configuration mode

  CtrlFSM: process(pnReset, pLCLKA)
    variable vSampleRamAddr: std_ulogic;
    variable vSysRamAddr:    std_ulogic;
    variable vSysFpgaAddr:   std_ulogic;
    variable vDspFpgaAddr:   std_ulogic;
    variable vPerFpgaAddr:   std_ulogic;
    variable vBlockRamAddr:  std_ulogic;
    variable vValidAccess: std_ulogic;
  begin
    if pnReset = '0' then
      CtrlState  <= sIdle;
      IncAddress <= '0';
      nSysRamCS  <= '1';
      nSysRamWE  <= '1';
      nSysRamOE  <= '1';
      BlockRamAccess <= '0';
      sys_reg_enable <= '0';
      pLDoutEn       <= '0';
      nPerFpgaCs     <= '1';
      nDspFpgaCs     <= '1';
      pTest          <= '1';
      nReady         <= '1';
      BurstInc       <= '0';
      BurstZero      <= '1';
      BurstCount     <= 0;
      BurstAddr      <= "000000";
      BurstWrite     <= '0';
      sys_oor_count  <= (others => '0');

    elsif rising_edge(pLCLKA) then
      nReady     <= '1';
      IncAddress <= '0';
      nSysRamCS  <= not local_bus_control;  -- System SRAM is in read mode during FPGA programming
      nSysRamWE  <= '1';
      nSysRamOE  <= not local_bus_control;  -- System SRAM is in read mode during FPGA programming
      BlockRamAccess <= '0';
      sys_reg_enable <= '0';
      pLDoutEn       <= '0';
      nDspFpgaCs     <= pnDspFpgaProg(0);
      nPerFpgaCs     <= pnPerFpgaProg(0);
      BurstInc       <= '0';
      BurstWrite     <= '0';

      -- Decode addresses for use in control state machine
      vSampleRamAddr := '0';
      vSysRamAddr    := '0';
      vSysFpgaAddr   := '0';
      vDspFpgaAddr   := '0';
      vPerFpgaAddr   := '0';
      vBlockRamAddr  := '0';
      case IntAddr(31 downto 20) is
        when X"000" | X"001" | X"002" | X"003" =>  -- Sample RAM address
          vSampleRamAddr := '1';
        when X"004" =>  -- System RAM address
          vSysRamAddr := '1';

        when X"005" =>  -- FPGA Adresses
          case IntAddr(19 downto 8) is
            when X"000" =>  -- System FPGA address
              vSysFpgaAddr := '1';
            when X"002" =>  -- DSP FPGA address
              vDspFpgaAddr := '1';
            when X"004" =>  -- Peripheral FPFA address
              vPerFpgaAddr := '1';
            when others => null;
          end case;

        when X"006" =>  -- EEPROM Block RAM address
          vBlockRamAddr := '1';

        when others => null;
      end case;

      if OorReset = '1' then
        sys_oor_count  <= (others => '0');
      end if;

      -- Actual code for main control FSM
      case CtrlState is
        when sIdle =>
          if pnADS = '0' and Intlholda = '1' then  -- Start of transaction
            CtrlState <= sDelay1;
          end if;

        when sDelay1 =>
          if vSampleRamAddr = '1' then
            CtrlState <= sSampleDelay1;
          else
            CtrlState <= sDelay2;
          end if;

        when sSampleDelay1 =>
          CtrlState <= sSampleDelay2;
          nDspFpgaCs <= '0';

        when sSampleDelay2 =>
          CtrlState <= sDelay2;
          nDspFpgaCs <= '0';

        when sDelay2 =>
          vValidAccess := '0';
          CtrlState <= sDoAccess;
          if pnBLAST = '1' then
            -- Burst access, increment address
            IncAddress <= '1';
          end if;
          if vSysRamAddr = '1' then
            nSysRamCS <= '0';
            if IntLW_R = '1' then
              nSysRamWE <= '0';
            else
              nSysRamOE <= '0';
            end if;
            vValidAccess := '1';
          end if;
          if vSysFpgaAddr = '1' then
            sys_reg_enable <= '1';
            vValidAccess := '1';
          end if;
          if vDspFpgaAddr = '1' or vSampleRamAddr = '1' then
            nDspFpgaCs <= '0';
            vValidAccess := '1';
          end if;
          if vPerFpgaAddr = '1' then
            nPerFpgaCs <= '0';
            vValidAccess := '1';
          end if;
          if vBlockRamAddr = '1' then
            BlockRamAccess <= '1';
            vValidAccess := '1';
          end if;
          if IntLW_R = '0' then
            if vSysFpgaAddr = '1' or BlockRamAccess = '1' then
              pLDoutEn       <= '1';  -- Read from this FPGA - drive data lines
            end if;
          end if;

        when sDoAccess =>
          if pnBLAST = '0' then
            CtrlState <= sIdle;
            if BurstZero = '0' then
              -- The burst count is not zero, write value to BlockRAM
              BurstWrite <= '1';
            end if;
          else
            pTest <= '0';  -- Turn on LED when burst access happens
            CtrlState <= sDelay2;
            BurstInc  <= '1';  -- Increment the burst count
            BurstZero <= '0';
          end if;
          if vSysRamAddr = '1' then
            nSysRamCS <= '0';
            if IntLW_R /= '1' then
              nSysRamOE <= '0';
            end if;
          end if;
          if vSysFpgaAddr = '1' then
            sys_reg_enable <= '1';
          end if;
          if vDspFpgaAddr = '1' or vSampleRamAddr = '1' then
            nDspFpgaCs <= '0';
          end if;
          if vPerFpgaAddr = '1' then
            nPerFpgaCs <= '0';
          end if;
          if IntLW_R = '0' then
            if vSysFpgaAddr = '1' or BlockRamAccess = '1' then
              pLDoutEn     <= '1';  -- Read from this FPGA - drive data lines
            end if;
        end if;
        if vValidAccess = '0' then
          sys_oor_count <= sys_oor_count + 1;
        end if;
        if vValidAccess = '1' or sys_command_reg(8) = '0' then
          nReady <= '0';
        end if;
      end case;

      -- Form the address counter
      if BurstReset = '1' then
        BurstZero      <= '1';
        BurstAddr      <= "000000";
      elsif BurstWrite = '1' then
        BurstZero      <= '1';
        if BurstAddr /= "111111" then
          BurstAddr <= unsigned(BurstAddr) + 1;
        end if;
      end if;

      -- Form the actual burst length counter
      if BurstReset = '1' or BurstWrite = '1' then
        BurstCount <= 0;
      elsif BurstInc = '1' then
        if BurstCount /= cBurstCountMax then
          BurstCount <= BurstCount + 1;
        end if;
      end if;

    end if;
  end process CtrlFSM;

  -- Drive Sytem SRAM control signals
  pnSysRamCS <= nSysRamCS;
  pnSysRamOE <= nSysRamOE;
  pnSysRamWE <= nSysRamWE;

--          when X"005" =>            -- registers
--            case IntAddr(19 downto 8) is
--              when X"000" =>



  -- bus arbitration
  -- to get local bus...
  -- assert BREQi wait for lholda to fall
  process(pLCLKA)
  begin
    if rising_edge(pLCLKA) then
      if local_bus_control = '0' then
        Intlholda <= pLHOLD;          -- ack bus owner
      else
        -- Do not hand over control of the bus
        Intlholda <= '0';
      end if;

      if(BREQi = '0') then        -- PCI can have the bus
        local_bus_control <= '0';   -- flag PCI bus control
      elsif(BREQi = '1') then       -- local bus request
        if(pLHOLD = '0') then        -- PCI relinquished bus
          local_bus_control <= '1'; -- flag local bus control
        end if;
      end if;

    end if;
  end process;

  pLHOLDA <= Intlholda;



end Behavioral;
