---------------------------------------------------------------------------
-- NDT Solutions Ltd. Proprietary Information
-- Company Confidential
-- Copyright 2005
--
-- Filename: SysControl.vhd
-- Language: VHDL '93
-- Project:  Pulse Receive Card System FPGA
--
-- Design Description:
-- Central Control Block for Pulser Receiver Card (PRx) System FPGA
--
---------------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;

entity SysControl is
  port(
    pnReset     : in  std_ulogic;           -- Active low reset
    pClock      : in  std_ulogic;           -- System Clock 
    pnWE        : in  std_ulogic;           -- Write Enable
    pnCECmd     : in  std_ulogic;           -- Chip Enable - Command register
    pnCEGlb     : in  std_ulogic;           -- Chip Enable - global config register
    pHOLDA      : in  std_ulogic;           -- Bus hold acknowledge from arbiter
    pSRxD       : in  std_ulogic;           -- Serial receive 
    pEEBusy     : in  std_ulogic;
    pDataIn     : in  std_logic_vector(31 downto 0);  -- Data input port
    pStatusDOut : out std_logic_vector(31 downto 0);  -- Status register data output
    pGlobDOut   : out std_logic_vector(31 downto 0);  -- Global Config register data output
    pAddress    : out std_logic_vector(31 downto 2);  -- Address bus
	  pDPRAMIn    : in  std_logic_vector(31 downto 0);  -- Data input from DPRAM
    pSTxD       : out std_ulogic;           -- Serial transmit
    pCtrlRst    : out std_ulogic;           -- Control FPGA reset
    pEERead     : out std_ulogic;
    pEEWrite    : out std_ulogic);
end SysControl;

architecture RTL of SysControl is

  component SysKCPSM
    port (
      port_id      : out std_logic_vector(7 downto 0);
      write_strobe : out std_ulogic;
      read_strobe  : out std_ulogic;
      out_port     : out std_logic_vector(7 downto 0);
      in_port      : in  std_logic_vector(7 downto 0);
      interrupt    : in  std_ulogic;
      reset        : in  std_ulogic;
      clk          : in  std_ulogic);
  end component;
  
  component UAT
    port (
      pClock   : in  std_ulogic;
      pnReset  : in  std_ulogic;
      pWE      : in  std_ulogic;
      pPAD     : in  std_logic_vector(7 downto 0);
      pDataIn  : in  std_logic_vector(7 downto 0);
      pTxD     : out std_ulogic;
      pDataOut : out std_logic_vector(7 downto 0));
  end component;

  component UAR
    port (
      pClock   : in  std_ulogic;
      pnReset  : in  std_ulogic;
      pOE      : in  std_ulogic;
      pPAD     : in  std_logic_vector(7 downto 0);
      pRxD     : in  std_ulogic;
      pDataOut : out std_logic_vector(7 downto 0));
  end component;
  
  component OutPort32
    port (
      pClock   : in  std_ulogic;
      pnReset  : in  std_ulogic;
      pWE      : in  std_ulogic;
      pDataIn  : in  std_logic_vector(7 downto 0);
      pPAD     : in  std_logic_vector(7 downto 0);
      pDataOut : out std_logic_vector(31 downto 0);
      pSyncSet : in  std_logic_vector(31 downto 0));
  end component;
  
  component InPort32
    generic(
      gBase    : std_logic_vector(7 downto 0) := x"20");
    port (
      pClock   : in  std_ulogic;
      pnReset  : in  std_ulogic;
      pnWE     : in  std_ulogic;
      pPAD     : in  std_logic_vector(7 downto 0);
      pDataIn  : in  std_logic_vector(31 downto 0);
      pDataOut : out std_logic_vector(31 downto 0);
      pDOut8   : out std_logic_vector(7 downto 0);
      pSyncClr : in  std_logic_vector(31 downto 0));
  end component;
  
  component DPRAMMux
    port(
    pPAD     : in  std_logic_vector(7 downto 0);
    pBE      : in  std_logic_vector(1 downto 0);
    pDataIn  : in  std_logic_vector(31 downto 0);
    pDataOut : out std_logic_vector(7 downto 0));
  end component;
  
  component BitIO
    port (
      pClock   : in  std_ulogic;
      pnReset  : in  std_ulogic;
      pPAD     : in  std_logic_vector(7 downto 0);
      pWE      : in  std_ulogic;
      pDataIn  : in  std_ulogic;
      pPortIn  : in  std_logic_vector(7 downto 0);
      pDataOut : out std_ulogic;
      pPortOut : out std_logic_vector(7 downto 0));
  end component;
  
  component AddressCounter
    port (
      pClock      : in  std_ulogic;
      pnReset     : in  std_ulogic;
      pWE         : in  std_ulogic;
      pDataIn     : in  std_logic_vector(7 downto 0);
      pPAD        : in  std_logic_vector(7 downto 0);
      pAddressOut : out std_logic_vector(31 downto 0));
  end component;
  
  signal PAD        : std_logic_vector(7 downto 0);
  signal uCDataIn   : std_logic_vector(7 downto 0);
  signal uCDataOut  : std_logic_vector(7 downto 0);
  signal DOut1      : std_logic_vector(7 downto 0);
  signal DOut2      : std_logic_vector(7 downto 0);
  signal DOut3      : std_logic_vector(7 downto 0);
  signal DOut4      : std_logic_vector(7 downto 0);
  signal DOut5      : std_logic_vector(7 downto 0);
  signal DOut6      : std_ulogic;
  signal Reset      : std_ulogic;
  signal WE         : std_ulogic;
  signal nWECmd     : std_ulogic;
  signal nWEGlb     : std_ulogic;
  signal OE         : std_ulogic;
  signal nInPortRST : std_ulogic;

  signal BitPortIn  : std_logic_vector(7 downto 0);
  signal BitPortOut : std_logic_vector(7 downto 0);
  signal AddressOut : std_logic_vector(31 downto 0);
  signal CtrlClr    : std_logic_vector(31 downto 0);
  signal StatusSet  : std_logic_vector(31 downto 0);

begin
  
  nWECmd   <= '0' when pnWE = '0' and pnCECmd = '0' else '1';
  nWEGlb   <= '0' when pnWE = '0' and pnCEGlb = '0' else '1';
  Reset    <= not pnReset;
  uCDataIn <= DOut1 or DOut2 or DOut3 or DOut4 or Dout5 or "0000000" & DOut6;

  pEERead  <= BitPortOut(0);
  pEEWrite <= BitPortOut(1);
  pCtrlRst <= BitPortOut(7);

  BitPortIn(1) <= pEEBusy;

  picoBlaze_1 : SysKCPSM
    port map (
      port_id      => PAD,
      write_strobe => WE,
      read_strobe  => OE,
      out_port     => uCDataOut,
      in_port      => uCDataIn,
      interrupt    => '0',
      reset        => Reset,
      clk          => pClock);

  UAT_1 : UAT
    port map (
      pClock   => pClock,
      pnReset  => pnReset,
      pWE      => WE,
      pPAD     => PAD,
      pDataIn  => uCDataOut,
      pTxD     => pSTxD,
      pDataOut => DOut1);

  UAR_1 : UAR
    port map (
      pClock   => pClock,
      pnReset  => pnReset,
      pOE      => OE,
      pPAD     => PAD,
      pRxD     => pSRxD,
      pDataOut => DOut2);

  StatusReg : OutPort32
    port map (
      pClock   => pClock,
      pnReset  => pnReset,
      pWE      => WE,
      pDataIn  => uCDataOut,
      pPAD     => PAD,
      pDataOut => pStatusDOut,
      pSyncSet => StatusSet);

  StatusSet(0) <= '0';
  StatusSet(1) <= '1' when nWECmd = '0' and (pDataIn(1) = '1' or pDataIn(2) = '1') else '0';
  StatusSet(2) <= '1' when nWECmd = '0' and pDataIn(3) = '1' else '0';
  StatusSet(31 downto 3) <= (others => '0');

  ControlReg : InPort32
	generic map (
	  gBase    => x"20")
    port map (
      pClock   => pClock,
      pnReset  => pnReset,
      pnWE     => nWECmd,
      pPAD     => PAD,
      pDataIn  => pDataIn,
      pDataOut => open,
      pDOut8   => Dout3,
      pSyncClr => CtrlClr);

  CtrlClr(0) <= '0';
  CtrlClr(1) <= BitPortOut(5); -- non-latching;
  CtrlClr(2) <= BitPortOut(5);
  CtrlClr(3) <= BitPortOut(6); -- non-latching;
  CtrlClr(4) <= BitPortOut(4); -- non-latching;
  ctrlClr(31 downto 5) <= (others => '0');

  GlobalConfReg : InPort32
    generic map (
      gBase    => x"28")
    port map (
      pClock   => pClock,
      pnReset  => pnReset,
      pnWE     => nWEGlb,
      pPAD     => PAD,
      pDataIn  => pDataIn,
      pDataOut => pGlobDOut,
      pDOut8   => Dout4,
      pSyncClr => (others => '0'));

  SeqTableMux : DPRAMMux
    port map (
      pPAD     => PAD,
      pBE      => AddressOut(1 downto 0),
      pDataIn  => pDPRAMIn,
      pDataOut => Dout5);

  BitIO_1 : BitIO
    port map (
      pClock   => pClock,
      pnReset  => pnReset,
      pPAD     => PAD,
      pWE      => WE,
      pDataIn  => uCDataOut(0),
      pPortIn  => BitPortIn,
      pDataOut => DOut6,
      pPortOut => BitPortOut);

  AddressCounter_1 : AddressCounter
    port map (
      pClock      => pClock,
      pnReset     => pnReset,
      pWE         => WE,
      pDataIn     => uCDataOut,
      pPAD        => PAD,
      pAddressOut => AddressOut);

  pAddress <= AddressOut(31 downto 2);

end architecture RTL;

